github.com/ns1/terraform@v0.7.10-0.20161109153551-8949419bef40/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 }{ 109 "implicit primary managed instance, no specific index": { 110 "aws_instance.foo", 111 &ResourceAddress{ 112 Mode: config.ManagedResourceMode, 113 Type: "aws_instance", 114 Name: "foo", 115 InstanceType: TypePrimary, 116 Index: -1, 117 }, 118 "", 119 }, 120 "implicit primary data instance, no specific index": { 121 "data.aws_instance.foo", 122 &ResourceAddress{ 123 Mode: config.DataResourceMode, 124 Type: "aws_instance", 125 Name: "foo", 126 InstanceType: TypePrimary, 127 Index: -1, 128 }, 129 "", 130 }, 131 "implicit primary, explicit index": { 132 "aws_instance.foo[2]", 133 &ResourceAddress{ 134 Mode: config.ManagedResourceMode, 135 Type: "aws_instance", 136 Name: "foo", 137 InstanceType: TypePrimary, 138 Index: 2, 139 }, 140 "", 141 }, 142 "implicit primary, explicit index over ten": { 143 "aws_instance.foo[12]", 144 &ResourceAddress{ 145 Mode: config.ManagedResourceMode, 146 Type: "aws_instance", 147 Name: "foo", 148 InstanceType: TypePrimary, 149 Index: 12, 150 }, 151 "", 152 }, 153 "explicit primary, explicit index": { 154 "aws_instance.foo.primary[2]", 155 &ResourceAddress{ 156 Mode: config.ManagedResourceMode, 157 Type: "aws_instance", 158 Name: "foo", 159 InstanceType: TypePrimary, 160 InstanceTypeSet: true, 161 Index: 2, 162 }, 163 "", 164 }, 165 "tainted": { 166 "aws_instance.foo.tainted", 167 &ResourceAddress{ 168 Mode: config.ManagedResourceMode, 169 Type: "aws_instance", 170 Name: "foo", 171 InstanceType: TypeTainted, 172 InstanceTypeSet: true, 173 Index: -1, 174 }, 175 "", 176 }, 177 "deposed": { 178 "aws_instance.foo.deposed", 179 &ResourceAddress{ 180 Mode: config.ManagedResourceMode, 181 Type: "aws_instance", 182 Name: "foo", 183 InstanceType: TypeDeposed, 184 InstanceTypeSet: true, 185 Index: -1, 186 }, 187 "", 188 }, 189 "with a hyphen": { 190 "aws_instance.foo-bar", 191 &ResourceAddress{ 192 Mode: config.ManagedResourceMode, 193 Type: "aws_instance", 194 Name: "foo-bar", 195 InstanceType: TypePrimary, 196 Index: -1, 197 }, 198 "", 199 }, 200 "managed in a module": { 201 "module.child.aws_instance.foo", 202 &ResourceAddress{ 203 Path: []string{"child"}, 204 Mode: config.ManagedResourceMode, 205 Type: "aws_instance", 206 Name: "foo", 207 InstanceType: TypePrimary, 208 Index: -1, 209 }, 210 "", 211 }, 212 "data in a module": { 213 "module.child.data.aws_instance.foo", 214 &ResourceAddress{ 215 Path: []string{"child"}, 216 Mode: config.DataResourceMode, 217 Type: "aws_instance", 218 Name: "foo", 219 InstanceType: TypePrimary, 220 Index: -1, 221 }, 222 "", 223 }, 224 "nested modules": { 225 "module.a.module.b.module.forever.aws_instance.foo", 226 &ResourceAddress{ 227 Path: []string{"a", "b", "forever"}, 228 Mode: config.ManagedResourceMode, 229 Type: "aws_instance", 230 Name: "foo", 231 InstanceType: TypePrimary, 232 Index: -1, 233 }, 234 "", 235 }, 236 "just a module": { 237 "module.a", 238 &ResourceAddress{ 239 Path: []string{"a"}, 240 Type: "", 241 Name: "", 242 InstanceType: TypePrimary, 243 Index: -1, 244 }, 245 "", 246 }, 247 "just a nested module": { 248 "module.a.module.b", 249 &ResourceAddress{ 250 Path: []string{"a", "b"}, 251 Type: "", 252 Name: "", 253 InstanceType: TypePrimary, 254 Index: -1, 255 }, 256 "", 257 }, 258 } 259 260 for tn, tc := range cases { 261 out, err := ParseResourceAddress(tc.Input) 262 if err != nil { 263 t.Fatalf("%s: unexpected err: %#v", tn, err) 264 } 265 266 if !reflect.DeepEqual(out, tc.Expected) { 267 t.Fatalf("bad: %q\n\nexpected:\n%#v\n\ngot:\n%#v", tn, tc.Expected, out) 268 } 269 270 expected := tc.Input 271 if tc.Output != "" { 272 expected = tc.Output 273 } 274 if out.String() != expected { 275 t.Fatalf("bad: %q\n\nexpected: %s\n\ngot: %s", tn, expected, out) 276 } 277 } 278 } 279 280 func TestResourceAddressEquals(t *testing.T) { 281 cases := map[string]struct { 282 Address *ResourceAddress 283 Other interface{} 284 Expect bool 285 }{ 286 "basic match": { 287 Address: &ResourceAddress{ 288 Mode: config.ManagedResourceMode, 289 Type: "aws_instance", 290 Name: "foo", 291 InstanceType: TypePrimary, 292 Index: 0, 293 }, 294 Other: &ResourceAddress{ 295 Mode: config.ManagedResourceMode, 296 Type: "aws_instance", 297 Name: "foo", 298 InstanceType: TypePrimary, 299 Index: 0, 300 }, 301 Expect: true, 302 }, 303 "address does not set index": { 304 Address: &ResourceAddress{ 305 Mode: config.ManagedResourceMode, 306 Type: "aws_instance", 307 Name: "foo", 308 InstanceType: TypePrimary, 309 Index: -1, 310 }, 311 Other: &ResourceAddress{ 312 Mode: config.ManagedResourceMode, 313 Type: "aws_instance", 314 Name: "foo", 315 InstanceType: TypePrimary, 316 Index: 3, 317 }, 318 Expect: true, 319 }, 320 "other does not set index": { 321 Address: &ResourceAddress{ 322 Mode: config.ManagedResourceMode, 323 Type: "aws_instance", 324 Name: "foo", 325 InstanceType: TypePrimary, 326 Index: 3, 327 }, 328 Other: &ResourceAddress{ 329 Mode: config.ManagedResourceMode, 330 Type: "aws_instance", 331 Name: "foo", 332 InstanceType: TypePrimary, 333 Index: -1, 334 }, 335 Expect: true, 336 }, 337 "neither sets index": { 338 Address: &ResourceAddress{ 339 Mode: config.ManagedResourceMode, 340 Type: "aws_instance", 341 Name: "foo", 342 InstanceType: TypePrimary, 343 Index: -1, 344 }, 345 Other: &ResourceAddress{ 346 Mode: config.ManagedResourceMode, 347 Type: "aws_instance", 348 Name: "foo", 349 InstanceType: TypePrimary, 350 Index: -1, 351 }, 352 Expect: true, 353 }, 354 "index over ten": { 355 Address: &ResourceAddress{ 356 Mode: config.ManagedResourceMode, 357 Type: "aws_instance", 358 Name: "foo", 359 InstanceType: TypePrimary, 360 Index: 1, 361 }, 362 Other: &ResourceAddress{ 363 Mode: config.ManagedResourceMode, 364 Type: "aws_instance", 365 Name: "foo", 366 InstanceType: TypePrimary, 367 Index: 13, 368 }, 369 Expect: false, 370 }, 371 "different type": { 372 Address: &ResourceAddress{ 373 Mode: config.ManagedResourceMode, 374 Type: "aws_instance", 375 Name: "foo", 376 InstanceType: TypePrimary, 377 Index: 0, 378 }, 379 Other: &ResourceAddress{ 380 Mode: config.ManagedResourceMode, 381 Type: "aws_vpc", 382 Name: "foo", 383 InstanceType: TypePrimary, 384 Index: 0, 385 }, 386 Expect: false, 387 }, 388 "different mode": { 389 Address: &ResourceAddress{ 390 Mode: config.ManagedResourceMode, 391 Type: "aws_instance", 392 Name: "foo", 393 InstanceType: TypePrimary, 394 Index: 0, 395 }, 396 Other: &ResourceAddress{ 397 Mode: config.DataResourceMode, 398 Type: "aws_instance", 399 Name: "foo", 400 InstanceType: TypePrimary, 401 Index: 0, 402 }, 403 Expect: false, 404 }, 405 "different name": { 406 Address: &ResourceAddress{ 407 Mode: config.ManagedResourceMode, 408 Type: "aws_instance", 409 Name: "foo", 410 InstanceType: TypePrimary, 411 Index: 0, 412 }, 413 Other: &ResourceAddress{ 414 Mode: config.ManagedResourceMode, 415 Type: "aws_instance", 416 Name: "bar", 417 InstanceType: TypePrimary, 418 Index: 0, 419 }, 420 Expect: false, 421 }, 422 "different instance type": { 423 Address: &ResourceAddress{ 424 Mode: config.ManagedResourceMode, 425 Type: "aws_instance", 426 Name: "foo", 427 InstanceType: TypePrimary, 428 Index: 0, 429 }, 430 Other: &ResourceAddress{ 431 Mode: config.ManagedResourceMode, 432 Type: "aws_instance", 433 Name: "foo", 434 InstanceType: TypeTainted, 435 Index: 0, 436 }, 437 Expect: false, 438 }, 439 "different index": { 440 Address: &ResourceAddress{ 441 Mode: config.ManagedResourceMode, 442 Type: "aws_instance", 443 Name: "foo", 444 InstanceType: TypePrimary, 445 Index: 0, 446 }, 447 Other: &ResourceAddress{ 448 Mode: config.ManagedResourceMode, 449 Type: "aws_instance", 450 Name: "foo", 451 InstanceType: TypePrimary, 452 Index: 1, 453 }, 454 Expect: false, 455 }, 456 "module address matches address of managed resource inside module": { 457 Address: &ResourceAddress{ 458 Path: []string{"a", "b"}, 459 Type: "", 460 Name: "", 461 InstanceType: TypePrimary, 462 Index: -1, 463 }, 464 Other: &ResourceAddress{ 465 Path: []string{"a", "b"}, 466 Mode: config.ManagedResourceMode, 467 Type: "aws_instance", 468 Name: "foo", 469 InstanceType: TypePrimary, 470 Index: 0, 471 }, 472 Expect: true, 473 }, 474 "module address matches address of data resource inside module": { 475 Address: &ResourceAddress{ 476 Path: []string{"a", "b"}, 477 Type: "", 478 Name: "", 479 InstanceType: TypePrimary, 480 Index: -1, 481 }, 482 Other: &ResourceAddress{ 483 Path: []string{"a", "b"}, 484 Mode: config.DataResourceMode, 485 Type: "aws_instance", 486 Name: "foo", 487 InstanceType: TypePrimary, 488 Index: 0, 489 }, 490 Expect: true, 491 }, 492 "module address doesn't match managed resource outside module": { 493 Address: &ResourceAddress{ 494 Path: []string{"a", "b"}, 495 Type: "", 496 Name: "", 497 InstanceType: TypePrimary, 498 Index: -1, 499 }, 500 Other: &ResourceAddress{ 501 Path: []string{"a"}, 502 Mode: config.ManagedResourceMode, 503 Type: "aws_instance", 504 Name: "foo", 505 InstanceType: TypePrimary, 506 Index: 0, 507 }, 508 Expect: false, 509 }, 510 "module address doesn't match data resource outside module": { 511 Address: &ResourceAddress{ 512 Path: []string{"a", "b"}, 513 Type: "", 514 Name: "", 515 InstanceType: TypePrimary, 516 Index: -1, 517 }, 518 Other: &ResourceAddress{ 519 Path: []string{"a"}, 520 Mode: config.DataResourceMode, 521 Type: "aws_instance", 522 Name: "foo", 523 InstanceType: TypePrimary, 524 Index: 0, 525 }, 526 Expect: false, 527 }, 528 "nil path vs empty path should match": { 529 Address: &ResourceAddress{ 530 Path: []string{}, 531 Mode: config.ManagedResourceMode, 532 Type: "aws_instance", 533 Name: "foo", 534 InstanceType: TypePrimary, 535 Index: -1, 536 }, 537 Other: &ResourceAddress{ 538 Path: nil, 539 Mode: config.ManagedResourceMode, 540 Type: "aws_instance", 541 Name: "foo", 542 InstanceType: TypePrimary, 543 Index: 0, 544 }, 545 Expect: true, 546 }, 547 } 548 549 for tn, tc := range cases { 550 actual := tc.Address.Equals(tc.Other) 551 if actual != tc.Expect { 552 t.Fatalf("%q: expected equals: %t, got %t for:\n%#v\n%#v", 553 tn, tc.Expect, actual, tc.Address, tc.Other) 554 } 555 } 556 } 557 558 func TestResourceAddressStateId(t *testing.T) { 559 cases := map[string]struct { 560 Input *ResourceAddress 561 Expected string 562 }{ 563 "basic resource": { 564 &ResourceAddress{ 565 Mode: config.ManagedResourceMode, 566 Type: "aws_instance", 567 Name: "foo", 568 InstanceType: TypePrimary, 569 Index: -1, 570 }, 571 "aws_instance.foo", 572 }, 573 574 "basic resource ignores count": { 575 &ResourceAddress{ 576 Mode: config.ManagedResourceMode, 577 Type: "aws_instance", 578 Name: "foo", 579 InstanceType: TypePrimary, 580 Index: 2, 581 }, 582 "aws_instance.foo", 583 }, 584 585 "data resource": { 586 &ResourceAddress{ 587 Mode: config.DataResourceMode, 588 Type: "aws_instance", 589 Name: "foo", 590 InstanceType: TypePrimary, 591 Index: -1, 592 }, 593 "data.aws_instance.foo", 594 }, 595 } 596 597 for tn, tc := range cases { 598 t.Run(tn, func(t *testing.T) { 599 actual := tc.Input.stateId() 600 if actual != tc.Expected { 601 t.Fatalf("bad: %q\n\nexpected: %s\n\ngot: %s", tn, tc.Expected, actual) 602 } 603 }) 604 } 605 }