github.com/ewbankkit/terraform@v0.7.7/command/command_test.go (about)

     1  package command
     2  
     3  import (
     4  	"flag"
     5  	"io/ioutil"
     6  	"log"
     7  	"os"
     8  	"path/filepath"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/hashicorp/go-getter"
    13  	"github.com/hashicorp/terraform/config/module"
    14  	"github.com/hashicorp/terraform/helper/logging"
    15  	"github.com/hashicorp/terraform/terraform"
    16  )
    17  
    18  // This is the directory where our test fixtures are.
    19  var fixtureDir = "./test-fixtures"
    20  
    21  func init() {
    22  	test = true
    23  
    24  	// Expand the fixture dir on init because we change the working
    25  	// directory in some tests.
    26  	var err error
    27  	fixtureDir, err = filepath.Abs(fixtureDir)
    28  	if err != nil {
    29  		panic(err)
    30  	}
    31  }
    32  
    33  func TestMain(m *testing.M) {
    34  	flag.Parse()
    35  	if testing.Verbose() {
    36  		// if we're verbose, use the logging requested by TF_LOG
    37  		logging.SetOutput()
    38  	} else {
    39  		// otherwise silence all logs
    40  		log.SetOutput(ioutil.Discard)
    41  	}
    42  
    43  	os.Exit(m.Run())
    44  }
    45  
    46  func tempDir(t *testing.T) string {
    47  	dir, err := ioutil.TempDir("", "tf")
    48  	if err != nil {
    49  		t.Fatalf("err: %s", err)
    50  	}
    51  	if err := os.RemoveAll(dir); err != nil {
    52  		t.Fatalf("err: %s", err)
    53  	}
    54  
    55  	return dir
    56  }
    57  
    58  func testFixturePath(name string) string {
    59  	return filepath.Join(fixtureDir, name)
    60  }
    61  
    62  func testCtxConfig(p terraform.ResourceProvider) *terraform.ContextOpts {
    63  	return &terraform.ContextOpts{
    64  		Providers: map[string]terraform.ResourceProviderFactory{
    65  			"test": func() (terraform.ResourceProvider, error) {
    66  				return p, nil
    67  			},
    68  		},
    69  	}
    70  }
    71  
    72  func testCtxConfigWithShell(p terraform.ResourceProvider, pr terraform.ResourceProvisioner) *terraform.ContextOpts {
    73  	return &terraform.ContextOpts{
    74  		Providers: map[string]terraform.ResourceProviderFactory{
    75  			"test": func() (terraform.ResourceProvider, error) {
    76  				return p, nil
    77  			},
    78  		},
    79  		Provisioners: map[string]terraform.ResourceProvisionerFactory{
    80  			"shell": func() (terraform.ResourceProvisioner, error) {
    81  				return pr, nil
    82  			},
    83  		},
    84  	}
    85  }
    86  
    87  func testModule(t *testing.T, name string) *module.Tree {
    88  	mod, err := module.NewTreeModule("", filepath.Join(fixtureDir, name))
    89  	if err != nil {
    90  		t.Fatalf("err: %s", err)
    91  	}
    92  
    93  	s := &getter.FolderStorage{StorageDir: tempDir(t)}
    94  	if err := mod.Load(s, module.GetModeGet); err != nil {
    95  		t.Fatalf("err: %s", err)
    96  	}
    97  
    98  	return mod
    99  }
   100  
   101  func testPlanFile(t *testing.T, plan *terraform.Plan) string {
   102  	path := testTempFile(t)
   103  
   104  	f, err := os.Create(path)
   105  	if err != nil {
   106  		t.Fatalf("err: %s", err)
   107  	}
   108  	defer f.Close()
   109  
   110  	if err := terraform.WritePlan(plan, f); err != nil {
   111  		t.Fatalf("err: %s", err)
   112  	}
   113  
   114  	return path
   115  }
   116  
   117  func testReadPlan(t *testing.T, path string) *terraform.Plan {
   118  	f, err := os.Open(path)
   119  	if err != nil {
   120  		t.Fatalf("err: %s", err)
   121  	}
   122  	defer f.Close()
   123  
   124  	p, err := terraform.ReadPlan(f)
   125  	if err != nil {
   126  		t.Fatalf("err: %s", err)
   127  	}
   128  
   129  	return p
   130  }
   131  
   132  // testState returns a test State structure that we use for a lot of tests.
   133  func testState() *terraform.State {
   134  	state := &terraform.State{
   135  		Version: 2,
   136  		Modules: []*terraform.ModuleState{
   137  			&terraform.ModuleState{
   138  				Path: []string{"root"},
   139  				Resources: map[string]*terraform.ResourceState{
   140  					"test_instance.foo": &terraform.ResourceState{
   141  						Type: "test_instance",
   142  						Primary: &terraform.InstanceState{
   143  							ID: "bar",
   144  						},
   145  					},
   146  				},
   147  				Outputs: map[string]*terraform.OutputState{},
   148  			},
   149  		},
   150  	}
   151  	state.Init()
   152  	return state
   153  }
   154  
   155  func testStateFile(t *testing.T, s *terraform.State) string {
   156  	path := testTempFile(t)
   157  
   158  	f, err := os.Create(path)
   159  	if err != nil {
   160  		t.Fatalf("err: %s", err)
   161  	}
   162  	defer f.Close()
   163  
   164  	if err := terraform.WriteState(s, f); err != nil {
   165  		t.Fatalf("err: %s", err)
   166  	}
   167  
   168  	return path
   169  }
   170  
   171  // testStateFileDefault writes the state out to the default statefile
   172  // in the cwd. Use `testCwd` to change into a temp cwd.
   173  func testStateFileDefault(t *testing.T, s *terraform.State) string {
   174  	f, err := os.Create(DefaultStateFilename)
   175  	if err != nil {
   176  		t.Fatalf("err: %s", err)
   177  	}
   178  	defer f.Close()
   179  
   180  	if err := terraform.WriteState(s, f); err != nil {
   181  		t.Fatalf("err: %s", err)
   182  	}
   183  
   184  	return DefaultStateFilename
   185  }
   186  
   187  // testStateFileRemote writes the state out to the remote statefile
   188  // in the cwd. Use `testCwd` to change into a temp cwd.
   189  func testStateFileRemote(t *testing.T, s *terraform.State) string {
   190  	path := filepath.Join(DefaultDataDir, DefaultStateFilename)
   191  	if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
   192  		t.Fatalf("err: %s", err)
   193  	}
   194  
   195  	f, err := os.Create(path)
   196  	if err != nil {
   197  		t.Fatalf("err: %s", err)
   198  	}
   199  	defer f.Close()
   200  
   201  	if err := terraform.WriteState(s, f); err != nil {
   202  		t.Fatalf("err: %s", err)
   203  	}
   204  
   205  	return path
   206  }
   207  
   208  // testStateOutput tests that the state at the given path contains
   209  // the expected state string.
   210  func testStateOutput(t *testing.T, path string, expected string) {
   211  	f, err := os.Open(path)
   212  	if err != nil {
   213  		t.Fatalf("err: %s", err)
   214  	}
   215  
   216  	newState, err := terraform.ReadState(f)
   217  	f.Close()
   218  	if err != nil {
   219  		t.Fatalf("err: %s", err)
   220  	}
   221  
   222  	actual := strings.TrimSpace(newState.String())
   223  	expected = strings.TrimSpace(expected)
   224  	if actual != expected {
   225  		t.Fatalf("expected:\n%s\nactual:\n%s", expected, actual)
   226  	}
   227  }
   228  
   229  func testProvider() *terraform.MockResourceProvider {
   230  	p := new(terraform.MockResourceProvider)
   231  	p.DiffReturn = &terraform.InstanceDiff{}
   232  	p.RefreshFn = func(
   233  		info *terraform.InstanceInfo,
   234  		s *terraform.InstanceState) (*terraform.InstanceState, error) {
   235  		return s, nil
   236  	}
   237  	p.ResourcesReturn = []terraform.ResourceType{
   238  		terraform.ResourceType{
   239  			Name: "test_instance",
   240  		},
   241  	}
   242  
   243  	return p
   244  }
   245  
   246  func testTempFile(t *testing.T) string {
   247  	return filepath.Join(testTempDir(t), "state.tfstate")
   248  }
   249  
   250  func testTempDir(t *testing.T) string {
   251  	d, err := ioutil.TempDir("", "tf")
   252  	if err != nil {
   253  		t.Fatalf("err: %s", err)
   254  	}
   255  
   256  	return d
   257  }
   258  
   259  // testRename renames the path to new and returns a function to defer to
   260  // revert the rename.
   261  func testRename(t *testing.T, base, path, new string) func() {
   262  	if base != "" {
   263  		path = filepath.Join(base, path)
   264  		new = filepath.Join(base, new)
   265  	}
   266  
   267  	if err := os.Rename(path, new); err != nil {
   268  		t.Fatalf("err: %s", err)
   269  	}
   270  
   271  	return func() {
   272  		// Just re-rename and ignore the return value
   273  		testRename(t, "", new, path)
   274  	}
   275  }
   276  
   277  // testChdir changes the directory and returns a function to defer to
   278  // revert the old cwd.
   279  func testChdir(t *testing.T, new string) func() {
   280  	old, err := os.Getwd()
   281  	if err != nil {
   282  		t.Fatalf("err: %s", err)
   283  	}
   284  
   285  	if err := os.Chdir(new); err != nil {
   286  		t.Fatalf("err: %v", err)
   287  	}
   288  
   289  	return func() {
   290  		// Re-run the function ignoring the defer result
   291  		testChdir(t, old)
   292  	}
   293  }
   294  
   295  // testCwd is used to change the current working directory
   296  // into a test directory that should be remoted after
   297  func testCwd(t *testing.T) (string, string) {
   298  	tmp, err := ioutil.TempDir("", "tf")
   299  	if err != nil {
   300  		t.Fatalf("err: %v", err)
   301  	}
   302  
   303  	cwd, err := os.Getwd()
   304  	if err != nil {
   305  		t.Fatalf("err: %v", err)
   306  	}
   307  
   308  	if err := os.Chdir(tmp); err != nil {
   309  		t.Fatalf("err: %v", err)
   310  	}
   311  
   312  	return tmp, cwd
   313  }
   314  
   315  // testFixCwd is used to as a defer to testDir
   316  func testFixCwd(t *testing.T, tmp, cwd string) {
   317  	if err := os.Chdir(cwd); err != nil {
   318  		t.Fatalf("err: %v", err)
   319  	}
   320  
   321  	if err := os.RemoveAll(tmp); err != nil {
   322  		t.Fatalf("err: %v", err)
   323  	}
   324  }