github.com/mehmetalisavas/terraform@v0.7.10/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 }