github.com/nathanielks/terraform@v0.6.1-0.20170509030759-13e1a62319dc/config/module/tree_test.go (about)

     1  package module
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"reflect"
     7  	"strings"
     8  	"testing"
     9  
    10  	"github.com/hashicorp/go-getter"
    11  	"github.com/hashicorp/terraform/config"
    12  	"github.com/hashicorp/terraform/helper/copy"
    13  )
    14  
    15  func TestTreeChild(t *testing.T) {
    16  	var nilTree *Tree
    17  	if nilTree.Child(nil) != nil {
    18  		t.Fatal("child should be nil")
    19  	}
    20  
    21  	storage := testStorage(t)
    22  	tree := NewTree("", testConfig(t, "child"))
    23  	if err := tree.Load(storage, GetModeGet); err != nil {
    24  		t.Fatalf("err: %s", err)
    25  	}
    26  
    27  	// Should be able to get the root child
    28  	if c := tree.Child([]string{}); c == nil {
    29  		t.Fatal("should not be nil")
    30  	} else if c.Name() != "root" {
    31  		t.Fatalf("bad: %#v", c.Name())
    32  	} else if !reflect.DeepEqual(c.Path(), []string(nil)) {
    33  		t.Fatalf("bad: %#v", c.Path())
    34  	}
    35  
    36  	// Should be able to get the root child
    37  	if c := tree.Child(nil); c == nil {
    38  		t.Fatal("should not be nil")
    39  	} else if c.Name() != "root" {
    40  		t.Fatalf("bad: %#v", c.Name())
    41  	} else if !reflect.DeepEqual(c.Path(), []string(nil)) {
    42  		t.Fatalf("bad: %#v", c.Path())
    43  	}
    44  
    45  	// Should be able to get the foo child
    46  	if c := tree.Child([]string{"foo"}); c == nil {
    47  		t.Fatal("should not be nil")
    48  	} else if c.Name() != "foo" {
    49  		t.Fatalf("bad: %#v", c.Name())
    50  	} else if !reflect.DeepEqual(c.Path(), []string{"foo"}) {
    51  		t.Fatalf("bad: %#v", c.Path())
    52  	}
    53  
    54  	// Should be able to get the nested child
    55  	if c := tree.Child([]string{"foo", "bar"}); c == nil {
    56  		t.Fatal("should not be nil")
    57  	} else if c.Name() != "bar" {
    58  		t.Fatalf("bad: %#v", c.Name())
    59  	} else if !reflect.DeepEqual(c.Path(), []string{"foo", "bar"}) {
    60  		t.Fatalf("bad: %#v", c.Path())
    61  	}
    62  }
    63  
    64  func TestTreeLoad(t *testing.T) {
    65  	storage := testStorage(t)
    66  	tree := NewTree("", testConfig(t, "basic"))
    67  
    68  	if tree.Loaded() {
    69  		t.Fatal("should not be loaded")
    70  	}
    71  
    72  	// This should error because we haven't gotten things yet
    73  	if err := tree.Load(storage, GetModeNone); err == nil {
    74  		t.Fatal("should error")
    75  	}
    76  
    77  	if tree.Loaded() {
    78  		t.Fatal("should not be loaded")
    79  	}
    80  
    81  	// This should get things
    82  	if err := tree.Load(storage, GetModeGet); err != nil {
    83  		t.Fatalf("err: %s", err)
    84  	}
    85  
    86  	if !tree.Loaded() {
    87  		t.Fatal("should be loaded")
    88  	}
    89  
    90  	// This should no longer error
    91  	if err := tree.Load(storage, GetModeNone); err != nil {
    92  		t.Fatalf("err: %s", err)
    93  	}
    94  
    95  	actual := strings.TrimSpace(tree.String())
    96  	expected := strings.TrimSpace(treeLoadStr)
    97  	if actual != expected {
    98  		t.Fatalf("bad: \n\n%s", actual)
    99  	}
   100  }
   101  
   102  func TestTreeLoad_duplicate(t *testing.T) {
   103  	storage := testStorage(t)
   104  	tree := NewTree("", testConfig(t, "dup"))
   105  
   106  	if tree.Loaded() {
   107  		t.Fatal("should not be loaded")
   108  	}
   109  
   110  	// This should get things
   111  	if err := tree.Load(storage, GetModeGet); err == nil {
   112  		t.Fatalf("should error")
   113  	}
   114  }
   115  
   116  func TestTreeLoad_copyable(t *testing.T) {
   117  	dir := tempDir(t)
   118  	storage := &getter.FolderStorage{StorageDir: dir}
   119  	cfg := testConfig(t, "basic")
   120  	tree := NewTree("", cfg)
   121  
   122  	// This should get things
   123  	if err := tree.Load(storage, GetModeGet); err != nil {
   124  		t.Fatalf("err: %s", err)
   125  	}
   126  
   127  	if !tree.Loaded() {
   128  		t.Fatal("should be loaded")
   129  	}
   130  
   131  	// This should no longer error
   132  	if err := tree.Load(storage, GetModeNone); err != nil {
   133  		t.Fatalf("err: %s", err)
   134  	}
   135  
   136  	// Now we copy the directory, this COPIES symlink values, and
   137  	// doesn't create symlinks themselves. That is important.
   138  	dir2 := tempDir(t)
   139  	os.RemoveAll(dir2)
   140  	defer os.RemoveAll(dir2)
   141  	if err := copy.CopyDir(dir, dir2); err != nil {
   142  		t.Fatalf("err: %s", err)
   143  	}
   144  
   145  	// Now copy the configuration
   146  	cfgDir := tempDir(t)
   147  	os.RemoveAll(cfgDir)
   148  	defer os.RemoveAll(cfgDir)
   149  	if err := copy.CopyDir(cfg.Dir, cfgDir); err != nil {
   150  		t.Fatalf("err: %s", err)
   151  	}
   152  
   153  	{
   154  		cfg, err := config.LoadDir(cfgDir)
   155  		if err != nil {
   156  			t.Fatalf("err: %s", err)
   157  		}
   158  
   159  		tree := NewTree("", cfg)
   160  		storage := &getter.FolderStorage{StorageDir: dir2}
   161  
   162  		// This should not error since we already got it!
   163  		if err := tree.Load(storage, GetModeNone); err != nil {
   164  			t.Fatalf("err: %s", err)
   165  		}
   166  
   167  		if !tree.Loaded() {
   168  			t.Fatal("should be loaded")
   169  		}
   170  	}
   171  }
   172  
   173  func TestTreeLoad_parentRef(t *testing.T) {
   174  	storage := testStorage(t)
   175  	tree := NewTree("", testConfig(t, "basic-parent"))
   176  
   177  	if tree.Loaded() {
   178  		t.Fatal("should not be loaded")
   179  	}
   180  
   181  	// This should error because we haven't gotten things yet
   182  	if err := tree.Load(storage, GetModeNone); err == nil {
   183  		t.Fatal("should error")
   184  	}
   185  
   186  	if tree.Loaded() {
   187  		t.Fatal("should not be loaded")
   188  	}
   189  
   190  	// This should get things
   191  	if err := tree.Load(storage, GetModeGet); err != nil {
   192  		t.Fatalf("err: %s", err)
   193  	}
   194  
   195  	if !tree.Loaded() {
   196  		t.Fatal("should be loaded")
   197  	}
   198  
   199  	// This should no longer error
   200  	if err := tree.Load(storage, GetModeNone); err != nil {
   201  		t.Fatalf("err: %s", err)
   202  	}
   203  
   204  	actual := strings.TrimSpace(tree.String())
   205  	expected := strings.TrimSpace(treeLoadParentStr)
   206  	if actual != expected {
   207  		t.Fatalf("bad: \n\n%s", actual)
   208  	}
   209  }
   210  
   211  func TestTreeLoad_subdir(t *testing.T) {
   212  	storage := testStorage(t)
   213  	tree := NewTree("", testConfig(t, "basic-subdir"))
   214  
   215  	if tree.Loaded() {
   216  		t.Fatal("should not be loaded")
   217  	}
   218  
   219  	// This should error because we haven't gotten things yet
   220  	if err := tree.Load(storage, GetModeNone); err == nil {
   221  		t.Fatal("should error")
   222  	}
   223  
   224  	if tree.Loaded() {
   225  		t.Fatal("should not be loaded")
   226  	}
   227  
   228  	// This should get things
   229  	if err := tree.Load(storage, GetModeGet); err != nil {
   230  		t.Fatalf("err: %s", err)
   231  	}
   232  
   233  	if !tree.Loaded() {
   234  		t.Fatal("should be loaded")
   235  	}
   236  
   237  	// This should no longer error
   238  	if err := tree.Load(storage, GetModeNone); err != nil {
   239  		t.Fatalf("err: %s", err)
   240  	}
   241  
   242  	actual := strings.TrimSpace(tree.String())
   243  	expected := strings.TrimSpace(treeLoadSubdirStr)
   244  	if actual != expected {
   245  		t.Fatalf("bad: \n\n%s", actual)
   246  	}
   247  }
   248  
   249  func TestTreeModules(t *testing.T) {
   250  	tree := NewTree("", testConfig(t, "basic"))
   251  	actual := tree.Modules()
   252  
   253  	expected := []*Module{
   254  		&Module{Name: "foo", Source: "./foo"},
   255  	}
   256  
   257  	if !reflect.DeepEqual(actual, expected) {
   258  		t.Fatalf("bad: %#v", actual)
   259  	}
   260  }
   261  
   262  func TestTreeName(t *testing.T) {
   263  	tree := NewTree("", testConfig(t, "basic"))
   264  	actual := tree.Name()
   265  
   266  	if actual != RootName {
   267  		t.Fatalf("bad: %#v", actual)
   268  	}
   269  }
   270  
   271  // This is a table-driven test for tree validation. This is the preferred
   272  // way to test Validate. Non table-driven tests exist historically but
   273  // that style shouldn't be done anymore.
   274  func TestTreeValidate_table(t *testing.T) {
   275  	cases := []struct {
   276  		Name    string
   277  		Fixture string
   278  		Err     string
   279  	}{
   280  		{
   281  			"provider alias in child",
   282  			"validate-alias-good",
   283  			"",
   284  		},
   285  
   286  		{
   287  			"undefined provider alias in child",
   288  			"validate-alias-bad",
   289  			"alias must be defined",
   290  		},
   291  
   292  		{
   293  			"root module named root",
   294  			"validate-module-root",
   295  			"cannot contain module",
   296  		},
   297  
   298  		{
   299  			"grandchild module named root",
   300  			"validate-module-root-grandchild",
   301  			"",
   302  		},
   303  	}
   304  
   305  	for i, tc := range cases {
   306  		t.Run(fmt.Sprintf("%d-%s", i, tc.Name), func(t *testing.T) {
   307  			tree := NewTree("", testConfig(t, tc.Fixture))
   308  			if err := tree.Load(testStorage(t), GetModeGet); err != nil {
   309  				t.Fatalf("err: %s", err)
   310  			}
   311  
   312  			err := tree.Validate()
   313  			if (err != nil) != (tc.Err != "") {
   314  				t.Fatalf("err: %s", err)
   315  			}
   316  			if err == nil {
   317  				return
   318  			}
   319  			if !strings.Contains(err.Error(), tc.Err) {
   320  				t.Fatalf("err should contain %q: %s", tc.Err, err)
   321  			}
   322  		})
   323  	}
   324  }
   325  
   326  func TestTreeValidate_badChild(t *testing.T) {
   327  	tree := NewTree("", testConfig(t, "validate-child-bad"))
   328  
   329  	if err := tree.Load(testStorage(t), GetModeGet); err != nil {
   330  		t.Fatalf("err: %s", err)
   331  	}
   332  
   333  	if err := tree.Validate(); err == nil {
   334  		t.Fatal("should error")
   335  	}
   336  }
   337  
   338  func TestTreeValidate_badChildOutput(t *testing.T) {
   339  	tree := NewTree("", testConfig(t, "validate-bad-output"))
   340  
   341  	if err := tree.Load(testStorage(t), GetModeGet); err != nil {
   342  		t.Fatalf("err: %s", err)
   343  	}
   344  
   345  	if err := tree.Validate(); err == nil {
   346  		t.Fatal("should error")
   347  	}
   348  }
   349  
   350  func TestTreeValidate_badChildOutputToModule(t *testing.T) {
   351  	tree := NewTree("", testConfig(t, "validate-bad-output-to-module"))
   352  
   353  	if err := tree.Load(testStorage(t), GetModeGet); err != nil {
   354  		t.Fatalf("err: %s", err)
   355  	}
   356  
   357  	if err := tree.Validate(); err == nil {
   358  		t.Fatal("should error")
   359  	}
   360  }
   361  
   362  func TestTreeValidate_badChildVar(t *testing.T) {
   363  	tree := NewTree("", testConfig(t, "validate-bad-var"))
   364  
   365  	if err := tree.Load(testStorage(t), GetModeGet); err != nil {
   366  		t.Fatalf("err: %s", err)
   367  	}
   368  
   369  	if err := tree.Validate(); err == nil {
   370  		t.Fatal("should error")
   371  	}
   372  }
   373  
   374  func TestTreeValidate_badRoot(t *testing.T) {
   375  	tree := NewTree("", testConfig(t, "validate-root-bad"))
   376  
   377  	if err := tree.Load(testStorage(t), GetModeGet); err != nil {
   378  		t.Fatalf("err: %s", err)
   379  	}
   380  
   381  	if err := tree.Validate(); err == nil {
   382  		t.Fatal("should error")
   383  	}
   384  }
   385  
   386  func TestTreeValidate_good(t *testing.T) {
   387  	tree := NewTree("", testConfig(t, "validate-child-good"))
   388  
   389  	if err := tree.Load(testStorage(t), GetModeGet); err != nil {
   390  		t.Fatalf("err: %s", err)
   391  	}
   392  
   393  	if err := tree.Validate(); err != nil {
   394  		t.Fatalf("err: %s", err)
   395  	}
   396  }
   397  
   398  func TestTreeValidate_notLoaded(t *testing.T) {
   399  	tree := NewTree("", testConfig(t, "basic"))
   400  
   401  	if err := tree.Validate(); err == nil {
   402  		t.Fatal("should error")
   403  	}
   404  }
   405  
   406  func TestTreeValidate_requiredChildVar(t *testing.T) {
   407  	tree := NewTree("", testConfig(t, "validate-required-var"))
   408  
   409  	if err := tree.Load(testStorage(t), GetModeGet); err != nil {
   410  		t.Fatalf("err: %s", err)
   411  	}
   412  
   413  	err := tree.Validate()
   414  	if err == nil {
   415  		t.Fatal("should error")
   416  	}
   417  
   418  	// ensure both variables are mentioned in the output
   419  	errMsg := err.Error()
   420  	for _, v := range []string{"feature", "memory"} {
   421  		if !strings.Contains(errMsg, v) {
   422  			t.Fatalf("no mention of missing variable %q", v)
   423  		}
   424  	}
   425  }
   426  
   427  func TestTreeValidate_unknownModule(t *testing.T) {
   428  	tree := NewTree("", testConfig(t, "validate-module-unknown"))
   429  
   430  	if err := tree.Load(testStorage(t), GetModeNone); err != nil {
   431  		t.Fatalf("err: %s", err)
   432  	}
   433  
   434  	if err := tree.Validate(); err == nil {
   435  		t.Fatal("should error")
   436  	}
   437  }
   438  
   439  const treeLoadStr = `
   440  root
   441    foo (path: foo)
   442  `
   443  
   444  const treeLoadParentStr = `
   445  root
   446    a (path: a)
   447      b (path: a, b)
   448  `
   449  const treeLoadSubdirStr = `
   450  root
   451    foo (path: foo)
   452      bar (path: foo, bar)
   453  `