github.com/rhenning/terraform@v0.8.0-beta2/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  // testPlan returns a non-nil noop plan.
   102  func testPlan(t *testing.T) *terraform.Plan {
   103  	state := terraform.NewState()
   104  	state.RootModule().Outputs["foo"] = &terraform.OutputState{
   105  		Type:  "string",
   106  		Value: "foo",
   107  	}
   108  
   109  	return &terraform.Plan{
   110  		Module: testModule(t, "apply"),
   111  		State:  state,
   112  	}
   113  }
   114  
   115  func testPlanFile(t *testing.T, plan *terraform.Plan) string {
   116  	path := testTempFile(t)
   117  
   118  	f, err := os.Create(path)
   119  	if err != nil {
   120  		t.Fatalf("err: %s", err)
   121  	}
   122  	defer f.Close()
   123  
   124  	if err := terraform.WritePlan(plan, f); err != nil {
   125  		t.Fatalf("err: %s", err)
   126  	}
   127  
   128  	return path
   129  }
   130  
   131  func testReadPlan(t *testing.T, path string) *terraform.Plan {
   132  	f, err := os.Open(path)
   133  	if err != nil {
   134  		t.Fatalf("err: %s", err)
   135  	}
   136  	defer f.Close()
   137  
   138  	p, err := terraform.ReadPlan(f)
   139  	if err != nil {
   140  		t.Fatalf("err: %s", err)
   141  	}
   142  
   143  	return p
   144  }
   145  
   146  // testState returns a test State structure that we use for a lot of tests.
   147  func testState() *terraform.State {
   148  	state := &terraform.State{
   149  		Version: 2,
   150  		Modules: []*terraform.ModuleState{
   151  			&terraform.ModuleState{
   152  				Path: []string{"root"},
   153  				Resources: map[string]*terraform.ResourceState{
   154  					"test_instance.foo": &terraform.ResourceState{
   155  						Type: "test_instance",
   156  						Primary: &terraform.InstanceState{
   157  							ID: "bar",
   158  						},
   159  					},
   160  				},
   161  				Outputs: map[string]*terraform.OutputState{},
   162  			},
   163  		},
   164  	}
   165  	state.Init()
   166  	return state
   167  }
   168  
   169  func testStateFile(t *testing.T, s *terraform.State) string {
   170  	path := testTempFile(t)
   171  
   172  	f, err := os.Create(path)
   173  	if err != nil {
   174  		t.Fatalf("err: %s", err)
   175  	}
   176  	defer f.Close()
   177  
   178  	if err := terraform.WriteState(s, f); err != nil {
   179  		t.Fatalf("err: %s", err)
   180  	}
   181  
   182  	return path
   183  }
   184  
   185  // testStateFileDefault writes the state out to the default statefile
   186  // in the cwd. Use `testCwd` to change into a temp cwd.
   187  func testStateFileDefault(t *testing.T, s *terraform.State) string {
   188  	f, err := os.Create(DefaultStateFilename)
   189  	if err != nil {
   190  		t.Fatalf("err: %s", err)
   191  	}
   192  	defer f.Close()
   193  
   194  	if err := terraform.WriteState(s, f); err != nil {
   195  		t.Fatalf("err: %s", err)
   196  	}
   197  
   198  	return DefaultStateFilename
   199  }
   200  
   201  // testStateFileRemote writes the state out to the remote statefile
   202  // in the cwd. Use `testCwd` to change into a temp cwd.
   203  func testStateFileRemote(t *testing.T, s *terraform.State) string {
   204  	path := filepath.Join(DefaultDataDir, DefaultStateFilename)
   205  	if err := os.MkdirAll(filepath.Dir(path), 0755); err != nil {
   206  		t.Fatalf("err: %s", err)
   207  	}
   208  
   209  	f, err := os.Create(path)
   210  	if err != nil {
   211  		t.Fatalf("err: %s", err)
   212  	}
   213  	defer f.Close()
   214  
   215  	if err := terraform.WriteState(s, f); err != nil {
   216  		t.Fatalf("err: %s", err)
   217  	}
   218  
   219  	return path
   220  }
   221  
   222  // testStateOutput tests that the state at the given path contains
   223  // the expected state string.
   224  func testStateOutput(t *testing.T, path string, expected string) {
   225  	f, err := os.Open(path)
   226  	if err != nil {
   227  		t.Fatalf("err: %s", err)
   228  	}
   229  
   230  	newState, err := terraform.ReadState(f)
   231  	f.Close()
   232  	if err != nil {
   233  		t.Fatalf("err: %s", err)
   234  	}
   235  
   236  	actual := strings.TrimSpace(newState.String())
   237  	expected = strings.TrimSpace(expected)
   238  	if actual != expected {
   239  		t.Fatalf("expected:\n%s\nactual:\n%s", expected, actual)
   240  	}
   241  }
   242  
   243  func testProvider() *terraform.MockResourceProvider {
   244  	p := new(terraform.MockResourceProvider)
   245  	p.DiffReturn = &terraform.InstanceDiff{}
   246  	p.RefreshFn = func(
   247  		info *terraform.InstanceInfo,
   248  		s *terraform.InstanceState) (*terraform.InstanceState, error) {
   249  		return s, nil
   250  	}
   251  	p.ResourcesReturn = []terraform.ResourceType{
   252  		terraform.ResourceType{
   253  			Name: "test_instance",
   254  		},
   255  	}
   256  
   257  	return p
   258  }
   259  
   260  func testTempFile(t *testing.T) string {
   261  	return filepath.Join(testTempDir(t), "state.tfstate")
   262  }
   263  
   264  func testTempDir(t *testing.T) string {
   265  	d, err := ioutil.TempDir("", "tf")
   266  	if err != nil {
   267  		t.Fatalf("err: %s", err)
   268  	}
   269  
   270  	return d
   271  }
   272  
   273  // testRename renames the path to new and returns a function to defer to
   274  // revert the rename.
   275  func testRename(t *testing.T, base, path, new string) func() {
   276  	if base != "" {
   277  		path = filepath.Join(base, path)
   278  		new = filepath.Join(base, new)
   279  	}
   280  
   281  	if err := os.Rename(path, new); err != nil {
   282  		t.Fatalf("err: %s", err)
   283  	}
   284  
   285  	return func() {
   286  		// Just re-rename and ignore the return value
   287  		testRename(t, "", new, path)
   288  	}
   289  }
   290  
   291  // testChdir changes the directory and returns a function to defer to
   292  // revert the old cwd.
   293  func testChdir(t *testing.T, new string) func() {
   294  	old, err := os.Getwd()
   295  	if err != nil {
   296  		t.Fatalf("err: %s", err)
   297  	}
   298  
   299  	if err := os.Chdir(new); err != nil {
   300  		t.Fatalf("err: %v", err)
   301  	}
   302  
   303  	return func() {
   304  		// Re-run the function ignoring the defer result
   305  		testChdir(t, old)
   306  	}
   307  }
   308  
   309  // testCwd is used to change the current working directory
   310  // into a test directory that should be remoted after
   311  func testCwd(t *testing.T) (string, string) {
   312  	tmp, err := ioutil.TempDir("", "tf")
   313  	if err != nil {
   314  		t.Fatalf("err: %v", err)
   315  	}
   316  
   317  	cwd, err := os.Getwd()
   318  	if err != nil {
   319  		t.Fatalf("err: %v", err)
   320  	}
   321  
   322  	if err := os.Chdir(tmp); err != nil {
   323  		t.Fatalf("err: %v", err)
   324  	}
   325  
   326  	return tmp, cwd
   327  }
   328  
   329  // testFixCwd is used to as a defer to testDir
   330  func testFixCwd(t *testing.T, tmp, cwd string) {
   331  	if err := os.Chdir(cwd); err != nil {
   332  		t.Fatalf("err: %v", err)
   333  	}
   334  
   335  	if err := os.RemoveAll(tmp); err != nil {
   336  		t.Fatalf("err: %v", err)
   337  	}
   338  }