github.com/medzin/terraform@v0.11.11/config/raw_config_test.go (about)

     1  package config
     2  
     3  import (
     4  	"encoding/gob"
     5  	"reflect"
     6  	"testing"
     7  
     8  	hcl2 "github.com/hashicorp/hcl2/hcl"
     9  	"github.com/hashicorp/hil/ast"
    10  )
    11  
    12  func TestNewRawConfig(t *testing.T) {
    13  	raw := map[string]interface{}{
    14  		"foo": "${var.bar}",
    15  		"bar": `${file("boom.txt")}`,
    16  	}
    17  
    18  	rc, err := NewRawConfig(raw)
    19  	if err != nil {
    20  		t.Fatalf("err: %s", err)
    21  	}
    22  
    23  	if len(rc.Interpolations) != 2 {
    24  		t.Fatalf("bad: %#v", rc.Interpolations)
    25  	}
    26  	if len(rc.Variables) != 1 {
    27  		t.Fatalf("bad: %#v", rc.Variables)
    28  	}
    29  }
    30  
    31  func TestRawConfig_basic(t *testing.T) {
    32  	raw := map[string]interface{}{
    33  		"foo": "${var.bar}",
    34  	}
    35  
    36  	rc, err := NewRawConfig(raw)
    37  	if err != nil {
    38  		t.Fatalf("err: %s", err)
    39  	}
    40  
    41  	// Before interpolate, Config() should be the raw
    42  	if !reflect.DeepEqual(rc.Config(), raw) {
    43  		t.Fatalf("bad: %#v", rc.Config())
    44  	}
    45  
    46  	vars := map[string]ast.Variable{
    47  		"var.bar": ast.Variable{
    48  			Value: "baz",
    49  			Type:  ast.TypeString,
    50  		},
    51  	}
    52  	if err := rc.Interpolate(vars); err != nil {
    53  		t.Fatalf("err: %s", err)
    54  	}
    55  
    56  	actual := rc.Config()
    57  	expected := map[string]interface{}{
    58  		"foo": "baz",
    59  	}
    60  
    61  	if !reflect.DeepEqual(actual, expected) {
    62  		t.Fatalf("bad: %#v", actual)
    63  	}
    64  	if len(rc.UnknownKeys()) != 0 {
    65  		t.Fatalf("bad: %#v", rc.UnknownKeys())
    66  	}
    67  }
    68  
    69  func TestRawConfig_double(t *testing.T) {
    70  	raw := map[string]interface{}{
    71  		"foo": "${var.bar}",
    72  	}
    73  
    74  	rc, err := NewRawConfig(raw)
    75  	if err != nil {
    76  		t.Fatalf("err: %s", err)
    77  	}
    78  
    79  	vars := map[string]ast.Variable{
    80  		"var.bar": ast.Variable{
    81  			Value: "baz",
    82  			Type:  ast.TypeString,
    83  		},
    84  	}
    85  	if err := rc.Interpolate(vars); err != nil {
    86  		t.Fatalf("err: %s", err)
    87  	}
    88  
    89  	actual := rc.Config()
    90  	expected := map[string]interface{}{
    91  		"foo": "baz",
    92  	}
    93  
    94  	if !reflect.DeepEqual(actual, expected) {
    95  		t.Fatalf("bad: %#v", actual)
    96  	}
    97  
    98  	vars = map[string]ast.Variable{
    99  		"var.bar": ast.Variable{
   100  			Value: "what",
   101  			Type:  ast.TypeString,
   102  		},
   103  	}
   104  	if err := rc.Interpolate(vars); err != nil {
   105  		t.Fatalf("err: %s", err)
   106  	}
   107  
   108  	actual = rc.Config()
   109  	expected = map[string]interface{}{
   110  		"foo": "what",
   111  	}
   112  
   113  	if !reflect.DeepEqual(actual, expected) {
   114  		t.Fatalf("bad: %#v", actual)
   115  	}
   116  }
   117  
   118  func TestRawConfigInterpolate_escaped(t *testing.T) {
   119  	raw := map[string]interface{}{
   120  		"foo": "bar-$${baz}",
   121  	}
   122  
   123  	rc, err := NewRawConfig(raw)
   124  	if err != nil {
   125  		t.Fatalf("err: %s", err)
   126  	}
   127  
   128  	// Before interpolate, Config() should be the raw
   129  	if !reflect.DeepEqual(rc.Config(), raw) {
   130  		t.Fatalf("bad: %#v", rc.Config())
   131  	}
   132  
   133  	if err := rc.Interpolate(nil); err != nil {
   134  		t.Fatalf("err: %s", err)
   135  	}
   136  
   137  	actual := rc.Config()
   138  	expected := map[string]interface{}{
   139  		"foo": "bar-${baz}",
   140  	}
   141  
   142  	if !reflect.DeepEqual(actual, expected) {
   143  		t.Fatalf("bad: %#v", actual)
   144  	}
   145  	if len(rc.UnknownKeys()) != 0 {
   146  		t.Fatalf("bad: %#v", rc.UnknownKeys())
   147  	}
   148  }
   149  
   150  func TestRawConfig_merge(t *testing.T) {
   151  	raw1 := map[string]interface{}{
   152  		"foo": "${var.foo}",
   153  		"bar": "${var.bar}",
   154  	}
   155  
   156  	rc1, err := NewRawConfig(raw1)
   157  	if err != nil {
   158  		t.Fatalf("err: %s", err)
   159  	}
   160  
   161  	{
   162  		vars := map[string]ast.Variable{
   163  			"var.foo": ast.Variable{
   164  				Value: "foovalue",
   165  				Type:  ast.TypeString,
   166  			},
   167  			"var.bar": ast.Variable{
   168  				Value: "nope",
   169  				Type:  ast.TypeString,
   170  			},
   171  		}
   172  		if err := rc1.Interpolate(vars); err != nil {
   173  			t.Fatalf("err: %s", err)
   174  		}
   175  	}
   176  
   177  	raw2 := map[string]interface{}{
   178  		"bar": "${var.bar}",
   179  		"baz": "${var.baz}",
   180  	}
   181  
   182  	rc2, err := NewRawConfig(raw2)
   183  	if err != nil {
   184  		t.Fatalf("err: %s", err)
   185  	}
   186  
   187  	{
   188  		vars := map[string]ast.Variable{
   189  			"var.bar": ast.Variable{
   190  				Value: "barvalue",
   191  				Type:  ast.TypeString,
   192  			},
   193  			"var.baz": ast.Variable{
   194  				Value: UnknownVariableValue,
   195  				Type:  ast.TypeUnknown,
   196  			},
   197  		}
   198  		if err := rc2.Interpolate(vars); err != nil {
   199  			t.Fatalf("err: %s", err)
   200  		}
   201  	}
   202  
   203  	// Merge the two
   204  	rc3 := rc1.Merge(rc2)
   205  
   206  	// Raw should be merged
   207  	raw3 := map[string]interface{}{
   208  		"foo": "${var.foo}",
   209  		"bar": "${var.bar}",
   210  		"baz": "${var.baz}",
   211  	}
   212  	if !reflect.DeepEqual(rc3.Raw, raw3) {
   213  		t.Fatalf("bad: %#v", rc3.Raw)
   214  	}
   215  
   216  	actual := rc3.Config()
   217  	expected := map[string]interface{}{
   218  		"foo": "foovalue",
   219  		"bar": "barvalue",
   220  		"baz": UnknownVariableValue,
   221  	}
   222  	if !reflect.DeepEqual(actual, expected) {
   223  		t.Fatalf("bad: %#v", actual)
   224  	}
   225  
   226  	expectedKeys := []string{"baz"}
   227  	if !reflect.DeepEqual(rc3.UnknownKeys(), expectedKeys) {
   228  		t.Fatalf("bad: %#v", rc3.UnknownKeys())
   229  	}
   230  }
   231  
   232  func TestRawConfig_syntax(t *testing.T) {
   233  	raw := map[string]interface{}{
   234  		"foo": "${var",
   235  	}
   236  
   237  	if _, err := NewRawConfig(raw); err == nil {
   238  		t.Fatal("should error")
   239  	}
   240  }
   241  
   242  func TestRawConfig_unknown(t *testing.T) {
   243  	raw := map[string]interface{}{
   244  		"foo": "${var.bar}",
   245  	}
   246  
   247  	rc, err := NewRawConfig(raw)
   248  	if err != nil {
   249  		t.Fatalf("err: %s", err)
   250  	}
   251  
   252  	vars := map[string]ast.Variable{
   253  		"var.bar": ast.Variable{
   254  			Value: UnknownVariableValue,
   255  			Type:  ast.TypeUnknown,
   256  		},
   257  	}
   258  	if err := rc.Interpolate(vars); err != nil {
   259  		t.Fatalf("err: %s", err)
   260  	}
   261  
   262  	actual := rc.Config()
   263  	expected := map[string]interface{}{"foo": UnknownVariableValue}
   264  
   265  	if !reflect.DeepEqual(actual, expected) {
   266  		t.Fatalf("bad: %#v", actual)
   267  	}
   268  
   269  	expectedKeys := []string{"foo"}
   270  	if !reflect.DeepEqual(rc.UnknownKeys(), expectedKeys) {
   271  		t.Fatalf("bad: %#v", rc.UnknownKeys())
   272  	}
   273  }
   274  
   275  func TestRawConfig_unknownPartial(t *testing.T) {
   276  	raw := map[string]interface{}{
   277  		"foo": "${var.bar}/32",
   278  	}
   279  
   280  	rc, err := NewRawConfig(raw)
   281  	if err != nil {
   282  		t.Fatalf("err: %s", err)
   283  	}
   284  
   285  	vars := map[string]ast.Variable{
   286  		"var.bar": ast.Variable{
   287  			Value: UnknownVariableValue,
   288  			Type:  ast.TypeUnknown,
   289  		},
   290  	}
   291  	if err := rc.Interpolate(vars); err != nil {
   292  		t.Fatalf("err: %s", err)
   293  	}
   294  
   295  	actual := rc.Config()
   296  	expected := map[string]interface{}{"foo": UnknownVariableValue}
   297  
   298  	if !reflect.DeepEqual(actual, expected) {
   299  		t.Fatalf("bad: %#v", actual)
   300  	}
   301  
   302  	expectedKeys := []string{"foo"}
   303  	if !reflect.DeepEqual(rc.UnknownKeys(), expectedKeys) {
   304  		t.Fatalf("bad: %#v", rc.UnknownKeys())
   305  	}
   306  }
   307  
   308  func TestRawConfig_unknownPartialList(t *testing.T) {
   309  	raw := map[string]interface{}{
   310  		"foo": []interface{}{
   311  			"${var.bar}/32",
   312  		},
   313  	}
   314  
   315  	rc, err := NewRawConfig(raw)
   316  	if err != nil {
   317  		t.Fatalf("err: %s", err)
   318  	}
   319  
   320  	vars := map[string]ast.Variable{
   321  		"var.bar": ast.Variable{
   322  			Value: UnknownVariableValue,
   323  			Type:  ast.TypeUnknown,
   324  		},
   325  	}
   326  	if err := rc.Interpolate(vars); err != nil {
   327  		t.Fatalf("err: %s", err)
   328  	}
   329  
   330  	actual := rc.Config()
   331  	expected := map[string]interface{}{"foo": []interface{}{UnknownVariableValue}}
   332  
   333  	if !reflect.DeepEqual(actual, expected) {
   334  		t.Fatalf("bad: %#v", actual)
   335  	}
   336  
   337  	expectedKeys := []string{"foo"}
   338  	if !reflect.DeepEqual(rc.UnknownKeys(), expectedKeys) {
   339  		t.Fatalf("bad: %#v", rc.UnknownKeys())
   340  	}
   341  }
   342  
   343  // This tests a race found where we were not maintaining the "slice index"
   344  // accounting properly. The result would be that some computed keys would
   345  // look like they had no slice index when they in fact do. This test is not
   346  // very reliable but it did fail before the fix and passed after.
   347  func TestRawConfig_sliceIndexLoss(t *testing.T) {
   348  	raw := map[string]interface{}{
   349  		"slice": []map[string]interface{}{
   350  			map[string]interface{}{
   351  				"foo": []interface{}{"foo/${var.unknown}"},
   352  				"bar": []interface{}{"bar"},
   353  			},
   354  		},
   355  	}
   356  
   357  	vars := map[string]ast.Variable{
   358  		"var.unknown": ast.Variable{
   359  			Value: UnknownVariableValue,
   360  			Type:  ast.TypeUnknown,
   361  		},
   362  		"var.known": ast.Variable{
   363  			Value: "123456",
   364  			Type:  ast.TypeString,
   365  		},
   366  	}
   367  
   368  	// We run it a lot because its fast and we try to get a race out
   369  	for i := 0; i < 50; i++ {
   370  		rc, err := NewRawConfig(raw)
   371  		if err != nil {
   372  			t.Fatalf("err: %s", err)
   373  		}
   374  
   375  		if err := rc.Interpolate(vars); err != nil {
   376  			t.Fatalf("err: %s", err)
   377  		}
   378  
   379  		expectedKeys := []string{"slice.0.foo"}
   380  		if !reflect.DeepEqual(rc.UnknownKeys(), expectedKeys) {
   381  			t.Fatalf("bad: %#v", rc.UnknownKeys())
   382  		}
   383  	}
   384  }
   385  
   386  func TestRawConfigCopy(t *testing.T) {
   387  	raw := map[string]interface{}{
   388  		"foo": "${var.bar}",
   389  	}
   390  
   391  	rc, err := NewRawConfig(raw)
   392  	if err != nil {
   393  		t.Fatalf("err: %s", err)
   394  	}
   395  
   396  	rc.Key = "foo"
   397  	if rc.Value() != "${var.bar}" {
   398  		t.Fatalf("err: %#v", rc.Value())
   399  	}
   400  
   401  	// Interpolate the first one
   402  	vars := map[string]ast.Variable{
   403  		"var.bar": ast.Variable{
   404  			Value: "baz",
   405  			Type:  ast.TypeString,
   406  		},
   407  	}
   408  	if err := rc.Interpolate(vars); err != nil {
   409  		t.Fatalf("err: %s", err)
   410  	}
   411  
   412  	if rc.Value() != "baz" {
   413  		t.Fatalf("bad: %#v", rc.Value())
   414  	}
   415  
   416  	// Copy and interpolate
   417  	{
   418  		rc2 := rc.Copy()
   419  		if rc2.Value() != "${var.bar}" {
   420  			t.Fatalf("err: %#v", rc2.Value())
   421  		}
   422  
   423  		vars := map[string]ast.Variable{
   424  			"var.bar": ast.Variable{
   425  				Value: "qux",
   426  				Type:  ast.TypeString,
   427  			},
   428  		}
   429  		if err := rc2.Interpolate(vars); err != nil {
   430  			t.Fatalf("err: %s", err)
   431  		}
   432  
   433  		if rc2.Value() != "qux" {
   434  			t.Fatalf("bad: %#v", rc2.Value())
   435  		}
   436  	}
   437  }
   438  
   439  func TestRawConfigCopyHCL2(t *testing.T) {
   440  	rc := NewRawConfigHCL2(hcl2.EmptyBody())
   441  	rc2 := rc.Copy()
   442  
   443  	if rc.Body == nil {
   444  		t.Errorf("RawConfig copy has a nil Body")
   445  	}
   446  	if rc2.Raw != nil {
   447  		t.Errorf("RawConfig copy got a non-nil Raw")
   448  	}
   449  }
   450  
   451  func TestRawConfigValue(t *testing.T) {
   452  	raw := map[string]interface{}{
   453  		"foo": "${var.bar}",
   454  	}
   455  
   456  	rc, err := NewRawConfig(raw)
   457  	if err != nil {
   458  		t.Fatalf("err: %s", err)
   459  	}
   460  
   461  	rc.Key = ""
   462  	if rc.Value() != nil {
   463  		t.Fatalf("bad: %#v", rc.Value())
   464  	}
   465  
   466  	rc.Key = "foo"
   467  	if rc.Value() != "${var.bar}" {
   468  		t.Fatalf("err: %#v", rc.Value())
   469  	}
   470  
   471  	vars := map[string]ast.Variable{
   472  		"var.bar": ast.Variable{
   473  			Value: "baz",
   474  			Type:  ast.TypeString,
   475  		},
   476  	}
   477  	if err := rc.Interpolate(vars); err != nil {
   478  		t.Fatalf("err: %s", err)
   479  	}
   480  
   481  	if rc.Value() != "baz" {
   482  		t.Fatalf("bad: %#v", rc.Value())
   483  	}
   484  }
   485  
   486  func TestRawConfig_implGob(t *testing.T) {
   487  	var _ gob.GobDecoder = new(RawConfig)
   488  	var _ gob.GobEncoder = new(RawConfig)
   489  }
   490  
   491  // verify that RawMap returns a identical copy
   492  func TestNewRawConfig_rawMap(t *testing.T) {
   493  	raw := map[string]interface{}{
   494  		"foo": "${var.bar}",
   495  		"bar": `${file("boom.txt")}`,
   496  	}
   497  
   498  	rc, err := NewRawConfig(raw)
   499  	if err != nil {
   500  		t.Fatalf("err: %s", err)
   501  	}
   502  
   503  	rawCopy := rc.RawMap()
   504  	if !reflect.DeepEqual(raw, rawCopy) {
   505  		t.Fatalf("bad: %#v", rawCopy)
   506  	}
   507  
   508  	// make sure they aren't the same map
   509  	raw["test"] = "value"
   510  	if reflect.DeepEqual(raw, rawCopy) {
   511  		t.Fatal("RawMap() didn't return a copy")
   512  	}
   513  }