github.com/skyscape-cloud-services/terraform@v0.9.2-0.20170609144644-7ece028a1747/terraform/resource_address_test.go (about) 1 package terraform 2 3 import ( 4 "reflect" 5 "testing" 6 7 "github.com/hashicorp/terraform/config" 8 ) 9 10 func TestParseResourceAddressInternal(t *testing.T) { 11 cases := map[string]struct { 12 Input string 13 Expected *ResourceAddress 14 Output string 15 }{ 16 "basic resource": { 17 "aws_instance.foo", 18 &ResourceAddress{ 19 Mode: config.ManagedResourceMode, 20 Type: "aws_instance", 21 Name: "foo", 22 InstanceType: TypePrimary, 23 Index: -1, 24 }, 25 "aws_instance.foo", 26 }, 27 28 "basic resource with count": { 29 "aws_instance.foo.1", 30 &ResourceAddress{ 31 Mode: config.ManagedResourceMode, 32 Type: "aws_instance", 33 Name: "foo", 34 InstanceType: TypePrimary, 35 Index: 1, 36 }, 37 "aws_instance.foo[1]", 38 }, 39 40 "data resource": { 41 "data.aws_ami.foo", 42 &ResourceAddress{ 43 Mode: config.DataResourceMode, 44 Type: "aws_ami", 45 Name: "foo", 46 InstanceType: TypePrimary, 47 Index: -1, 48 }, 49 "data.aws_ami.foo", 50 }, 51 52 "data resource with count": { 53 "data.aws_ami.foo.1", 54 &ResourceAddress{ 55 Mode: config.DataResourceMode, 56 Type: "aws_ami", 57 Name: "foo", 58 InstanceType: TypePrimary, 59 Index: 1, 60 }, 61 "data.aws_ami.foo[1]", 62 }, 63 64 "non-data resource with 4 elements": { 65 "aws_instance.foo.bar.1", 66 nil, 67 "", 68 }, 69 } 70 71 for tn, tc := range cases { 72 t.Run(tc.Input, func(t *testing.T) { 73 out, err := parseResourceAddressInternal(tc.Input) 74 if (err != nil) != (tc.Expected == nil) { 75 t.Fatalf("%s: unexpected err: %#v", tn, err) 76 } 77 if err != nil { 78 return 79 } 80 81 if !reflect.DeepEqual(out, tc.Expected) { 82 t.Fatalf("bad: %q\n\nexpected:\n%#v\n\ngot:\n%#v", tn, tc.Expected, out) 83 } 84 85 // Compare outputs if those exist 86 expected := tc.Input 87 if tc.Output != "" { 88 expected = tc.Output 89 } 90 if out.String() != expected { 91 t.Fatalf("bad: %q\n\nexpected: %s\n\ngot: %s", tn, expected, out) 92 } 93 94 // Compare equality because the internal parse is used 95 // to compare equality to equal inputs. 96 if !out.Equals(tc.Expected) { 97 t.Fatalf("expected equality:\n\n%#v\n\n%#v", out, tc.Expected) 98 } 99 }) 100 } 101 } 102 103 func TestParseResourceAddress(t *testing.T) { 104 cases := map[string]struct { 105 Input string 106 Expected *ResourceAddress 107 Output string 108 Err bool 109 }{ 110 "implicit primary managed instance, no specific index": { 111 "aws_instance.foo", 112 &ResourceAddress{ 113 Mode: config.ManagedResourceMode, 114 Type: "aws_instance", 115 Name: "foo", 116 InstanceType: TypePrimary, 117 Index: -1, 118 }, 119 "", 120 false, 121 }, 122 "implicit primary data instance, no specific index": { 123 "data.aws_instance.foo", 124 &ResourceAddress{ 125 Mode: config.DataResourceMode, 126 Type: "aws_instance", 127 Name: "foo", 128 InstanceType: TypePrimary, 129 Index: -1, 130 }, 131 "", 132 false, 133 }, 134 "implicit primary, explicit index": { 135 "aws_instance.foo[2]", 136 &ResourceAddress{ 137 Mode: config.ManagedResourceMode, 138 Type: "aws_instance", 139 Name: "foo", 140 InstanceType: TypePrimary, 141 Index: 2, 142 }, 143 "", 144 false, 145 }, 146 "implicit primary, explicit index over ten": { 147 "aws_instance.foo[12]", 148 &ResourceAddress{ 149 Mode: config.ManagedResourceMode, 150 Type: "aws_instance", 151 Name: "foo", 152 InstanceType: TypePrimary, 153 Index: 12, 154 }, 155 "", 156 false, 157 }, 158 "explicit primary, explicit index": { 159 "aws_instance.foo.primary[2]", 160 &ResourceAddress{ 161 Mode: config.ManagedResourceMode, 162 Type: "aws_instance", 163 Name: "foo", 164 InstanceType: TypePrimary, 165 InstanceTypeSet: true, 166 Index: 2, 167 }, 168 "", 169 false, 170 }, 171 "tainted": { 172 "aws_instance.foo.tainted", 173 &ResourceAddress{ 174 Mode: config.ManagedResourceMode, 175 Type: "aws_instance", 176 Name: "foo", 177 InstanceType: TypeTainted, 178 InstanceTypeSet: true, 179 Index: -1, 180 }, 181 "", 182 false, 183 }, 184 "deposed": { 185 "aws_instance.foo.deposed", 186 &ResourceAddress{ 187 Mode: config.ManagedResourceMode, 188 Type: "aws_instance", 189 Name: "foo", 190 InstanceType: TypeDeposed, 191 InstanceTypeSet: true, 192 Index: -1, 193 }, 194 "", 195 false, 196 }, 197 "with a hyphen": { 198 "aws_instance.foo-bar", 199 &ResourceAddress{ 200 Mode: config.ManagedResourceMode, 201 Type: "aws_instance", 202 Name: "foo-bar", 203 InstanceType: TypePrimary, 204 Index: -1, 205 }, 206 "", 207 false, 208 }, 209 "managed in a module": { 210 "module.child.aws_instance.foo", 211 &ResourceAddress{ 212 Path: []string{"child"}, 213 Mode: config.ManagedResourceMode, 214 Type: "aws_instance", 215 Name: "foo", 216 InstanceType: TypePrimary, 217 Index: -1, 218 }, 219 "", 220 false, 221 }, 222 "data in a module": { 223 "module.child.data.aws_instance.foo", 224 &ResourceAddress{ 225 Path: []string{"child"}, 226 Mode: config.DataResourceMode, 227 Type: "aws_instance", 228 Name: "foo", 229 InstanceType: TypePrimary, 230 Index: -1, 231 }, 232 "", 233 false, 234 }, 235 "nested modules": { 236 "module.a.module.b.module.forever.aws_instance.foo", 237 &ResourceAddress{ 238 Path: []string{"a", "b", "forever"}, 239 Mode: config.ManagedResourceMode, 240 Type: "aws_instance", 241 Name: "foo", 242 InstanceType: TypePrimary, 243 Index: -1, 244 }, 245 "", 246 false, 247 }, 248 "just a module": { 249 "module.a", 250 &ResourceAddress{ 251 Path: []string{"a"}, 252 Type: "", 253 Name: "", 254 InstanceType: TypePrimary, 255 Index: -1, 256 }, 257 "", 258 false, 259 }, 260 "just a nested module": { 261 "module.a.module.b", 262 &ResourceAddress{ 263 Path: []string{"a", "b"}, 264 Type: "", 265 Name: "", 266 InstanceType: TypePrimary, 267 Index: -1, 268 }, 269 "", 270 false, 271 }, 272 "module missing resource type": { 273 "module.name.foo", 274 nil, 275 "", 276 true, 277 }, 278 } 279 280 for tn, tc := range cases { 281 t.Run(tn, func(t *testing.T) { 282 out, err := ParseResourceAddress(tc.Input) 283 if (err != nil) != tc.Err { 284 t.Fatalf("%s: unexpected err: %#v", tn, err) 285 } 286 if tc.Err { 287 return 288 } 289 290 if !reflect.DeepEqual(out, tc.Expected) { 291 t.Fatalf("bad: %q\n\nexpected:\n%#v\n\ngot:\n%#v", tn, tc.Expected, out) 292 } 293 294 expected := tc.Input 295 if tc.Output != "" { 296 expected = tc.Output 297 } 298 if out.String() != expected { 299 t.Fatalf("bad: %q\n\nexpected: %s\n\ngot: %s", tn, expected, out) 300 } 301 }) 302 } 303 } 304 305 func TestResourceAddressEquals(t *testing.T) { 306 cases := map[string]struct { 307 Address *ResourceAddress 308 Other interface{} 309 Expect bool 310 }{ 311 "basic match": { 312 Address: &ResourceAddress{ 313 Mode: config.ManagedResourceMode, 314 Type: "aws_instance", 315 Name: "foo", 316 InstanceType: TypePrimary, 317 Index: 0, 318 }, 319 Other: &ResourceAddress{ 320 Mode: config.ManagedResourceMode, 321 Type: "aws_instance", 322 Name: "foo", 323 InstanceType: TypePrimary, 324 Index: 0, 325 }, 326 Expect: true, 327 }, 328 "address does not set index": { 329 Address: &ResourceAddress{ 330 Mode: config.ManagedResourceMode, 331 Type: "aws_instance", 332 Name: "foo", 333 InstanceType: TypePrimary, 334 Index: -1, 335 }, 336 Other: &ResourceAddress{ 337 Mode: config.ManagedResourceMode, 338 Type: "aws_instance", 339 Name: "foo", 340 InstanceType: TypePrimary, 341 Index: 3, 342 }, 343 Expect: true, 344 }, 345 "other does not set index": { 346 Address: &ResourceAddress{ 347 Mode: config.ManagedResourceMode, 348 Type: "aws_instance", 349 Name: "foo", 350 InstanceType: TypePrimary, 351 Index: 3, 352 }, 353 Other: &ResourceAddress{ 354 Mode: config.ManagedResourceMode, 355 Type: "aws_instance", 356 Name: "foo", 357 InstanceType: TypePrimary, 358 Index: -1, 359 }, 360 Expect: true, 361 }, 362 "neither sets index": { 363 Address: &ResourceAddress{ 364 Mode: config.ManagedResourceMode, 365 Type: "aws_instance", 366 Name: "foo", 367 InstanceType: TypePrimary, 368 Index: -1, 369 }, 370 Other: &ResourceAddress{ 371 Mode: config.ManagedResourceMode, 372 Type: "aws_instance", 373 Name: "foo", 374 InstanceType: TypePrimary, 375 Index: -1, 376 }, 377 Expect: true, 378 }, 379 "index over ten": { 380 Address: &ResourceAddress{ 381 Mode: config.ManagedResourceMode, 382 Type: "aws_instance", 383 Name: "foo", 384 InstanceType: TypePrimary, 385 Index: 1, 386 }, 387 Other: &ResourceAddress{ 388 Mode: config.ManagedResourceMode, 389 Type: "aws_instance", 390 Name: "foo", 391 InstanceType: TypePrimary, 392 Index: 13, 393 }, 394 Expect: false, 395 }, 396 "different type": { 397 Address: &ResourceAddress{ 398 Mode: config.ManagedResourceMode, 399 Type: "aws_instance", 400 Name: "foo", 401 InstanceType: TypePrimary, 402 Index: 0, 403 }, 404 Other: &ResourceAddress{ 405 Mode: config.ManagedResourceMode, 406 Type: "aws_vpc", 407 Name: "foo", 408 InstanceType: TypePrimary, 409 Index: 0, 410 }, 411 Expect: false, 412 }, 413 "different mode": { 414 Address: &ResourceAddress{ 415 Mode: config.ManagedResourceMode, 416 Type: "aws_instance", 417 Name: "foo", 418 InstanceType: TypePrimary, 419 Index: 0, 420 }, 421 Other: &ResourceAddress{ 422 Mode: config.DataResourceMode, 423 Type: "aws_instance", 424 Name: "foo", 425 InstanceType: TypePrimary, 426 Index: 0, 427 }, 428 Expect: false, 429 }, 430 "different name": { 431 Address: &ResourceAddress{ 432 Mode: config.ManagedResourceMode, 433 Type: "aws_instance", 434 Name: "foo", 435 InstanceType: TypePrimary, 436 Index: 0, 437 }, 438 Other: &ResourceAddress{ 439 Mode: config.ManagedResourceMode, 440 Type: "aws_instance", 441 Name: "bar", 442 InstanceType: TypePrimary, 443 Index: 0, 444 }, 445 Expect: false, 446 }, 447 "different instance type": { 448 Address: &ResourceAddress{ 449 Mode: config.ManagedResourceMode, 450 Type: "aws_instance", 451 Name: "foo", 452 InstanceType: TypePrimary, 453 Index: 0, 454 }, 455 Other: &ResourceAddress{ 456 Mode: config.ManagedResourceMode, 457 Type: "aws_instance", 458 Name: "foo", 459 InstanceType: TypeTainted, 460 Index: 0, 461 }, 462 Expect: false, 463 }, 464 "different index": { 465 Address: &ResourceAddress{ 466 Mode: config.ManagedResourceMode, 467 Type: "aws_instance", 468 Name: "foo", 469 InstanceType: TypePrimary, 470 Index: 0, 471 }, 472 Other: &ResourceAddress{ 473 Mode: config.ManagedResourceMode, 474 Type: "aws_instance", 475 Name: "foo", 476 InstanceType: TypePrimary, 477 Index: 1, 478 }, 479 Expect: false, 480 }, 481 "module address matches address of managed resource inside module": { 482 Address: &ResourceAddress{ 483 Path: []string{"a", "b"}, 484 Type: "", 485 Name: "", 486 InstanceType: TypePrimary, 487 Index: -1, 488 }, 489 Other: &ResourceAddress{ 490 Path: []string{"a", "b"}, 491 Mode: config.ManagedResourceMode, 492 Type: "aws_instance", 493 Name: "foo", 494 InstanceType: TypePrimary, 495 Index: 0, 496 }, 497 Expect: true, 498 }, 499 "module address matches address of data resource inside module": { 500 Address: &ResourceAddress{ 501 Path: []string{"a", "b"}, 502 Type: "", 503 Name: "", 504 InstanceType: TypePrimary, 505 Index: -1, 506 }, 507 Other: &ResourceAddress{ 508 Path: []string{"a", "b"}, 509 Mode: config.DataResourceMode, 510 Type: "aws_instance", 511 Name: "foo", 512 InstanceType: TypePrimary, 513 Index: 0, 514 }, 515 Expect: true, 516 }, 517 "module address doesn't match managed resource outside module": { 518 Address: &ResourceAddress{ 519 Path: []string{"a", "b"}, 520 Type: "", 521 Name: "", 522 InstanceType: TypePrimary, 523 Index: -1, 524 }, 525 Other: &ResourceAddress{ 526 Path: []string{"a"}, 527 Mode: config.ManagedResourceMode, 528 Type: "aws_instance", 529 Name: "foo", 530 InstanceType: TypePrimary, 531 Index: 0, 532 }, 533 Expect: false, 534 }, 535 "module address doesn't match data resource outside module": { 536 Address: &ResourceAddress{ 537 Path: []string{"a", "b"}, 538 Type: "", 539 Name: "", 540 InstanceType: TypePrimary, 541 Index: -1, 542 }, 543 Other: &ResourceAddress{ 544 Path: []string{"a"}, 545 Mode: config.DataResourceMode, 546 Type: "aws_instance", 547 Name: "foo", 548 InstanceType: TypePrimary, 549 Index: 0, 550 }, 551 Expect: false, 552 }, 553 "nil path vs empty path should match": { 554 Address: &ResourceAddress{ 555 Path: []string{}, 556 Mode: config.ManagedResourceMode, 557 Type: "aws_instance", 558 Name: "foo", 559 InstanceType: TypePrimary, 560 Index: -1, 561 }, 562 Other: &ResourceAddress{ 563 Path: nil, 564 Mode: config.ManagedResourceMode, 565 Type: "aws_instance", 566 Name: "foo", 567 InstanceType: TypePrimary, 568 Index: 0, 569 }, 570 Expect: true, 571 }, 572 } 573 574 for tn, tc := range cases { 575 actual := tc.Address.Equals(tc.Other) 576 if actual != tc.Expect { 577 t.Fatalf("%q: expected equals: %t, got %t for:\n%#v\n%#v", 578 tn, tc.Expect, actual, tc.Address, tc.Other) 579 } 580 } 581 } 582 583 func TestResourceAddressStateId(t *testing.T) { 584 cases := map[string]struct { 585 Input *ResourceAddress 586 Expected string 587 }{ 588 "basic resource": { 589 &ResourceAddress{ 590 Mode: config.ManagedResourceMode, 591 Type: "aws_instance", 592 Name: "foo", 593 InstanceType: TypePrimary, 594 Index: -1, 595 }, 596 "aws_instance.foo", 597 }, 598 599 "basic resource with index": { 600 &ResourceAddress{ 601 Mode: config.ManagedResourceMode, 602 Type: "aws_instance", 603 Name: "foo", 604 InstanceType: TypePrimary, 605 Index: 2, 606 }, 607 "aws_instance.foo.2", 608 }, 609 610 "data resource": { 611 &ResourceAddress{ 612 Mode: config.DataResourceMode, 613 Type: "aws_instance", 614 Name: "foo", 615 InstanceType: TypePrimary, 616 Index: -1, 617 }, 618 "data.aws_instance.foo", 619 }, 620 } 621 622 for tn, tc := range cases { 623 t.Run(tn, func(t *testing.T) { 624 actual := tc.Input.stateId() 625 if actual != tc.Expected { 626 t.Fatalf("bad: %q\n\nexpected: %s\n\ngot: %s", tn, tc.Expected, actual) 627 } 628 }) 629 } 630 }