github.com/grange74/terraform@v0.7.0-rc3.0.20160722171430-8c8803864753/config/loader_test.go (about)

     1  package config
     2  
     3  import (
     4  	"io/ioutil"
     5  	"path/filepath"
     6  	"reflect"
     7  	"strings"
     8  	"testing"
     9  )
    10  
    11  func TestIsEmptyDir(t *testing.T) {
    12  	val, err := IsEmptyDir(fixtureDir)
    13  	if err != nil {
    14  		t.Fatalf("err: %s", err)
    15  	}
    16  	if val {
    17  		t.Fatal("should not be empty")
    18  	}
    19  }
    20  
    21  func TestIsEmptyDir_noExist(t *testing.T) {
    22  	val, err := IsEmptyDir(filepath.Join(fixtureDir, "nopenopenope"))
    23  	if err != nil {
    24  		t.Fatalf("err: %s", err)
    25  	}
    26  	if !val {
    27  		t.Fatal("should be empty")
    28  	}
    29  }
    30  
    31  func TestIsEmptyDir_noConfigs(t *testing.T) {
    32  	val, err := IsEmptyDir(filepath.Join(fixtureDir, "dir-empty"))
    33  	if err != nil {
    34  		t.Fatalf("err: %s", err)
    35  	}
    36  	if !val {
    37  		t.Fatal("should be empty")
    38  	}
    39  }
    40  
    41  func TestLoadFile_badType(t *testing.T) {
    42  	_, err := LoadFile(filepath.Join(fixtureDir, "bad_type.tf.nope"))
    43  	if err == nil {
    44  		t.Fatal("should have error")
    45  	}
    46  }
    47  
    48  func TestLoadFile_lifecycleKeyCheck(t *testing.T) {
    49  	_, err := LoadFile(filepath.Join(fixtureDir, "lifecycle_cbd_typo.tf"))
    50  	if err == nil {
    51  		t.Fatal("should have error")
    52  	}
    53  
    54  	t.Logf("err: %s", err)
    55  }
    56  
    57  func TestLoadFile_resourceArityMistake(t *testing.T) {
    58  	_, err := LoadFile(filepath.Join(fixtureDir, "resource-arity-mistake.tf"))
    59  	if err == nil {
    60  		t.Fatal("should have error")
    61  	}
    62  	expected := "Error loading test-fixtures/resource-arity-mistake.tf: position 2:10: resource must be followed by exactly two strings, a type and a name"
    63  	if err.Error() != expected {
    64  		t.Fatalf("expected:\n%s\ngot:\n%s", expected, err)
    65  	}
    66  }
    67  
    68  func TestLoadFile_dataSourceArityMistake(t *testing.T) {
    69  	_, err := LoadFile(filepath.Join(fixtureDir, "data-source-arity-mistake.tf"))
    70  	if err == nil {
    71  		t.Fatal("should have error")
    72  	}
    73  	expected := "Error loading test-fixtures/data-source-arity-mistake.tf: position 2:6: 'data' must be followed by exactly two strings: a type and a name"
    74  	if err.Error() != expected {
    75  		t.Fatalf("expected:\n%s\ngot:\n%s", expected, err)
    76  	}
    77  }
    78  
    79  func TestLoadFileWindowsLineEndings(t *testing.T) {
    80  	testFile := filepath.Join(fixtureDir, "windows-line-endings.tf")
    81  
    82  	contents, err := ioutil.ReadFile(testFile)
    83  	if err != nil {
    84  		t.Fatalf("err: %s", err)
    85  	}
    86  	if !strings.Contains(string(contents), "\r\n") {
    87  		t.Fatalf("Windows line endings test file %s contains no windows line endings - this may be an autocrlf related issue.", testFile)
    88  	}
    89  
    90  	c, err := LoadFile(testFile)
    91  	if err != nil {
    92  		t.Fatalf("err: %s", err)
    93  	}
    94  
    95  	if c == nil {
    96  		t.Fatal("config should not be nil")
    97  	}
    98  
    99  	if c.Dir != "" {
   100  		t.Fatalf("bad: %#v", c.Dir)
   101  	}
   102  
   103  	actual := resourcesStr(c.Resources)
   104  	if actual != strings.TrimSpace(windowsHeredocResourcesStr) {
   105  		t.Fatalf("bad:\n%s", actual)
   106  	}
   107  }
   108  
   109  func TestLoadFileHeredoc(t *testing.T) {
   110  	c, err := LoadFile(filepath.Join(fixtureDir, "heredoc.tf"))
   111  	if err != nil {
   112  		t.Fatalf("err: %s", err)
   113  	}
   114  
   115  	if c == nil {
   116  		t.Fatal("config should not be nil")
   117  	}
   118  
   119  	if c.Dir != "" {
   120  		t.Fatalf("bad: %#v", c.Dir)
   121  	}
   122  
   123  	actual := providerConfigsStr(c.ProviderConfigs)
   124  	if actual != strings.TrimSpace(heredocProvidersStr) {
   125  		t.Fatalf("bad:\n%s", actual)
   126  	}
   127  
   128  	actual = resourcesStr(c.Resources)
   129  	if actual != strings.TrimSpace(heredocResourcesStr) {
   130  		t.Fatalf("bad:\n%s", actual)
   131  	}
   132  }
   133  
   134  func TestLoadFileEscapedQuotes(t *testing.T) {
   135  	_, err := LoadFile(filepath.Join(fixtureDir, "escapedquotes.tf"))
   136  	if err == nil {
   137  		t.Fatalf("expected syntax error as escaped quotes are no longer supported")
   138  	}
   139  
   140  	if !strings.Contains(err.Error(), "syntax error") {
   141  		t.Fatalf("expected \"syntax error\", got: %s", err)
   142  	}
   143  }
   144  
   145  func TestLoadFileBasic(t *testing.T) {
   146  	c, err := LoadFile(filepath.Join(fixtureDir, "basic.tf"))
   147  	if err != nil {
   148  		t.Fatalf("err: %s", err)
   149  	}
   150  
   151  	if c == nil {
   152  		t.Fatal("config should not be nil")
   153  	}
   154  
   155  	if c.Dir != "" {
   156  		t.Fatalf("bad: %#v", c.Dir)
   157  	}
   158  
   159  	expectedAtlas := &AtlasConfig{Name: "mitchellh/foo"}
   160  	if !reflect.DeepEqual(c.Atlas, expectedAtlas) {
   161  		t.Fatalf("bad: %#v", c.Atlas)
   162  	}
   163  
   164  	actual := variablesStr(c.Variables)
   165  	if actual != strings.TrimSpace(basicVariablesStr) {
   166  		t.Fatalf("bad:\n%s", actual)
   167  	}
   168  
   169  	actual = providerConfigsStr(c.ProviderConfigs)
   170  	if actual != strings.TrimSpace(basicProvidersStr) {
   171  		t.Fatalf("bad:\n%s", actual)
   172  	}
   173  
   174  	actual = resourcesStr(c.Resources)
   175  	if actual != strings.TrimSpace(basicResourcesStr) {
   176  		t.Fatalf("bad:\n%s", actual)
   177  	}
   178  
   179  	actual = outputsStr(c.Outputs)
   180  	if actual != strings.TrimSpace(basicOutputsStr) {
   181  		t.Fatalf("bad:\n%s", actual)
   182  	}
   183  }
   184  
   185  func TestLoadFileBasic_empty(t *testing.T) {
   186  	c, err := LoadFile(filepath.Join(fixtureDir, "empty.tf"))
   187  	if err != nil {
   188  		t.Fatalf("err: %s", err)
   189  	}
   190  
   191  	if c == nil {
   192  		t.Fatal("config should not be nil")
   193  	}
   194  }
   195  
   196  func TestLoadFileBasic_import(t *testing.T) {
   197  	// Skip because we disabled importing
   198  	t.Skip()
   199  
   200  	c, err := LoadFile(filepath.Join(fixtureDir, "import.tf"))
   201  	if err != nil {
   202  		t.Fatalf("err: %s", err)
   203  	}
   204  
   205  	if c == nil {
   206  		t.Fatal("config should not be nil")
   207  	}
   208  
   209  	actual := variablesStr(c.Variables)
   210  	if actual != strings.TrimSpace(importVariablesStr) {
   211  		t.Fatalf("bad:\n%s", actual)
   212  	}
   213  
   214  	actual = providerConfigsStr(c.ProviderConfigs)
   215  	if actual != strings.TrimSpace(importProvidersStr) {
   216  		t.Fatalf("bad:\n%s", actual)
   217  	}
   218  
   219  	actual = resourcesStr(c.Resources)
   220  	if actual != strings.TrimSpace(importResourcesStr) {
   221  		t.Fatalf("bad:\n%s", actual)
   222  	}
   223  }
   224  
   225  func TestLoadFileBasic_json(t *testing.T) {
   226  	c, err := LoadFile(filepath.Join(fixtureDir, "basic.tf.json"))
   227  	if err != nil {
   228  		t.Fatalf("err: %s", err)
   229  	}
   230  
   231  	if c == nil {
   232  		t.Fatal("config should not be nil")
   233  	}
   234  
   235  	if c.Dir != "" {
   236  		t.Fatalf("bad: %#v", c.Dir)
   237  	}
   238  
   239  	expectedAtlas := &AtlasConfig{Name: "mitchellh/foo"}
   240  	if !reflect.DeepEqual(c.Atlas, expectedAtlas) {
   241  		t.Fatalf("bad: %#v", c.Atlas)
   242  	}
   243  
   244  	actual := variablesStr(c.Variables)
   245  	if actual != strings.TrimSpace(basicVariablesStr) {
   246  		t.Fatalf("bad:\n%s", actual)
   247  	}
   248  
   249  	actual = providerConfigsStr(c.ProviderConfigs)
   250  	if actual != strings.TrimSpace(basicProvidersStr) {
   251  		t.Fatalf("bad:\n%s", actual)
   252  	}
   253  
   254  	actual = resourcesStr(c.Resources)
   255  	if actual != strings.TrimSpace(basicResourcesStr) {
   256  		t.Fatalf("bad:\n%s", actual)
   257  	}
   258  
   259  	actual = outputsStr(c.Outputs)
   260  	if actual != strings.TrimSpace(basicOutputsStr) {
   261  		t.Fatalf("bad:\n%s", actual)
   262  	}
   263  }
   264  
   265  func TestLoadFileBasic_modules(t *testing.T) {
   266  	c, err := LoadFile(filepath.Join(fixtureDir, "modules.tf"))
   267  	if err != nil {
   268  		t.Fatalf("err: %s", err)
   269  	}
   270  
   271  	if c == nil {
   272  		t.Fatal("config should not be nil")
   273  	}
   274  
   275  	if c.Dir != "" {
   276  		t.Fatalf("bad: %#v", c.Dir)
   277  	}
   278  
   279  	actual := modulesStr(c.Modules)
   280  	if actual != strings.TrimSpace(modulesModulesStr) {
   281  		t.Fatalf("bad:\n%s", actual)
   282  	}
   283  }
   284  
   285  func TestLoadJSONBasic(t *testing.T) {
   286  	raw, err := ioutil.ReadFile(filepath.Join(fixtureDir, "basic.tf.json"))
   287  	if err != nil {
   288  		t.Fatalf("err: %s", err)
   289  	}
   290  
   291  	c, err := LoadJSON(raw)
   292  	if err != nil {
   293  		t.Fatalf("err: %s", err)
   294  	}
   295  
   296  	if c == nil {
   297  		t.Fatal("config should not be nil")
   298  	}
   299  
   300  	if c.Dir != "" {
   301  		t.Fatalf("bad: %#v", c.Dir)
   302  	}
   303  
   304  	expectedAtlas := &AtlasConfig{Name: "mitchellh/foo"}
   305  	if !reflect.DeepEqual(c.Atlas, expectedAtlas) {
   306  		t.Fatalf("bad: %#v", c.Atlas)
   307  	}
   308  
   309  	actual := variablesStr(c.Variables)
   310  	if actual != strings.TrimSpace(basicVariablesStr) {
   311  		t.Fatalf("bad:\n%s", actual)
   312  	}
   313  
   314  	actual = providerConfigsStr(c.ProviderConfigs)
   315  	if actual != strings.TrimSpace(basicProvidersStr) {
   316  		t.Fatalf("bad:\n%s", actual)
   317  	}
   318  
   319  	actual = resourcesStr(c.Resources)
   320  	if actual != strings.TrimSpace(basicResourcesStr) {
   321  		t.Fatalf("bad:\n%s", actual)
   322  	}
   323  
   324  	actual = outputsStr(c.Outputs)
   325  	if actual != strings.TrimSpace(basicOutputsStr) {
   326  		t.Fatalf("bad:\n%s", actual)
   327  	}
   328  }
   329  
   330  func TestLoadFile_variables(t *testing.T) {
   331  	c, err := LoadFile(filepath.Join(fixtureDir, "variables.tf"))
   332  	if err != nil {
   333  		t.Fatalf("err: %s", err)
   334  	}
   335  	if c == nil {
   336  		t.Fatal("config should not be nil")
   337  	}
   338  
   339  	if c.Dir != "" {
   340  		t.Fatalf("bad: %#v", c.Dir)
   341  	}
   342  
   343  	actual := variablesStr(c.Variables)
   344  	if actual != strings.TrimSpace(variablesVariablesStr) {
   345  		t.Fatalf("bad:\n%s", actual)
   346  	}
   347  }
   348  
   349  func TestLoadDir_basic(t *testing.T) {
   350  	dir := filepath.Join(fixtureDir, "dir-basic")
   351  	c, err := LoadDir(dir)
   352  	if err != nil {
   353  		t.Fatalf("err: %s", err)
   354  	}
   355  
   356  	if c == nil {
   357  		t.Fatal("config should not be nil")
   358  	}
   359  
   360  	dirAbs, err := filepath.Abs(dir)
   361  	if err != nil {
   362  		t.Fatalf("err: %s", err)
   363  	}
   364  	if c.Dir != dirAbs {
   365  		t.Fatalf("bad: %#v", c.Dir)
   366  	}
   367  
   368  	actual := variablesStr(c.Variables)
   369  	if actual != strings.TrimSpace(dirBasicVariablesStr) {
   370  		t.Fatalf("bad:\n%s", actual)
   371  	}
   372  
   373  	actual = providerConfigsStr(c.ProviderConfigs)
   374  	if actual != strings.TrimSpace(dirBasicProvidersStr) {
   375  		t.Fatalf("bad:\n%s", actual)
   376  	}
   377  
   378  	actual = resourcesStr(c.Resources)
   379  	if actual != strings.TrimSpace(dirBasicResourcesStr) {
   380  		t.Fatalf("bad:\n%s", actual)
   381  	}
   382  
   383  	actual = outputsStr(c.Outputs)
   384  	if actual != strings.TrimSpace(dirBasicOutputsStr) {
   385  		t.Fatalf("bad:\n%s", actual)
   386  	}
   387  }
   388  
   389  func TestLoadDir_file(t *testing.T) {
   390  	_, err := LoadDir(filepath.Join(fixtureDir, "variables.tf"))
   391  	if err == nil {
   392  		t.Fatal("should error")
   393  	}
   394  }
   395  
   396  func TestLoadDir_noConfigs(t *testing.T) {
   397  	_, err := LoadDir(filepath.Join(fixtureDir, "dir-empty"))
   398  	if err == nil {
   399  		t.Fatal("should error")
   400  	}
   401  }
   402  
   403  func TestLoadDir_noMerge(t *testing.T) {
   404  	c, err := LoadDir(filepath.Join(fixtureDir, "dir-merge"))
   405  	if err != nil {
   406  		t.Fatalf("err: %s", err)
   407  	}
   408  
   409  	if c == nil {
   410  		t.Fatal("config should not be nil")
   411  	}
   412  
   413  	if err := c.Validate(); err == nil {
   414  		t.Fatal("should not be valid")
   415  	}
   416  }
   417  
   418  func TestLoadDir_override(t *testing.T) {
   419  	c, err := LoadDir(filepath.Join(fixtureDir, "dir-override"))
   420  	if err != nil {
   421  		t.Fatalf("err: %s", err)
   422  	}
   423  
   424  	if c == nil {
   425  		t.Fatal("config should not be nil")
   426  	}
   427  
   428  	actual := variablesStr(c.Variables)
   429  	if actual != strings.TrimSpace(dirOverrideVariablesStr) {
   430  		t.Fatalf("bad:\n%s", actual)
   431  	}
   432  
   433  	actual = providerConfigsStr(c.ProviderConfigs)
   434  	if actual != strings.TrimSpace(dirOverrideProvidersStr) {
   435  		t.Fatalf("bad:\n%s", actual)
   436  	}
   437  
   438  	actual = resourcesStr(c.Resources)
   439  	if actual != strings.TrimSpace(dirOverrideResourcesStr) {
   440  		t.Fatalf("bad:\n%s", actual)
   441  	}
   442  
   443  	actual = outputsStr(c.Outputs)
   444  	if actual != strings.TrimSpace(dirOverrideOutputsStr) {
   445  		t.Fatalf("bad:\n%s", actual)
   446  	}
   447  }
   448  
   449  func TestLoadFile_mismatchedVariableTypes(t *testing.T) {
   450  	_, err := LoadFile(filepath.Join(fixtureDir, "variable-mismatched-type.tf"))
   451  	if err == nil {
   452  		t.Fatalf("bad: expected error")
   453  	}
   454  
   455  	errorStr := err.Error()
   456  	if !strings.Contains(errorStr, "'not_a_map' has a default value which is not of type 'string'") {
   457  		t.Fatalf("bad: expected error has wrong text: %s", errorStr)
   458  	}
   459  }
   460  
   461  func TestLoadFile_badVariableTypes(t *testing.T) {
   462  	_, err := LoadFile(filepath.Join(fixtureDir, "bad-variable-type.tf"))
   463  	if err == nil {
   464  		t.Fatalf("bad: expected error")
   465  	}
   466  
   467  	errorStr := err.Error()
   468  	if !strings.Contains(errorStr, "'bad_type' must be of type string") {
   469  		t.Fatalf("bad: expected error has wrong text: %s", errorStr)
   470  	}
   471  }
   472  
   473  func TestLoadFile_provisioners(t *testing.T) {
   474  	c, err := LoadFile(filepath.Join(fixtureDir, "provisioners.tf"))
   475  	if err != nil {
   476  		t.Fatalf("err: %s", err)
   477  	}
   478  
   479  	if c == nil {
   480  		t.Fatal("config should not be nil")
   481  	}
   482  
   483  	actual := resourcesStr(c.Resources)
   484  	if actual != strings.TrimSpace(provisionerResourcesStr) {
   485  		t.Fatalf("bad:\n%s", actual)
   486  	}
   487  }
   488  
   489  func TestLoadFile_connections(t *testing.T) {
   490  	c, err := LoadFile(filepath.Join(fixtureDir, "connection.tf"))
   491  	if err != nil {
   492  		t.Fatalf("err: %s", err)
   493  	}
   494  
   495  	if c == nil {
   496  		t.Fatal("config should not be nil")
   497  	}
   498  
   499  	actual := resourcesStr(c.Resources)
   500  	if actual != strings.TrimSpace(connectionResourcesStr) {
   501  		t.Fatalf("bad:\n%s", actual)
   502  	}
   503  
   504  	// Check for the connection info
   505  	r := c.Resources[0]
   506  	if r.Name != "web" && r.Type != "aws_instance" {
   507  		t.Fatalf("Bad: %#v", r)
   508  	}
   509  
   510  	p1 := r.Provisioners[0]
   511  	if p1.ConnInfo == nil || len(p1.ConnInfo.Raw) != 2 {
   512  		t.Fatalf("Bad: %#v", p1.ConnInfo)
   513  	}
   514  	if p1.ConnInfo.Raw["user"] != "nobody" {
   515  		t.Fatalf("Bad: %#v", p1.ConnInfo)
   516  	}
   517  
   518  	p2 := r.Provisioners[1]
   519  	if p2.ConnInfo == nil || len(p2.ConnInfo.Raw) != 2 {
   520  		t.Fatalf("Bad: %#v", p2.ConnInfo)
   521  	}
   522  	if p2.ConnInfo.Raw["user"] != "root" {
   523  		t.Fatalf("Bad: %#v", p2.ConnInfo)
   524  	}
   525  }
   526  
   527  func TestLoadFile_createBeforeDestroy(t *testing.T) {
   528  	c, err := LoadFile(filepath.Join(fixtureDir, "create-before-destroy.tf"))
   529  	if err != nil {
   530  		t.Fatalf("err: %s", err)
   531  	}
   532  
   533  	if c == nil {
   534  		t.Fatal("config should not be nil")
   535  	}
   536  
   537  	actual := resourcesStr(c.Resources)
   538  	if actual != strings.TrimSpace(createBeforeDestroyResourcesStr) {
   539  		t.Fatalf("bad:\n%s", actual)
   540  	}
   541  
   542  	// Check for the flag value
   543  	r := c.Resources[0]
   544  	if r.Name != "web" && r.Type != "aws_instance" {
   545  		t.Fatalf("Bad: %#v", r)
   546  	}
   547  
   548  	// Should enable create before destroy
   549  	if !r.Lifecycle.CreateBeforeDestroy {
   550  		t.Fatalf("Bad: %#v", r)
   551  	}
   552  
   553  	r = c.Resources[1]
   554  	if r.Name != "bar" && r.Type != "aws_instance" {
   555  		t.Fatalf("Bad: %#v", r)
   556  	}
   557  
   558  	// Should not enable create before destroy
   559  	if r.Lifecycle.CreateBeforeDestroy {
   560  		t.Fatalf("Bad: %#v", r)
   561  	}
   562  }
   563  
   564  func TestLoadFile_ignoreChanges(t *testing.T) {
   565  	c, err := LoadFile(filepath.Join(fixtureDir, "ignore-changes.tf"))
   566  	if err != nil {
   567  		t.Fatalf("err: %s", err)
   568  	}
   569  
   570  	if c == nil {
   571  		t.Fatal("config should not be nil")
   572  	}
   573  
   574  	actual := resourcesStr(c.Resources)
   575  	print(actual)
   576  	if actual != strings.TrimSpace(ignoreChangesResourcesStr) {
   577  		t.Fatalf("bad:\n%s", actual)
   578  	}
   579  
   580  	// Check for the flag value
   581  	r := c.Resources[0]
   582  	if r.Name != "web" && r.Type != "aws_instance" {
   583  		t.Fatalf("Bad: %#v", r)
   584  	}
   585  
   586  	// Should populate ignore changes
   587  	if len(r.Lifecycle.IgnoreChanges) == 0 {
   588  		t.Fatalf("Bad: %#v", r)
   589  	}
   590  
   591  	r = c.Resources[1]
   592  	if r.Name != "bar" && r.Type != "aws_instance" {
   593  		t.Fatalf("Bad: %#v", r)
   594  	}
   595  
   596  	// Should not populate ignore changes
   597  	if len(r.Lifecycle.IgnoreChanges) > 0 {
   598  		t.Fatalf("Bad: %#v", r)
   599  	}
   600  
   601  	r = c.Resources[2]
   602  	if r.Name != "baz" && r.Type != "aws_instance" {
   603  		t.Fatalf("Bad: %#v", r)
   604  	}
   605  
   606  	// Should not populate ignore changes
   607  	if len(r.Lifecycle.IgnoreChanges) > 0 {
   608  		t.Fatalf("Bad: %#v", r)
   609  	}
   610  }
   611  
   612  func TestLoad_preventDestroyString(t *testing.T) {
   613  	c, err := LoadFile(filepath.Join(fixtureDir, "prevent-destroy-string.tf"))
   614  	if err != nil {
   615  		t.Fatalf("err: %s", err)
   616  	}
   617  
   618  	if c == nil {
   619  		t.Fatal("config should not be nil")
   620  	}
   621  
   622  	actual := resourcesStr(c.Resources)
   623  	if actual != strings.TrimSpace(createBeforeDestroyResourcesStr) {
   624  		t.Fatalf("bad:\n%s", actual)
   625  	}
   626  
   627  	// Check for the flag value
   628  	r := c.Resources[0]
   629  	if r.Name != "web" && r.Type != "aws_instance" {
   630  		t.Fatalf("Bad: %#v", r)
   631  	}
   632  
   633  	// Should enable create before destroy
   634  	if !r.Lifecycle.PreventDestroy {
   635  		t.Fatalf("Bad: %#v", r)
   636  	}
   637  
   638  	r = c.Resources[1]
   639  	if r.Name != "bar" && r.Type != "aws_instance" {
   640  		t.Fatalf("Bad: %#v", r)
   641  	}
   642  
   643  	// Should not enable create before destroy
   644  	if r.Lifecycle.PreventDestroy {
   645  		t.Fatalf("Bad: %#v", r)
   646  	}
   647  }
   648  
   649  func TestLoad_temporary_files(t *testing.T) {
   650  	_, err := LoadDir(filepath.Join(fixtureDir, "dir-temporary-files"))
   651  	if err == nil {
   652  		t.Fatalf("Expected to see an error stating no config files found")
   653  	}
   654  }
   655  
   656  func TestLoad_hclAttributes(t *testing.T) {
   657  	c, err := LoadFile(filepath.Join(fixtureDir, "attributes.tf"))
   658  	if err != nil {
   659  		t.Fatalf("Bad: %s", err)
   660  	}
   661  
   662  	if c == nil {
   663  		t.Fatal("config should not be nil")
   664  	}
   665  
   666  	actual := resourcesStr(c.Resources)
   667  	print(actual)
   668  	if actual != strings.TrimSpace(jsonAttributeStr) {
   669  		t.Fatalf("bad:\n%s", actual)
   670  	}
   671  
   672  	r := c.Resources[0]
   673  	if r.Name != "test" && r.Type != "cloudstack_firewall" {
   674  		t.Fatalf("Bad: %#v", r)
   675  	}
   676  
   677  	raw := r.RawConfig
   678  	if raw.Raw["ipaddress"] != "192.168.0.1" {
   679  		t.Fatalf("Bad: %s", raw.Raw["ipAddress"])
   680  	}
   681  
   682  	rule := raw.Raw["rule"].([]map[string]interface{})[0]
   683  	if rule["protocol"] != "tcp" {
   684  		t.Fatalf("Bad: %s", rule["protocol"])
   685  	}
   686  
   687  	if rule["source_cidr"] != "10.0.0.0/8" {
   688  		t.Fatalf("Bad: %s", rule["source_cidr"])
   689  	}
   690  
   691  	ports := rule["ports"].([]interface{})
   692  
   693  	if ports[0] != "80" {
   694  		t.Fatalf("Bad ports: %s", ports[0])
   695  	}
   696  	if ports[1] != "1000-2000" {
   697  		t.Fatalf("Bad ports: %s", ports[1])
   698  	}
   699  }
   700  
   701  func TestLoad_jsonAttributes(t *testing.T) {
   702  	c, err := LoadFile(filepath.Join(fixtureDir, "attributes.tf.json"))
   703  	if err != nil {
   704  		t.Fatalf("Bad: %s", err)
   705  	}
   706  
   707  	if c == nil {
   708  		t.Fatal("config should not be nil")
   709  	}
   710  
   711  	actual := resourcesStr(c.Resources)
   712  	print(actual)
   713  	if actual != strings.TrimSpace(jsonAttributeStr) {
   714  		t.Fatalf("bad:\n%s", actual)
   715  	}
   716  
   717  	r := c.Resources[0]
   718  	if r.Name != "test" && r.Type != "cloudstack_firewall" {
   719  		t.Fatalf("Bad: %#v", r)
   720  	}
   721  
   722  	raw := r.RawConfig
   723  	if raw.Raw["ipaddress"] != "192.168.0.1" {
   724  		t.Fatalf("Bad: %s", raw.Raw["ipAddress"])
   725  	}
   726  
   727  	rule := raw.Raw["rule"].([]map[string]interface{})[0]
   728  	if rule["protocol"] != "tcp" {
   729  		t.Fatalf("Bad: %s", rule["protocol"])
   730  	}
   731  
   732  	if rule["source_cidr"] != "10.0.0.0/8" {
   733  		t.Fatalf("Bad: %s", rule["source_cidr"])
   734  	}
   735  
   736  	ports := rule["ports"].([]interface{})
   737  
   738  	if ports[0] != "80" {
   739  		t.Fatalf("Bad ports: %s", ports[0])
   740  	}
   741  	if ports[1] != "1000-2000" {
   742  		t.Fatalf("Bad ports: %s", ports[1])
   743  	}
   744  }
   745  
   746  const jsonAttributeStr = `
   747  cloudstack_firewall.test (x1)
   748    ipaddress
   749    rule
   750  `
   751  
   752  const windowsHeredocResourcesStr = `
   753  aws_instance.test (x1)
   754    user_data
   755  `
   756  
   757  const heredocProvidersStr = `
   758  aws
   759    access_key
   760    secret_key
   761  `
   762  
   763  const heredocResourcesStr = `
   764  aws_iam_policy.policy (x1)
   765    description
   766    name
   767    path
   768    policy
   769  aws_instance.heredocwithnumbers (x1)
   770    ami
   771    provisioners
   772      local-exec
   773        command
   774  aws_instance.test (x1)
   775    ami
   776    provisioners
   777      remote-exec
   778        inline
   779  `
   780  
   781  const basicOutputsStr = `
   782  web_ip
   783    vars
   784      resource: aws_instance.web.private_ip
   785  `
   786  
   787  const basicProvidersStr = `
   788  aws
   789    access_key
   790    secret_key
   791  do
   792    api_key
   793    vars
   794      user: var.foo
   795  `
   796  
   797  const basicResourcesStr = `
   798  aws_instance.db (x1)
   799    VPC
   800    security_groups
   801    provisioners
   802      file
   803        destination
   804        source
   805    dependsOn
   806      aws_instance.web
   807    vars
   808      resource: aws_security_group.firewall.*.id
   809  aws_instance.web (x1)
   810    ami
   811    network_interface
   812    security_groups
   813    provisioners
   814      file
   815        destination
   816        source
   817    vars
   818      resource: aws_security_group.firewall.foo
   819      user: var.foo
   820  aws_security_group.firewall (x5)
   821  data.do.depends (x1)
   822    dependsOn
   823      data.do.simple
   824  data.do.simple (x1)
   825    foo
   826  `
   827  
   828  const basicVariablesStr = `
   829  bar (required) (string)
   830    <>
   831    <>
   832  baz (map)
   833    map[key:value]
   834    <>
   835  foo
   836    bar
   837    bar
   838  `
   839  
   840  const dirBasicOutputsStr = `
   841  web_ip
   842    vars
   843      resource: aws_instance.web.private_ip
   844  `
   845  
   846  const dirBasicProvidersStr = `
   847  aws
   848    access_key
   849    secret_key
   850  do
   851    api_key
   852    vars
   853      user: var.foo
   854  `
   855  
   856  const dirBasicResourcesStr = `
   857  aws_instance.db (x1)
   858    security_groups
   859    vars
   860      resource: aws_security_group.firewall.*.id
   861  aws_instance.web (x1)
   862    ami
   863    network_interface
   864    security_groups
   865    vars
   866      resource: aws_security_group.firewall.foo
   867      user: var.foo
   868  aws_security_group.firewall (x5)
   869  data.do.depends (x1)
   870    dependsOn
   871      data.do.simple
   872  data.do.simple (x1)
   873    foo
   874  `
   875  
   876  const dirBasicVariablesStr = `
   877  foo
   878    bar
   879    bar
   880  `
   881  
   882  const dirOverrideOutputsStr = `
   883  web_ip
   884    vars
   885      resource: aws_instance.web.private_ip
   886  `
   887  
   888  const dirOverrideProvidersStr = `
   889  aws
   890    access_key
   891    secret_key
   892  do
   893    api_key
   894    vars
   895      user: var.foo
   896  `
   897  
   898  const dirOverrideResourcesStr = `
   899  aws_instance.db (x1)
   900    ami
   901    security_groups
   902  aws_instance.web (x1)
   903    ami
   904    foo
   905    network_interface
   906    security_groups
   907    vars
   908      resource: aws_security_group.firewall.foo
   909      user: var.foo
   910  aws_security_group.firewall (x5)
   911  data.do.depends (x1)
   912    hello
   913    dependsOn
   914      data.do.simple
   915  data.do.simple (x1)
   916    foo
   917  `
   918  
   919  const dirOverrideVariablesStr = `
   920  foo
   921    bar
   922    bar
   923  `
   924  
   925  const importProvidersStr = `
   926  aws
   927    bar
   928    foo
   929  `
   930  
   931  const importResourcesStr = `
   932  aws_security_group.db (x1)
   933  aws_security_group.web (x1)
   934  `
   935  
   936  const importVariablesStr = `
   937  bar (required)
   938    <>
   939    <>
   940  foo
   941    bar
   942    bar
   943  `
   944  
   945  const modulesModulesStr = `
   946  bar
   947    source = baz
   948    memory
   949  `
   950  
   951  const provisionerResourcesStr = `
   952  aws_instance.web (x1)
   953    ami
   954    security_groups
   955    provisioners
   956      shell
   957        path
   958    vars
   959      resource: aws_security_group.firewall.foo
   960      user: var.foo
   961  `
   962  
   963  const connectionResourcesStr = `
   964  aws_instance.web (x1)
   965    ami
   966    security_groups
   967    provisioners
   968      shell
   969        path
   970      shell
   971        path
   972    vars
   973      resource: aws_security_group.firewall.foo
   974      user: var.foo
   975  `
   976  
   977  const variablesVariablesStr = `
   978  bar
   979    <>
   980    <>
   981  baz
   982    foo
   983    <>
   984  foo (required)
   985    <>
   986    <>
   987  `
   988  
   989  const createBeforeDestroyResourcesStr = `
   990  aws_instance.bar (x1)
   991    ami
   992  aws_instance.web (x1)
   993    ami
   994  `
   995  
   996  const ignoreChangesResourcesStr = `
   997  aws_instance.bar (x1)
   998    ami
   999  aws_instance.baz (x1)
  1000    ami
  1001  aws_instance.web (x1)
  1002    ami
  1003  `