github.com/memsql/terraform@v0.7.0-rc2.0.20160706152241-21e2173e0a32/terraform/context_input_test.go (about) 1 package terraform 2 3 import ( 4 "reflect" 5 "strings" 6 "sync" 7 "testing" 8 ) 9 10 func TestContext2Input(t *testing.T) { 11 input := new(MockUIInput) 12 m := testModule(t, "input-vars") 13 p := testProvider("aws") 14 p.ApplyFn = testApplyFn 15 p.DiffFn = testDiffFn 16 ctx := testContext2(t, &ContextOpts{ 17 Module: m, 18 Providers: map[string]ResourceProviderFactory{ 19 "aws": testProviderFuncFixed(p), 20 }, 21 Variables: map[string]string{ 22 "foo": "us-west-2", 23 "amis.us-east-1": "override", 24 }, 25 UIInput: input, 26 }) 27 28 input.InputReturnMap = map[string]string{ 29 "var.foo": "us-east-1", 30 } 31 32 if err := ctx.Input(InputModeStd); err != nil { 33 t.Fatalf("err: %s", err) 34 } 35 36 if _, err := ctx.Plan(); err != nil { 37 t.Fatalf("err: %s", err) 38 } 39 40 state, err := ctx.Apply() 41 if err != nil { 42 t.Fatalf("err: %s", err) 43 } 44 45 actual := strings.TrimSpace(state.String()) 46 expected := strings.TrimSpace(testTerraformInputVarsStr) 47 if actual != expected { 48 t.Fatalf("expected:\n%s\ngot:\n%s", expected, actual) 49 } 50 } 51 52 func TestContext2Input_moduleComputedOutputElement(t *testing.T) { 53 m := testModule(t, "input-module-computed-output-element") 54 p := testProvider("aws") 55 p.ApplyFn = testApplyFn 56 p.DiffFn = testDiffFn 57 ctx := testContext2(t, &ContextOpts{ 58 Module: m, 59 Providers: map[string]ResourceProviderFactory{ 60 "aws": testProviderFuncFixed(p), 61 }, 62 }) 63 64 p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { 65 return c, nil 66 } 67 68 if err := ctx.Input(InputModeStd); err != nil { 69 t.Fatalf("err: %s", err) 70 } 71 } 72 73 func TestContext2Input_badVarDefault(t *testing.T) { 74 m := testModule(t, "input-bad-var-default") 75 p := testProvider("aws") 76 p.ApplyFn = testApplyFn 77 p.DiffFn = testDiffFn 78 ctx := testContext2(t, &ContextOpts{ 79 Module: m, 80 Providers: map[string]ResourceProviderFactory{ 81 "aws": testProviderFuncFixed(p), 82 }, 83 }) 84 85 p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { 86 c.Config["foo"] = "bar" 87 return c, nil 88 } 89 90 if err := ctx.Input(InputModeStd); err != nil { 91 t.Fatalf("err: %s", err) 92 } 93 } 94 95 func TestContext2Input_provider(t *testing.T) { 96 m := testModule(t, "input-provider") 97 p := testProvider("aws") 98 p.ApplyFn = testApplyFn 99 p.DiffFn = testDiffFn 100 ctx := testContext2(t, &ContextOpts{ 101 Module: m, 102 Providers: map[string]ResourceProviderFactory{ 103 "aws": testProviderFuncFixed(p), 104 }, 105 }) 106 107 var actual interface{} 108 p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { 109 c.Config["foo"] = "bar" 110 return c, nil 111 } 112 p.ConfigureFn = func(c *ResourceConfig) error { 113 actual = c.Config["foo"] 114 return nil 115 } 116 p.ValidateFn = func(c *ResourceConfig) ([]string, []error) { 117 return nil, c.CheckSet([]string{"foo"}) 118 } 119 120 if err := ctx.Input(InputModeStd); err != nil { 121 t.Fatalf("err: %s", err) 122 } 123 124 if _, err := ctx.Plan(); err != nil { 125 t.Fatalf("err: %s", err) 126 } 127 128 if _, err := ctx.Apply(); err != nil { 129 t.Fatalf("err: %s", err) 130 } 131 132 if !reflect.DeepEqual(actual, "bar") { 133 t.Fatalf("bad: %#v", actual) 134 } 135 } 136 137 func TestContext2Input_providerMulti(t *testing.T) { 138 m := testModule(t, "input-provider-multi") 139 p := testProvider("aws") 140 p.ApplyFn = testApplyFn 141 p.DiffFn = testDiffFn 142 ctx := testContext2(t, &ContextOpts{ 143 Module: m, 144 Providers: map[string]ResourceProviderFactory{ 145 "aws": testProviderFuncFixed(p), 146 }, 147 }) 148 149 var actual []interface{} 150 var lock sync.Mutex 151 p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { 152 c.Config["foo"] = "bar" 153 return c, nil 154 } 155 p.ConfigureFn = func(c *ResourceConfig) error { 156 lock.Lock() 157 defer lock.Unlock() 158 actual = append(actual, c.Config["foo"]) 159 return nil 160 } 161 p.ValidateFn = func(c *ResourceConfig) ([]string, []error) { 162 return nil, c.CheckSet([]string{"foo"}) 163 } 164 165 if err := ctx.Input(InputModeStd); err != nil { 166 t.Fatalf("err: %s", err) 167 } 168 169 if _, err := ctx.Plan(); err != nil { 170 t.Fatalf("err: %s", err) 171 } 172 173 if _, err := ctx.Apply(); err != nil { 174 t.Fatalf("err: %s", err) 175 } 176 177 expected := []interface{}{"bar", "bar"} 178 if !reflect.DeepEqual(actual, expected) { 179 t.Fatalf("bad: %#v", actual) 180 } 181 } 182 183 func TestContext2Input_providerOnce(t *testing.T) { 184 m := testModule(t, "input-provider-once") 185 p := testProvider("aws") 186 p.ApplyFn = testApplyFn 187 p.DiffFn = testDiffFn 188 ctx := testContext2(t, &ContextOpts{ 189 Module: m, 190 Providers: map[string]ResourceProviderFactory{ 191 "aws": testProviderFuncFixed(p), 192 }, 193 }) 194 195 count := 0 196 p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { 197 count++ 198 return nil, nil 199 } 200 201 if err := ctx.Input(InputModeStd); err != nil { 202 t.Fatalf("err: %s", err) 203 } 204 205 if count != 1 { 206 t.Fatalf("should only be called once: %d", count) 207 } 208 } 209 210 func TestContext2Input_providerId(t *testing.T) { 211 input := new(MockUIInput) 212 m := testModule(t, "input-provider") 213 p := testProvider("aws") 214 p.ApplyFn = testApplyFn 215 p.DiffFn = testDiffFn 216 ctx := testContext2(t, &ContextOpts{ 217 Module: m, 218 Providers: map[string]ResourceProviderFactory{ 219 "aws": testProviderFuncFixed(p), 220 }, 221 UIInput: input, 222 }) 223 224 var actual interface{} 225 p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { 226 v, err := i.Input(&InputOpts{Id: "foo"}) 227 if err != nil { 228 return nil, err 229 } 230 231 c.Config["foo"] = v 232 return c, nil 233 } 234 p.ConfigureFn = func(c *ResourceConfig) error { 235 actual = c.Config["foo"] 236 return nil 237 } 238 239 input.InputReturnMap = map[string]string{ 240 "provider.aws.foo": "bar", 241 } 242 243 if err := ctx.Input(InputModeStd); err != nil { 244 t.Fatalf("err: %s", err) 245 } 246 247 if _, err := ctx.Plan(); err != nil { 248 t.Fatalf("err: %s", err) 249 } 250 251 if _, err := ctx.Apply(); err != nil { 252 t.Fatalf("err: %s", err) 253 } 254 255 if !reflect.DeepEqual(actual, "bar") { 256 t.Fatalf("bad: %#v", actual) 257 } 258 } 259 260 func TestContext2Input_providerOnly(t *testing.T) { 261 input := new(MockUIInput) 262 m := testModule(t, "input-provider-vars") 263 p := testProvider("aws") 264 p.ApplyFn = testApplyFn 265 p.DiffFn = testDiffFn 266 ctx := testContext2(t, &ContextOpts{ 267 Module: m, 268 Providers: map[string]ResourceProviderFactory{ 269 "aws": testProviderFuncFixed(p), 270 }, 271 Variables: map[string]string{ 272 "foo": "us-west-2", 273 }, 274 UIInput: input, 275 }) 276 277 input.InputReturnMap = map[string]string{ 278 "var.foo": "us-east-1", 279 } 280 281 var actual interface{} 282 p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { 283 c.Config["foo"] = "bar" 284 return c, nil 285 } 286 p.ConfigureFn = func(c *ResourceConfig) error { 287 actual = c.Config["foo"] 288 return nil 289 } 290 291 if err := ctx.Input(InputModeProvider); err != nil { 292 t.Fatalf("err: %s", err) 293 } 294 295 if _, err := ctx.Plan(); err != nil { 296 t.Fatalf("err: %s", err) 297 } 298 299 state, err := ctx.Apply() 300 if err != nil { 301 t.Fatalf("err: %s", err) 302 } 303 304 if !reflect.DeepEqual(actual, "bar") { 305 t.Fatalf("bad: %#v", actual) 306 } 307 308 actualStr := strings.TrimSpace(state.String()) 309 expectedStr := strings.TrimSpace(testTerraformInputProviderOnlyStr) 310 if actualStr != expectedStr { 311 t.Fatalf("bad: \n%s", actualStr) 312 } 313 } 314 315 func TestContext2Input_providerVars(t *testing.T) { 316 input := new(MockUIInput) 317 m := testModule(t, "input-provider-with-vars") 318 p := testProvider("aws") 319 p.ApplyFn = testApplyFn 320 p.DiffFn = testDiffFn 321 ctx := testContext2(t, &ContextOpts{ 322 Module: m, 323 Providers: map[string]ResourceProviderFactory{ 324 "aws": testProviderFuncFixed(p), 325 }, 326 Variables: map[string]string{ 327 "foo": "bar", 328 }, 329 UIInput: input, 330 }) 331 332 input.InputReturnMap = map[string]string{ 333 "var.foo": "bar", 334 } 335 336 var actual interface{} 337 p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { 338 c.Config["bar"] = "baz" 339 return c, nil 340 } 341 p.ConfigureFn = func(c *ResourceConfig) error { 342 actual, _ = c.Get("foo") 343 return nil 344 } 345 346 if err := ctx.Input(InputModeStd); err != nil { 347 t.Fatalf("err: %s", err) 348 } 349 350 if _, err := ctx.Plan(); err != nil { 351 t.Fatalf("err: %s", err) 352 } 353 354 if _, err := ctx.Apply(); err != nil { 355 t.Fatalf("err: %s", err) 356 } 357 358 if !reflect.DeepEqual(actual, "bar") { 359 t.Fatalf("bad: %#v", actual) 360 } 361 } 362 363 func TestContext2Input_providerVarsModuleInherit(t *testing.T) { 364 input := new(MockUIInput) 365 m := testModule(t, "input-provider-with-vars-and-module") 366 p := testProvider("aws") 367 p.ApplyFn = testApplyFn 368 p.DiffFn = testDiffFn 369 ctx := testContext2(t, &ContextOpts{ 370 Module: m, 371 Providers: map[string]ResourceProviderFactory{ 372 "aws": testProviderFuncFixed(p), 373 }, 374 UIInput: input, 375 }) 376 377 p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { 378 if errs := c.CheckSet([]string{"access_key"}); len(errs) > 0 { 379 return c, errs[0] 380 } 381 return c, nil 382 } 383 p.ConfigureFn = func(c *ResourceConfig) error { 384 return nil 385 } 386 387 if err := ctx.Input(InputModeStd); err != nil { 388 t.Fatalf("err: %s", err) 389 } 390 } 391 392 func TestContext2Input_varOnly(t *testing.T) { 393 input := new(MockUIInput) 394 m := testModule(t, "input-provider-vars") 395 p := testProvider("aws") 396 p.ApplyFn = testApplyFn 397 p.DiffFn = testDiffFn 398 ctx := testContext2(t, &ContextOpts{ 399 Module: m, 400 Providers: map[string]ResourceProviderFactory{ 401 "aws": testProviderFuncFixed(p), 402 }, 403 Variables: map[string]string{ 404 "foo": "us-west-2", 405 }, 406 UIInput: input, 407 }) 408 409 input.InputReturnMap = map[string]string{ 410 "var.foo": "us-east-1", 411 } 412 413 var actual interface{} 414 p.InputFn = func(i UIInput, c *ResourceConfig) (*ResourceConfig, error) { 415 c.Raw["foo"] = "bar" 416 return c, nil 417 } 418 p.ConfigureFn = func(c *ResourceConfig) error { 419 actual = c.Raw["foo"] 420 return nil 421 } 422 423 if err := ctx.Input(InputModeVar); err != nil { 424 t.Fatalf("err: %s", err) 425 } 426 427 if _, err := ctx.Plan(); err != nil { 428 t.Fatalf("err: %s", err) 429 } 430 431 state, err := ctx.Apply() 432 if err != nil { 433 t.Fatalf("err: %s", err) 434 } 435 436 if reflect.DeepEqual(actual, "bar") { 437 t.Fatalf("bad: %#v", actual) 438 } 439 440 actualStr := strings.TrimSpace(state.String()) 441 expectedStr := strings.TrimSpace(testTerraformInputVarOnlyStr) 442 if actualStr != expectedStr { 443 t.Fatalf("bad: \n%s", actualStr) 444 } 445 } 446 447 func TestContext2Input_varOnlyUnset(t *testing.T) { 448 input := new(MockUIInput) 449 m := testModule(t, "input-vars-unset") 450 p := testProvider("aws") 451 p.ApplyFn = testApplyFn 452 p.DiffFn = testDiffFn 453 ctx := testContext2(t, &ContextOpts{ 454 Module: m, 455 Providers: map[string]ResourceProviderFactory{ 456 "aws": testProviderFuncFixed(p), 457 }, 458 Variables: map[string]string{ 459 "foo": "foovalue", 460 }, 461 UIInput: input, 462 }) 463 464 input.InputReturnMap = map[string]string{ 465 "var.foo": "nope", 466 "var.bar": "baz", 467 } 468 469 if err := ctx.Input(InputModeVar | InputModeVarUnset); err != nil { 470 t.Fatalf("err: %s", err) 471 } 472 473 if _, err := ctx.Plan(); err != nil { 474 t.Fatalf("err: %s", err) 475 } 476 477 state, err := ctx.Apply() 478 if err != nil { 479 t.Fatalf("err: %s", err) 480 } 481 482 actualStr := strings.TrimSpace(state.String()) 483 expectedStr := strings.TrimSpace(testTerraformInputVarOnlyUnsetStr) 484 if actualStr != expectedStr { 485 t.Fatalf("bad: \n%s", actualStr) 486 } 487 } 488 489 func TestContext2Input_varWithDefault(t *testing.T) { 490 input := new(MockUIInput) 491 m := testModule(t, "input-var-default") 492 p := testProvider("aws") 493 p.ApplyFn = testApplyFn 494 p.DiffFn = testDiffFn 495 ctx := testContext2(t, &ContextOpts{ 496 Module: m, 497 Providers: map[string]ResourceProviderFactory{ 498 "aws": testProviderFuncFixed(p), 499 }, 500 Variables: map[string]string{}, 501 UIInput: input, 502 }) 503 504 input.InputFn = func(opts *InputOpts) (string, error) { 505 t.Fatalf( 506 "Input should never be called because variable has a default: %#v", opts) 507 return "", nil 508 } 509 510 if err := ctx.Input(InputModeVar | InputModeVarUnset); err != nil { 511 t.Fatalf("err: %s", err) 512 } 513 514 if _, err := ctx.Plan(); err != nil { 515 t.Fatalf("err: %s", err) 516 } 517 518 state, err := ctx.Apply() 519 if err != nil { 520 t.Fatalf("err: %s", err) 521 } 522 523 actualStr := strings.TrimSpace(state.String()) 524 expectedStr := strings.TrimSpace(` 525 aws_instance.foo: 526 ID = foo 527 foo = 123 528 type = aws_instance 529 `) 530 if actualStr != expectedStr { 531 t.Fatalf("expected: \n%s\ngot: \n%s\n", expectedStr, actualStr) 532 } 533 } 534 535 func TestContext2Input_varPartiallyComputed(t *testing.T) { 536 input := new(MockUIInput) 537 m := testModule(t, "input-var-partially-computed") 538 p := testProvider("aws") 539 p.ApplyFn = testApplyFn 540 p.DiffFn = testDiffFn 541 ctx := testContext2(t, &ContextOpts{ 542 Module: m, 543 Providers: map[string]ResourceProviderFactory{ 544 "aws": testProviderFuncFixed(p), 545 }, 546 Variables: map[string]string{ 547 "foo": "foovalue", 548 }, 549 UIInput: input, 550 State: &State{ 551 Modules: []*ModuleState{ 552 &ModuleState{ 553 Path: rootModulePath, 554 Resources: map[string]*ResourceState{ 555 "aws_instance.foo": &ResourceState{ 556 Type: "aws_instance", 557 Primary: &InstanceState{ 558 ID: "i-abc123", 559 Attributes: map[string]string{ 560 "id": "i-abc123", 561 }, 562 }, 563 }, 564 }, 565 }, 566 &ModuleState{ 567 Path: append(rootModulePath, "child"), 568 Resources: map[string]*ResourceState{ 569 "aws_instance.mod": &ResourceState{ 570 Type: "aws_instance", 571 Primary: &InstanceState{ 572 ID: "i-bcd345", 573 Attributes: map[string]string{ 574 "id": "i-bcd345", 575 "value": "one,i-abc123", 576 }, 577 }, 578 }, 579 }, 580 }, 581 }, 582 }, 583 }) 584 585 if err := ctx.Input(InputModeStd); err != nil { 586 t.Fatalf("err: %s", err) 587 } 588 589 if _, err := ctx.Plan(); err != nil { 590 t.Fatalf("err: %s", err) 591 } 592 } 593 594 // Module variables weren't being interpolated during the Input walk. 595 // https://github.com/hashicorp/terraform/issues/5322 596 func TestContext2Input_interpolateVar(t *testing.T) { 597 input := new(MockUIInput) 598 599 m := testModule(t, "input-interpolate-var") 600 p := testProvider("null") 601 p.ApplyFn = testApplyFn 602 p.DiffFn = testDiffFn 603 604 ctx := testContext2(t, &ContextOpts{ 605 Module: m, 606 Providers: map[string]ResourceProviderFactory{ 607 "template": testProviderFuncFixed(p), 608 }, 609 UIInput: input, 610 }) 611 612 if err := ctx.Input(InputModeStd); err != nil { 613 t.Fatalf("err: %s", err) 614 } 615 }