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