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