github.com/nalum/terraform@v0.3.2-0.20141223102918-aa2c22ffeff6/command/remote_test.go (about) 1 package command 2 3 import ( 4 "bytes" 5 "io/ioutil" 6 "os" 7 "testing" 8 9 "github.com/hashicorp/terraform/remote" 10 "github.com/hashicorp/terraform/terraform" 11 "github.com/mitchellh/cli" 12 ) 13 14 // Test disabling remote management 15 func TestRemote_disable(t *testing.T) { 16 tmp, cwd := testCwd(t) 17 defer testFixCwd(t, tmp, cwd) 18 19 // Create remote state file, this should be pulled 20 s := terraform.NewState() 21 s.Serial = 10 22 conf, srv := testRemoteState(t, s, 200) 23 defer srv.Close() 24 25 // Persist local remote state 26 s = terraform.NewState() 27 s.Serial = 5 28 s.Remote = conf 29 if err := remote.EnsureDirectory(); err != nil { 30 t.Fatalf("err: %v", err) 31 } 32 if err := remote.PersistState(s); err != nil { 33 t.Fatalf("err: %v", err) 34 } 35 36 ui := new(cli.MockUi) 37 c := &RemoteCommand{ 38 Meta: Meta{ 39 ContextOpts: testCtxConfig(testProvider()), 40 Ui: ui, 41 }, 42 } 43 args := []string{"-disable"} 44 if code := c.Run(args); code != 0 { 45 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 46 } 47 48 // Local state file should be removed 49 haveLocal, err := remote.HaveLocalState() 50 if err != nil { 51 t.Fatalf("err: %v", err) 52 } 53 if haveLocal { 54 t.Fatalf("should be disabled") 55 } 56 57 // New state file should be installed 58 exists, err := remote.ExistsFile(DefaultStateFilename) 59 if err != nil { 60 t.Fatalf("err: %v", err) 61 } 62 if !exists { 63 t.Fatalf("failed to make state file") 64 } 65 66 // Check that the state file was updated 67 raw, _ := ioutil.ReadFile(DefaultStateFilename) 68 newState, err := terraform.ReadState(bytes.NewReader(raw)) 69 if err != nil { 70 t.Fatalf("err: %v", err) 71 } 72 73 // Ensure we updated 74 // TODO: Should be 10, but WriteState currently 75 // increments incorrectly 76 if newState.Serial != 11 { 77 t.Fatalf("state file not updated: %#v", newState) 78 } 79 if newState.Remote != nil { 80 t.Fatalf("remote configuration not removed") 81 } 82 } 83 84 // Test disabling remote management without pulling 85 func TestRemote_disable_noPull(t *testing.T) { 86 tmp, cwd := testCwd(t) 87 defer testFixCwd(t, tmp, cwd) 88 89 // Create remote state file, this should be pulled 90 s := terraform.NewState() 91 s.Serial = 10 92 conf, srv := testRemoteState(t, s, 200) 93 defer srv.Close() 94 95 // Persist local remote state 96 s = terraform.NewState() 97 s.Serial = 5 98 s.Remote = conf 99 if err := remote.EnsureDirectory(); err != nil { 100 t.Fatalf("err: %v", err) 101 } 102 if err := remote.PersistState(s); err != nil { 103 t.Fatalf("err: %v", err) 104 } 105 106 ui := new(cli.MockUi) 107 c := &RemoteCommand{ 108 Meta: Meta{ 109 ContextOpts: testCtxConfig(testProvider()), 110 Ui: ui, 111 }, 112 } 113 args := []string{"-disable", "-pull=false"} 114 if code := c.Run(args); code != 0 { 115 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 116 } 117 118 // Local state file should be removed 119 haveLocal, err := remote.HaveLocalState() 120 if err != nil { 121 t.Fatalf("err: %v", err) 122 } 123 if haveLocal { 124 t.Fatalf("should be disabled") 125 } 126 127 // New state file should be installed 128 exists, err := remote.ExistsFile(DefaultStateFilename) 129 if err != nil { 130 t.Fatalf("err: %v", err) 131 } 132 if !exists { 133 t.Fatalf("failed to make state file") 134 } 135 136 // Check that the state file was updated 137 raw, _ := ioutil.ReadFile(DefaultStateFilename) 138 newState, err := terraform.ReadState(bytes.NewReader(raw)) 139 if err != nil { 140 t.Fatalf("err: %v", err) 141 } 142 143 // Ensure we DIDNT updated 144 // TODO: Should be 5, but WriteState currently increments 145 // this which is incorrect. 146 if newState.Serial != 7 { 147 t.Fatalf("state file updated: %#v", newState) 148 } 149 if newState.Remote != nil { 150 t.Fatalf("remote configuration not removed") 151 } 152 } 153 154 // Test disabling remote management when not enabled 155 func TestRemote_disable_notEnabled(t *testing.T) { 156 tmp, cwd := testCwd(t) 157 defer testFixCwd(t, tmp, cwd) 158 159 ui := new(cli.MockUi) 160 c := &RemoteCommand{ 161 Meta: Meta{ 162 ContextOpts: testCtxConfig(testProvider()), 163 Ui: ui, 164 }, 165 } 166 167 args := []string{"-disable"} 168 if code := c.Run(args); code != 1 { 169 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 170 } 171 } 172 173 // Test disabling remote management with a state file in the way 174 func TestRemote_disable_otherState(t *testing.T) { 175 tmp, cwd := testCwd(t) 176 defer testFixCwd(t, tmp, cwd) 177 178 // Persist local remote state 179 s := terraform.NewState() 180 s.Serial = 5 181 if err := remote.EnsureDirectory(); err != nil { 182 t.Fatalf("err: %v", err) 183 } 184 if err := remote.PersistState(s); err != nil { 185 t.Fatalf("err: %v", err) 186 } 187 188 // Also put a file at the default path 189 fh, err := os.Create(DefaultStateFilename) 190 if err != nil { 191 t.Fatalf("err: %v", err) 192 } 193 err = terraform.WriteState(s, fh) 194 fh.Close() 195 if err != nil { 196 t.Fatalf("err: %v", err) 197 } 198 199 ui := new(cli.MockUi) 200 c := &RemoteCommand{ 201 Meta: Meta{ 202 ContextOpts: testCtxConfig(testProvider()), 203 Ui: ui, 204 }, 205 } 206 207 args := []string{"-disable"} 208 if code := c.Run(args); code != 1 { 209 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 210 } 211 } 212 213 // Test the case where both managed and non managed state present 214 func TestRemote_managedAndNonManaged(t *testing.T) { 215 tmp, cwd := testCwd(t) 216 defer testFixCwd(t, tmp, cwd) 217 218 // Persist local remote state 219 s := terraform.NewState() 220 s.Serial = 5 221 if err := remote.EnsureDirectory(); err != nil { 222 t.Fatalf("err: %v", err) 223 } 224 if err := remote.PersistState(s); err != nil { 225 t.Fatalf("err: %v", err) 226 } 227 228 // Also put a file at the default path 229 fh, err := os.Create(DefaultStateFilename) 230 if err != nil { 231 t.Fatalf("err: %v", err) 232 } 233 err = terraform.WriteState(s, fh) 234 fh.Close() 235 if err != nil { 236 t.Fatalf("err: %v", err) 237 } 238 239 ui := new(cli.MockUi) 240 c := &RemoteCommand{ 241 Meta: Meta{ 242 ContextOpts: testCtxConfig(testProvider()), 243 Ui: ui, 244 }, 245 } 246 247 args := []string{} 248 if code := c.Run(args); code != 1 { 249 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 250 } 251 } 252 253 // Test initializing blank state 254 func TestRemote_initBlank(t *testing.T) { 255 tmp, cwd := testCwd(t) 256 defer testFixCwd(t, tmp, cwd) 257 258 ui := new(cli.MockUi) 259 c := &RemoteCommand{ 260 Meta: Meta{ 261 ContextOpts: testCtxConfig(testProvider()), 262 Ui: ui, 263 }, 264 } 265 266 args := []string{ 267 "-backend=http", 268 "-address", "http://example.com", 269 "-access-token=test", 270 } 271 if code := c.Run(args); code != 0 { 272 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 273 } 274 275 local, _, err := remote.ReadLocalState() 276 if err != nil { 277 t.Fatalf("err: %v", err) 278 } 279 280 if local.Remote.Type != "http" { 281 t.Fatalf("Bad: %#v", local.Remote) 282 } 283 if local.Remote.Config["address"] != "http://example.com" { 284 t.Fatalf("Bad: %#v", local.Remote) 285 } 286 if local.Remote.Config["access_token"] != "test" { 287 t.Fatalf("Bad: %#v", local.Remote) 288 } 289 } 290 291 // Test initializing without remote settings 292 func TestRemote_initBlank_missingRemote(t *testing.T) { 293 tmp, cwd := testCwd(t) 294 defer testFixCwd(t, tmp, cwd) 295 296 ui := new(cli.MockUi) 297 c := &RemoteCommand{ 298 Meta: Meta{ 299 ContextOpts: testCtxConfig(testProvider()), 300 Ui: ui, 301 }, 302 } 303 304 args := []string{} 305 if code := c.Run(args); code != 1 { 306 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 307 } 308 } 309 310 // Test updating remote config 311 func TestRemote_updateRemote(t *testing.T) { 312 tmp, cwd := testCwd(t) 313 defer testFixCwd(t, tmp, cwd) 314 315 // Persist local remote state 316 s := terraform.NewState() 317 s.Serial = 5 318 s.Remote = &terraform.RemoteState{ 319 Type: "invalid", 320 } 321 if err := remote.EnsureDirectory(); err != nil { 322 t.Fatalf("err: %v", err) 323 } 324 if err := remote.PersistState(s); err != nil { 325 t.Fatalf("err: %v", err) 326 } 327 328 ui := new(cli.MockUi) 329 c := &RemoteCommand{ 330 Meta: Meta{ 331 ContextOpts: testCtxConfig(testProvider()), 332 Ui: ui, 333 }, 334 } 335 336 args := []string{ 337 "-backend=http", 338 "-address", 339 "http://example.com", 340 "-access-token=test", 341 } 342 if code := c.Run(args); code != 0 { 343 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 344 } 345 346 local, _, err := remote.ReadLocalState() 347 if err != nil { 348 t.Fatalf("err: %v", err) 349 } 350 351 if local.Remote.Type != "http" { 352 t.Fatalf("Bad: %#v", local.Remote) 353 } 354 if local.Remote.Config["address"] != "http://example.com" { 355 t.Fatalf("Bad: %#v", local.Remote) 356 } 357 if local.Remote.Config["access_token"] != "test" { 358 t.Fatalf("Bad: %#v", local.Remote) 359 } 360 } 361 362 // Test enabling remote state 363 func TestRemote_enableRemote(t *testing.T) { 364 tmp, cwd := testCwd(t) 365 defer testFixCwd(t, tmp, cwd) 366 367 // Create a non-remote enabled state 368 s := terraform.NewState() 369 s.Serial = 5 370 371 // Add the state at the default path 372 fh, err := os.Create(DefaultStateFilename) 373 if err != nil { 374 t.Fatalf("err: %v", err) 375 } 376 err = terraform.WriteState(s, fh) 377 fh.Close() 378 if err != nil { 379 t.Fatalf("err: %v", err) 380 } 381 382 ui := new(cli.MockUi) 383 c := &RemoteCommand{ 384 Meta: Meta{ 385 ContextOpts: testCtxConfig(testProvider()), 386 Ui: ui, 387 }, 388 } 389 390 args := []string{ 391 "-backend=http", 392 "-address", 393 "http://example.com", 394 "-access-token=test", 395 } 396 if code := c.Run(args); code != 0 { 397 t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) 398 } 399 400 local, _, err := remote.ReadLocalState() 401 if err != nil { 402 t.Fatalf("err: %v", err) 403 } 404 405 if local.Remote.Type != "http" { 406 t.Fatalf("Bad: %#v", local.Remote) 407 } 408 if local.Remote.Config["address"] != "http://example.com" { 409 t.Fatalf("Bad: %#v", local.Remote) 410 } 411 if local.Remote.Config["access_token"] != "test" { 412 t.Fatalf("Bad: %#v", local.Remote) 413 } 414 415 // Backup file should exist 416 exist, err := remote.ExistsFile(DefaultStateFilename + DefaultBackupExtention) 417 if err != nil { 418 t.Fatalf("err: %v", err) 419 } 420 if !exist { 421 t.Fatalf("backup should exist") 422 } 423 424 // State file should not 425 exist, err = remote.ExistsFile(DefaultStateFilename) 426 if err != nil { 427 t.Fatalf("err: %v", err) 428 } 429 if exist { 430 t.Fatalf("state file should not exist") 431 } 432 }