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 }