github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/command/jsonformat/computed/renderers/renderer_test.go (about) 1 package renderers 2 3 import ( 4 "strings" 5 "testing" 6 7 "github.com/hashicorp/terraform/internal/command/jsonformat/computed" 8 9 "github.com/google/go-cmp/cmp" 10 "github.com/mitchellh/colorstring" 11 "github.com/zclconf/go-cty/cty" 12 13 "github.com/hashicorp/terraform/internal/plans" 14 ) 15 16 func TestRenderers_Human(t *testing.T) { 17 colorize := colorstring.Colorize{ 18 Colors: colorstring.DefaultColors, 19 Disable: true, 20 } 21 22 tcs := map[string]struct { 23 diff computed.Diff 24 expected string 25 opts computed.RenderHumanOpts 26 }{ 27 "primitive_create": { 28 diff: computed.Diff{ 29 Renderer: Primitive(nil, 1.0, cty.Number), 30 Action: plans.Create, 31 }, 32 expected: "1", 33 }, 34 "primitive_delete": { 35 diff: computed.Diff{ 36 Renderer: Primitive(1.0, nil, cty.Number), 37 Action: plans.Delete, 38 }, 39 expected: "1 -> null", 40 }, 41 "primitive_delete_override": { 42 diff: computed.Diff{ 43 Renderer: Primitive(1.0, nil, cty.Number), 44 Action: plans.Delete, 45 }, 46 opts: computed.RenderHumanOpts{OverrideNullSuffix: true}, 47 expected: "1", 48 }, 49 "primitive_update_to_null": { 50 diff: computed.Diff{ 51 Renderer: Primitive(1.0, nil, cty.Number), 52 Action: plans.Update, 53 }, 54 expected: "1 -> null", 55 }, 56 "primitive_update_from_null": { 57 diff: computed.Diff{ 58 Renderer: Primitive(nil, 1.0, cty.Number), 59 Action: plans.Update, 60 }, 61 expected: "null -> 1", 62 }, 63 "primitive_update": { 64 diff: computed.Diff{ 65 Renderer: Primitive(0.0, 1.0, cty.Number), 66 Action: plans.Update, 67 }, 68 expected: "0 -> 1", 69 }, 70 "primitive_update_long_float": { 71 diff: computed.Diff{ 72 Renderer: Primitive(123456789.0, 987654321.0, cty.Number), 73 Action: plans.Update, 74 }, 75 expected: "123456789 -> 987654321", 76 }, 77 "primitive_update_replace": { 78 diff: computed.Diff{ 79 Renderer: Primitive(0.0, 1.0, cty.Number), 80 Action: plans.Update, 81 Replace: true, 82 }, 83 expected: "0 -> 1 # forces replacement", 84 }, 85 "primitive_multiline_string_create": { 86 diff: computed.Diff{ 87 Renderer: Primitive(nil, "hello\nworld", cty.String), 88 Action: plans.Create, 89 }, 90 expected: ` 91 <<-EOT 92 hello 93 world 94 EOT 95 `, 96 }, 97 "primitive_multiline_string_delete": { 98 diff: computed.Diff{ 99 Renderer: Primitive("hello\nworld", nil, cty.String), 100 Action: plans.Delete, 101 }, 102 expected: ` 103 <<-EOT 104 hello 105 world 106 EOT -> null 107 `, 108 }, 109 "primitive_multiline_string_update": { 110 diff: computed.Diff{ 111 Renderer: Primitive("hello\nold\nworld", "hello\nnew\nworld", cty.String), 112 Action: plans.Update, 113 }, 114 expected: ` 115 <<-EOT 116 hello 117 - old 118 + new 119 world 120 EOT 121 `, 122 }, 123 "primitive_json_string_create": { 124 diff: computed.Diff{ 125 Renderer: Primitive(nil, "{\"key_one\": \"value_one\",\"key_two\":\"value_two\"}", cty.String), 126 Action: plans.Create, 127 }, 128 expected: ` 129 jsonencode( 130 { 131 + key_one = "value_one" 132 + key_two = "value_two" 133 } 134 ) 135 `, 136 }, 137 "primitive_json_string_delete": { 138 diff: computed.Diff{ 139 Renderer: Primitive("{\"key_one\": \"value_one\",\"key_two\":\"value_two\"}", nil, cty.String), 140 Action: plans.Delete, 141 }, 142 expected: ` 143 jsonencode( 144 { 145 - key_one = "value_one" 146 - key_two = "value_two" 147 } 148 ) -> null 149 `, 150 }, 151 "primitive_json_string_update": { 152 diff: computed.Diff{ 153 Renderer: Primitive("{\"key_one\": \"value_one\",\"key_two\":\"value_two\"}", "{\"key_one\": \"value_one\",\"key_two\":\"value_two\",\"key_three\":\"value_three\"}", cty.String), 154 Action: plans.Update, 155 }, 156 expected: ` 157 jsonencode( 158 ~ { 159 + key_three = "value_three" 160 # (2 unchanged attributes hidden) 161 } 162 ) 163 `, 164 }, 165 "primitive_json_explicit_nulls": { 166 diff: computed.Diff{ 167 Renderer: Primitive("{\"key_one\":\"value_one\",\"key_two\":\"value_two\"}", "{\"key_one\":null}", cty.String), 168 Action: plans.Update, 169 }, 170 expected: ` 171 jsonencode( 172 ~ { 173 ~ key_one = "value_one" -> null 174 - key_two = "value_two" 175 } 176 ) 177 `, 178 }, 179 "primitive_fake_json_string_update": { 180 diff: computed.Diff{ 181 // This isn't valid JSON, our renderer should be okay with it. 182 Renderer: Primitive("{\"key_one\": \"value_one\",\"key_two\":\"value_two\"", "{\"key_one\": \"value_one\",\"key_two\":\"value_two\",\"key_three\":\"value_three\"", cty.String), 183 Action: plans.Update, 184 }, 185 expected: "\"{\\\"key_one\\\": \\\"value_one\\\",\\\"key_two\\\":\\\"value_two\\\"\" -> \"{\\\"key_one\\\": \\\"value_one\\\",\\\"key_two\\\":\\\"value_two\\\",\\\"key_three\\\":\\\"value_three\\\"\"", 186 }, 187 "primitive_multiline_to_json_update": { 188 diff: computed.Diff{ 189 Renderer: Primitive("hello\nworld", "{\"key_one\": \"value_one\",\"key_two\":\"value_two\"}", cty.String), 190 Action: plans.Update, 191 }, 192 expected: ` 193 <<-EOT 194 hello 195 world 196 EOT -> jsonencode( 197 { 198 + key_one = "value_one" 199 + key_two = "value_two" 200 } 201 ) 202 `, 203 }, 204 "primitive_json_to_multiline_update": { 205 diff: computed.Diff{ 206 Renderer: Primitive("{\"key_one\": \"value_one\",\"key_two\":\"value_two\"}", "hello\nworld", cty.String), 207 Action: plans.Update, 208 }, 209 expected: ` 210 jsonencode( 211 { 212 - key_one = "value_one" 213 - key_two = "value_two" 214 } 215 ) -> <<-EOT 216 hello 217 world 218 EOT 219 `, 220 }, 221 "primitive_json_to_string_update": { 222 diff: computed.Diff{ 223 Renderer: Primitive("{\"key_one\": \"value_one\",\"key_two\":\"value_two\"}", "hello world", cty.String), 224 Action: plans.Update, 225 }, 226 expected: ` 227 jsonencode( 228 { 229 - key_one = "value_one" 230 - key_two = "value_two" 231 } 232 ) -> "hello world" 233 `, 234 }, 235 "primitive_string_to_json_update": { 236 diff: computed.Diff{ 237 Renderer: Primitive("hello world", "{\"key_one\": \"value_one\",\"key_two\":\"value_two\"}", cty.String), 238 Action: plans.Update, 239 }, 240 expected: ` 241 "hello world" -> jsonencode( 242 { 243 + key_one = "value_one" 244 + key_two = "value_two" 245 } 246 ) 247 `, 248 }, 249 "primitive_multi_to_single_update": { 250 diff: computed.Diff{ 251 Renderer: Primitive("hello\nworld", "hello world", cty.String), 252 Action: plans.Update, 253 }, 254 expected: ` 255 <<-EOT 256 - hello 257 - world 258 + hello world 259 EOT 260 `, 261 }, 262 "primitive_single_to_multi_update": { 263 diff: computed.Diff{ 264 Renderer: Primitive("hello world", "hello\nworld", cty.String), 265 Action: plans.Update, 266 }, 267 expected: ` 268 <<-EOT 269 - hello world 270 + hello 271 + world 272 EOT 273 `, 274 }, 275 "sensitive_update": { 276 diff: computed.Diff{ 277 Renderer: Sensitive(computed.Diff{ 278 Renderer: Primitive(0.0, 1.0, cty.Number), 279 Action: plans.Update, 280 }, true, true), 281 Action: plans.Update, 282 }, 283 expected: "(sensitive value)", 284 }, 285 "sensitive_update_replace": { 286 diff: computed.Diff{ 287 Renderer: Sensitive(computed.Diff{ 288 Renderer: Primitive(0.0, 1.0, cty.Number), 289 Action: plans.Update, 290 Replace: true, 291 }, true, true), 292 Action: plans.Update, 293 Replace: true, 294 }, 295 expected: "(sensitive value) # forces replacement", 296 }, 297 "computed_create": { 298 diff: computed.Diff{ 299 Renderer: Unknown(computed.Diff{}), 300 Action: plans.Create, 301 }, 302 expected: "(known after apply)", 303 }, 304 "computed_update": { 305 diff: computed.Diff{ 306 Renderer: Unknown(computed.Diff{ 307 Renderer: Primitive(0.0, nil, cty.Number), 308 Action: plans.Delete, 309 }), 310 Action: plans.Update, 311 }, 312 expected: "0 -> (known after apply)", 313 }, 314 "object_created": { 315 diff: computed.Diff{ 316 Renderer: Object(map[string]computed.Diff{}), 317 Action: plans.Create, 318 }, 319 expected: "{}", 320 }, 321 "object_created_with_attributes": { 322 diff: computed.Diff{ 323 Renderer: Object(map[string]computed.Diff{ 324 "attribute_one": { 325 Renderer: Primitive(nil, 0.0, cty.Number), 326 Action: plans.Create, 327 }, 328 }), 329 Action: plans.Create, 330 }, 331 expected: ` 332 { 333 + attribute_one = 0 334 } 335 `, 336 }, 337 "object_deleted": { 338 diff: computed.Diff{ 339 Renderer: Object(map[string]computed.Diff{}), 340 Action: plans.Delete, 341 }, 342 expected: "{} -> null", 343 }, 344 "object_deleted_with_attributes": { 345 diff: computed.Diff{ 346 Renderer: Object(map[string]computed.Diff{ 347 "attribute_one": { 348 Renderer: Primitive(0.0, nil, cty.Number), 349 Action: plans.Delete, 350 }, 351 }), 352 Action: plans.Delete, 353 }, 354 expected: ` 355 { 356 - attribute_one = 0 357 } -> null 358 `, 359 }, 360 "nested_object_deleted": { 361 diff: computed.Diff{ 362 Renderer: NestedObject(map[string]computed.Diff{}), 363 Action: plans.Delete, 364 }, 365 expected: "{} -> null", 366 }, 367 "nested_object_deleted_with_attributes": { 368 diff: computed.Diff{ 369 Renderer: NestedObject(map[string]computed.Diff{ 370 "attribute_one": { 371 Renderer: Primitive(0.0, nil, cty.Number), 372 Action: plans.Delete, 373 }, 374 }), 375 Action: plans.Delete, 376 }, 377 expected: ` 378 { 379 - attribute_one = 0 -> null 380 } -> null 381 `, 382 }, 383 "object_create_attribute": { 384 diff: computed.Diff{ 385 Renderer: Object(map[string]computed.Diff{ 386 "attribute_one": { 387 Renderer: Primitive(nil, 0.0, cty.Number), 388 Action: plans.Create, 389 }, 390 }), 391 Action: plans.Update, 392 }, 393 expected: ` 394 { 395 + attribute_one = 0 396 } 397 `, 398 }, 399 "object_update_attribute": { 400 diff: computed.Diff{ 401 Renderer: Object(map[string]computed.Diff{ 402 "attribute_one": { 403 Renderer: Primitive(0.0, 1.0, cty.Number), 404 Action: plans.Update, 405 }, 406 }), 407 Action: plans.Update, 408 }, 409 expected: ` 410 { 411 ~ attribute_one = 0 -> 1 412 } 413 `, 414 }, 415 "object_update_attribute_forces_replacement": { 416 diff: computed.Diff{ 417 Renderer: Object(map[string]computed.Diff{ 418 "attribute_one": { 419 Renderer: Primitive(0.0, 1.0, cty.Number), 420 Action: plans.Update, 421 }, 422 }), 423 Action: plans.Update, 424 Replace: true, 425 }, 426 expected: ` 427 { # forces replacement 428 ~ attribute_one = 0 -> 1 429 } 430 `, 431 }, 432 "object_delete_attribute": { 433 diff: computed.Diff{ 434 Renderer: Object(map[string]computed.Diff{ 435 "attribute_one": { 436 Renderer: Primitive(0.0, nil, cty.Number), 437 Action: plans.Delete, 438 }, 439 }), 440 Action: plans.Update, 441 }, 442 expected: ` 443 { 444 - attribute_one = 0 445 } 446 `, 447 }, 448 "object_ignore_unchanged_attributes": { 449 diff: computed.Diff{ 450 Renderer: Object(map[string]computed.Diff{ 451 "attribute_one": { 452 Renderer: Primitive(0.0, 1.0, cty.Number), 453 Action: plans.Update, 454 }, 455 "attribute_two": { 456 Renderer: Primitive(0.0, 0.0, cty.Number), 457 Action: plans.NoOp, 458 }, 459 "attribute_three": { 460 Renderer: Primitive(nil, 1.0, cty.Number), 461 Action: plans.Create, 462 }, 463 }), 464 Action: plans.Update, 465 }, 466 expected: ` 467 { 468 ~ attribute_one = 0 -> 1 469 + attribute_three = 1 470 # (1 unchanged attribute hidden) 471 } 472 `, 473 }, 474 "object_create_sensitive_attribute": { 475 diff: computed.Diff{ 476 Renderer: Object(map[string]computed.Diff{ 477 "attribute_one": { 478 Renderer: Sensitive(computed.Diff{ 479 Renderer: Primitive(nil, 1.0, cty.Number), 480 Action: plans.Create, 481 }, false, true), 482 Action: plans.Create, 483 }, 484 }), 485 Action: plans.Update, 486 }, 487 expected: ` 488 { 489 + attribute_one = (sensitive value) 490 } 491 `, 492 }, 493 "object_update_sensitive_attribute": { 494 diff: computed.Diff{ 495 Renderer: Object(map[string]computed.Diff{ 496 "attribute_one": { 497 Renderer: Sensitive(computed.Diff{ 498 Renderer: Primitive(0.0, 1.0, cty.Number), 499 Action: plans.Update, 500 }, true, true), 501 Action: plans.Update, 502 }, 503 }), 504 Action: plans.Update, 505 }, 506 expected: ` 507 { 508 ~ attribute_one = (sensitive value) 509 } 510 `, 511 }, 512 "object_delete_sensitive_attribute": { 513 diff: computed.Diff{ 514 Renderer: Object(map[string]computed.Diff{ 515 "attribute_one": { 516 Renderer: Sensitive(computed.Diff{ 517 Renderer: Primitive(0.0, nil, cty.Number), 518 Action: plans.Delete, 519 }, true, false), 520 Action: plans.Delete, 521 }, 522 }), 523 Action: plans.Update, 524 }, 525 expected: ` 526 { 527 - attribute_one = (sensitive value) 528 } 529 `, 530 }, 531 "object_create_computed_attribute": { 532 diff: computed.Diff{ 533 Renderer: Object(map[string]computed.Diff{ 534 "attribute_one": { 535 Renderer: Unknown(computed.Diff{Renderer: nil}), 536 Action: plans.Create, 537 }, 538 }), 539 Action: plans.Update, 540 }, 541 expected: ` 542 { 543 + attribute_one = (known after apply) 544 } 545 `, 546 }, 547 "object_update_computed_attribute": { 548 diff: computed.Diff{ 549 Renderer: Object(map[string]computed.Diff{ 550 "attribute_one": { 551 Renderer: Unknown(computed.Diff{ 552 Renderer: Primitive(1.0, nil, cty.Number), 553 Action: plans.Delete, 554 }), 555 Action: plans.Update, 556 }, 557 }), 558 Action: plans.Update, 559 }, 560 expected: ` 561 { 562 ~ attribute_one = 1 -> (known after apply) 563 } 564 `, 565 }, 566 "object_escapes_attribute_keys": { 567 diff: computed.Diff{ 568 Renderer: Object(map[string]computed.Diff{ 569 "attribute_one": { 570 Renderer: Primitive(1.0, 2.0, cty.Number), 571 Action: plans.Update, 572 }, 573 "attribute:two": { 574 Renderer: Primitive(2.0, 3.0, cty.Number), 575 Action: plans.Update, 576 }, 577 "attribute_six": { 578 Renderer: Primitive(3.0, 4.0, cty.Number), 579 Action: plans.Update, 580 }, 581 }), 582 Action: plans.Update, 583 }, 584 expected: ` 585 { 586 ~ "attribute:two" = 2 -> 3 587 ~ attribute_one = 1 -> 2 588 ~ attribute_six = 3 -> 4 589 } 590 `, 591 }, 592 "map_create_empty": { 593 diff: computed.Diff{ 594 Renderer: Map(map[string]computed.Diff{}), 595 Action: plans.Create, 596 }, 597 expected: "{}", 598 }, 599 "map_create": { 600 diff: computed.Diff{ 601 Renderer: Map(map[string]computed.Diff{ 602 "element_one": { 603 Renderer: Primitive(nil, "new", cty.String), 604 Action: plans.Create, 605 }, 606 }), 607 Action: plans.Create, 608 }, 609 expected: ` 610 { 611 + "element_one" = "new" 612 } 613 `, 614 }, 615 "map_delete_empty": { 616 diff: computed.Diff{ 617 Renderer: Map(map[string]computed.Diff{}), 618 Action: plans.Delete, 619 }, 620 expected: "{} -> null", 621 }, 622 "map_delete": { 623 diff: computed.Diff{ 624 Renderer: Map(map[string]computed.Diff{ 625 "element_one": { 626 Renderer: Primitive("old", nil, cty.String), 627 Action: plans.Delete, 628 }, 629 }), 630 Action: plans.Delete, 631 }, 632 expected: ` 633 { 634 - "element_one" = "old" 635 } -> null 636 `, 637 }, 638 "map_create_element": { 639 diff: computed.Diff{ 640 Renderer: Map(map[string]computed.Diff{ 641 "element_one": { 642 Renderer: Primitive(nil, "new", cty.String), 643 Action: plans.Create, 644 }, 645 }), 646 Action: plans.Update, 647 }, 648 expected: ` 649 { 650 + "element_one" = "new" 651 } 652 `, 653 }, 654 "map_update_element": { 655 diff: computed.Diff{ 656 Renderer: Map(map[string]computed.Diff{ 657 "element_one": { 658 Renderer: Primitive("old", "new", cty.String), 659 Action: plans.Update, 660 }, 661 }), 662 Action: plans.Update, 663 }, 664 expected: ` 665 { 666 ~ "element_one" = "old" -> "new" 667 } 668 `, 669 }, 670 "map_delete_element": { 671 diff: computed.Diff{ 672 Renderer: Map(map[string]computed.Diff{ 673 "element_one": { 674 Renderer: Primitive("old", nil, cty.String), 675 Action: plans.Delete, 676 }, 677 }), 678 Action: plans.Update, 679 }, 680 expected: ` 681 { 682 - "element_one" = "old" -> null 683 } 684 `, 685 }, 686 "map_update_forces_replacement": { 687 diff: computed.Diff{ 688 Renderer: Map(map[string]computed.Diff{ 689 "element_one": { 690 Renderer: Primitive("old", "new", cty.String), 691 Action: plans.Update, 692 }, 693 }), 694 Action: plans.Update, 695 Replace: true, 696 }, 697 expected: ` 698 { # forces replacement 699 ~ "element_one" = "old" -> "new" 700 } 701 `, 702 }, 703 "map_ignore_unchanged_elements": { 704 diff: computed.Diff{ 705 Renderer: Map(map[string]computed.Diff{ 706 "element_one": { 707 Renderer: Primitive(nil, "new", cty.String), 708 Action: plans.Create, 709 }, 710 "element_two": { 711 Renderer: Primitive("old", "old", cty.String), 712 Action: plans.NoOp, 713 }, 714 "element_three": { 715 Renderer: Primitive("old", "new", cty.String), 716 Action: plans.Update, 717 }, 718 }), 719 Action: plans.Update, 720 }, 721 expected: ` 722 { 723 + "element_one" = "new" 724 ~ "element_three" = "old" -> "new" 725 # (1 unchanged element hidden) 726 } 727 `, 728 }, 729 "map_create_sensitive_element": { 730 diff: computed.Diff{ 731 Renderer: Map(map[string]computed.Diff{ 732 "element_one": { 733 Renderer: Sensitive(computed.Diff{ 734 Renderer: Primitive(nil, 1.0, cty.Number), 735 Action: plans.Create, 736 }, false, true), 737 Action: plans.Create, 738 }, 739 }), 740 Action: plans.Update, 741 }, 742 expected: ` 743 { 744 + "element_one" = (sensitive value) 745 } 746 `, 747 }, 748 "map_update_sensitive_element": { 749 diff: computed.Diff{ 750 Renderer: Map(map[string]computed.Diff{ 751 "element_one": { 752 Renderer: Sensitive(computed.Diff{ 753 Renderer: Primitive(0.0, 1.0, cty.Number), 754 Action: plans.Update, 755 }, true, true), 756 Action: plans.Update, 757 }, 758 }), 759 Action: plans.Update, 760 }, 761 expected: ` 762 { 763 ~ "element_one" = (sensitive value) 764 } 765 `, 766 }, 767 "map_update_sensitive_element_status": { 768 diff: computed.Diff{ 769 Renderer: Map(map[string]computed.Diff{ 770 "element_one": { 771 Renderer: Sensitive(computed.Diff{ 772 Renderer: Primitive(0.0, 0.0, cty.Number), 773 Action: plans.NoOp, 774 }, true, false), 775 Action: plans.Update, 776 }, 777 }), 778 Action: plans.Update, 779 }, 780 expected: ` 781 { 782 # Warning: this attribute value will no longer be marked as sensitive 783 # after applying this change. The value is unchanged. 784 ~ "element_one" = (sensitive value) 785 } 786 `, 787 }, 788 "map_delete_sensitive_element": { 789 diff: computed.Diff{ 790 Renderer: Map(map[string]computed.Diff{ 791 "element_one": { 792 Renderer: Sensitive(computed.Diff{ 793 Renderer: Primitive(0.0, nil, cty.Number), 794 Action: plans.Delete, 795 }, true, false), 796 Action: plans.Delete, 797 }, 798 }), 799 Action: plans.Update, 800 }, 801 expected: ` 802 { 803 - "element_one" = (sensitive value) -> null 804 } 805 `, 806 }, 807 "map_create_computed_element": { 808 diff: computed.Diff{ 809 Renderer: Map(map[string]computed.Diff{ 810 "element_one": { 811 Renderer: Unknown(computed.Diff{}), 812 Action: plans.Create, 813 }, 814 }), 815 Action: plans.Update, 816 }, 817 expected: ` 818 { 819 + "element_one" = (known after apply) 820 } 821 `, 822 }, 823 "map_update_computed_element": { 824 diff: computed.Diff{ 825 Renderer: Map(map[string]computed.Diff{ 826 "element_one": { 827 Renderer: Unknown(computed.Diff{ 828 Renderer: Primitive(1.0, nil, cty.Number), 829 Action: plans.Delete, 830 }), 831 Action: plans.Update, 832 }, 833 }), 834 Action: plans.Update, 835 }, 836 expected: ` 837 { 838 ~ "element_one" = 1 -> (known after apply) 839 } 840 `, 841 }, 842 "map_aligns_key": { 843 diff: computed.Diff{ 844 Renderer: Map(map[string]computed.Diff{ 845 "element_one": { 846 Renderer: Primitive(1.0, 2.0, cty.Number), 847 Action: plans.Update, 848 }, 849 "element_two": { 850 Renderer: Primitive(1.0, 3.0, cty.Number), 851 Action: plans.Update, 852 }, 853 "element_three": { 854 Renderer: Primitive(1.0, 4.0, cty.Number), 855 Action: plans.Update, 856 }, 857 }), 858 Action: plans.Update, 859 }, 860 expected: ` 861 { 862 ~ "element_one" = 1 -> 2 863 ~ "element_three" = 1 -> 4 864 ~ "element_two" = 1 -> 3 865 } 866 `, 867 }, 868 "nested_map_does_not_align_keys": { 869 diff: computed.Diff{ 870 Renderer: NestedMap(map[string]computed.Diff{ 871 "element_one": { 872 Renderer: Primitive(1.0, 2.0, cty.Number), 873 Action: plans.Update, 874 }, 875 "element_two": { 876 Renderer: Primitive(1.0, 3.0, cty.Number), 877 Action: plans.Update, 878 }, 879 "element_three": { 880 Renderer: Primitive(1.0, 4.0, cty.Number), 881 Action: plans.Update, 882 }, 883 }), 884 Action: plans.Update, 885 }, 886 expected: ` 887 { 888 ~ "element_one" = 1 -> 2 889 ~ "element_three" = 1 -> 4 890 ~ "element_two" = 1 -> 3 891 } 892 `, 893 }, 894 "list_create_empty": { 895 diff: computed.Diff{ 896 Renderer: List([]computed.Diff{}), 897 Action: plans.Create, 898 }, 899 expected: "[]", 900 }, 901 "list_create": { 902 diff: computed.Diff{ 903 Renderer: List([]computed.Diff{ 904 { 905 Renderer: Primitive(nil, 1.0, cty.Number), 906 Action: plans.Create, 907 }, 908 }), 909 Action: plans.Create, 910 }, 911 expected: ` 912 [ 913 + 1, 914 ] 915 `, 916 }, 917 "list_delete_empty": { 918 diff: computed.Diff{ 919 Renderer: List([]computed.Diff{}), 920 Action: plans.Delete, 921 }, 922 expected: "[] -> null", 923 }, 924 "list_delete": { 925 diff: computed.Diff{ 926 Renderer: List([]computed.Diff{ 927 { 928 Renderer: Primitive(1.0, nil, cty.Number), 929 Action: plans.Delete, 930 }, 931 }), 932 Action: plans.Delete, 933 }, 934 expected: ` 935 [ 936 - 1, 937 ] -> null 938 `, 939 }, 940 "list_create_element": { 941 diff: computed.Diff{ 942 Renderer: List([]computed.Diff{ 943 { 944 Renderer: Primitive(nil, 1.0, cty.Number), 945 Action: plans.Create, 946 }, 947 }), 948 Action: plans.Update, 949 }, 950 expected: ` 951 [ 952 + 1, 953 ] 954 `, 955 }, 956 "list_update_element": { 957 diff: computed.Diff{ 958 Renderer: List([]computed.Diff{ 959 { 960 Renderer: Primitive(0.0, 1.0, cty.Number), 961 Action: plans.Update, 962 }, 963 }), 964 Action: plans.Update, 965 }, 966 expected: ` 967 [ 968 ~ 0 -> 1, 969 ] 970 `, 971 }, 972 "list_replace_element": { 973 diff: computed.Diff{ 974 Renderer: List([]computed.Diff{ 975 { 976 Renderer: Primitive(0.0, nil, cty.Number), 977 Action: plans.Delete, 978 }, 979 { 980 Renderer: Primitive(nil, 1.0, cty.Number), 981 Action: plans.Create, 982 }, 983 }), 984 Action: plans.Update, 985 }, 986 expected: ` 987 [ 988 - 0, 989 + 1, 990 ] 991 `, 992 }, 993 "list_delete_element": { 994 diff: computed.Diff{ 995 Renderer: List([]computed.Diff{ 996 { 997 Renderer: Primitive(0.0, nil, cty.Number), 998 Action: plans.Delete, 999 }, 1000 }), 1001 Action: plans.Update, 1002 }, 1003 expected: ` 1004 [ 1005 - 0, 1006 ] 1007 `, 1008 }, 1009 "list_update_forces_replacement": { 1010 diff: computed.Diff{ 1011 Renderer: List([]computed.Diff{ 1012 { 1013 Renderer: Primitive(0.0, 1.0, cty.Number), 1014 Action: plans.Update, 1015 }, 1016 }), 1017 Action: plans.Update, 1018 Replace: true, 1019 }, 1020 expected: ` 1021 [ # forces replacement 1022 ~ 0 -> 1, 1023 ] 1024 `, 1025 }, 1026 "list_update_ignores_unchanged": { 1027 diff: computed.Diff{ 1028 Renderer: NestedList([]computed.Diff{ 1029 { 1030 Renderer: Primitive(0.0, 0.0, cty.Number), 1031 Action: plans.NoOp, 1032 }, 1033 { 1034 Renderer: Primitive(1.0, 1.0, cty.Number), 1035 Action: plans.NoOp, 1036 }, 1037 { 1038 Renderer: Primitive(2.0, 5.0, cty.Number), 1039 Action: plans.Update, 1040 }, 1041 { 1042 Renderer: Primitive(3.0, 3.0, cty.Number), 1043 Action: plans.NoOp, 1044 }, 1045 { 1046 Renderer: Primitive(4.0, 4.0, cty.Number), 1047 Action: plans.NoOp, 1048 }, 1049 }), 1050 Action: plans.Update, 1051 }, 1052 expected: ` 1053 [ 1054 ~ 2 -> 5, 1055 # (4 unchanged elements hidden) 1056 ] 1057 `, 1058 }, 1059 "list_update_ignored_unchanged_with_context": { 1060 diff: computed.Diff{ 1061 Renderer: List([]computed.Diff{ 1062 { 1063 Renderer: Primitive(0.0, 0.0, cty.Number), 1064 Action: plans.NoOp, 1065 }, 1066 { 1067 Renderer: Primitive(1.0, 1.0, cty.Number), 1068 Action: plans.NoOp, 1069 }, 1070 { 1071 Renderer: Primitive(2.0, 5.0, cty.Number), 1072 Action: plans.Update, 1073 }, 1074 { 1075 Renderer: Primitive(3.0, 3.0, cty.Number), 1076 Action: plans.NoOp, 1077 }, 1078 { 1079 Renderer: Primitive(4.0, 4.0, cty.Number), 1080 Action: plans.NoOp, 1081 }, 1082 }), 1083 Action: plans.Update, 1084 }, 1085 expected: ` 1086 [ 1087 # (1 unchanged element hidden) 1088 1, 1089 ~ 2 -> 5, 1090 3, 1091 # (1 unchanged element hidden) 1092 ] 1093 `, 1094 }, 1095 "list_create_sensitive_element": { 1096 diff: computed.Diff{ 1097 Renderer: List([]computed.Diff{ 1098 { 1099 Renderer: Sensitive(computed.Diff{ 1100 Renderer: Primitive(nil, 1.0, cty.Number), 1101 Action: plans.Create, 1102 }, false, true), 1103 Action: plans.Create, 1104 }, 1105 }), 1106 Action: plans.Update, 1107 }, 1108 expected: ` 1109 [ 1110 + (sensitive value), 1111 ] 1112 `, 1113 }, 1114 "list_delete_sensitive_element": { 1115 diff: computed.Diff{ 1116 Renderer: List([]computed.Diff{ 1117 { 1118 Renderer: Sensitive(computed.Diff{ 1119 Renderer: Primitive(1.0, nil, cty.Number), 1120 Action: plans.Delete, 1121 }, true, false), 1122 Action: plans.Delete, 1123 }, 1124 }), 1125 Action: plans.Update, 1126 }, 1127 expected: ` 1128 [ 1129 - (sensitive value), 1130 ] 1131 `, 1132 }, 1133 "list_update_sensitive_element": { 1134 diff: computed.Diff{ 1135 Renderer: List([]computed.Diff{ 1136 { 1137 Renderer: Sensitive(computed.Diff{ 1138 Renderer: Primitive(0.0, 1.0, cty.Number), 1139 Action: plans.Update, 1140 }, true, true), 1141 Action: plans.Update, 1142 }, 1143 }), 1144 Action: plans.Update, 1145 }, 1146 expected: ` 1147 [ 1148 ~ (sensitive value), 1149 ] 1150 `, 1151 }, 1152 "list_update_sensitive_element_status": { 1153 diff: computed.Diff{ 1154 Renderer: List([]computed.Diff{ 1155 { 1156 Renderer: Sensitive(computed.Diff{ 1157 Renderer: Primitive(1.0, 1.0, cty.Number), 1158 Action: plans.NoOp, 1159 }, false, true), 1160 Action: plans.Update, 1161 }, 1162 }), 1163 Action: plans.Update, 1164 }, 1165 expected: ` 1166 [ 1167 # Warning: this attribute value will be marked as sensitive and will not 1168 # display in UI output after applying this change. The value is unchanged. 1169 ~ (sensitive value), 1170 ] 1171 `, 1172 }, 1173 "list_create_computed_element": { 1174 diff: computed.Diff{ 1175 Renderer: List([]computed.Diff{ 1176 { 1177 Renderer: Unknown(computed.Diff{}), 1178 Action: plans.Create, 1179 }, 1180 }), 1181 Action: plans.Update, 1182 }, 1183 expected: ` 1184 [ 1185 + (known after apply), 1186 ] 1187 `, 1188 }, 1189 "list_update_computed_element": { 1190 diff: computed.Diff{ 1191 Renderer: List([]computed.Diff{ 1192 { 1193 Renderer: Unknown(computed.Diff{ 1194 Renderer: Primitive(0.0, nil, cty.Number), 1195 Action: plans.Delete, 1196 }), 1197 Action: plans.Update, 1198 }, 1199 }), 1200 Action: plans.Update, 1201 }, 1202 expected: ` 1203 [ 1204 ~ 0 -> (known after apply), 1205 ] 1206 `, 1207 }, 1208 "set_create_empty": { 1209 diff: computed.Diff{ 1210 Renderer: Set([]computed.Diff{}), 1211 Action: plans.Create, 1212 }, 1213 expected: "[]", 1214 }, 1215 "set_create": { 1216 diff: computed.Diff{ 1217 Renderer: Set([]computed.Diff{ 1218 { 1219 Renderer: Primitive(nil, 1.0, cty.Number), 1220 Action: plans.Create, 1221 }, 1222 }), 1223 Action: plans.Create, 1224 }, 1225 expected: ` 1226 [ 1227 + 1, 1228 ] 1229 `, 1230 }, 1231 "set_delete_empty": { 1232 diff: computed.Diff{ 1233 Renderer: Set([]computed.Diff{}), 1234 Action: plans.Delete, 1235 }, 1236 expected: "[] -> null", 1237 }, 1238 "set_delete": { 1239 diff: computed.Diff{ 1240 Renderer: Set([]computed.Diff{ 1241 { 1242 Renderer: Primitive(1.0, nil, cty.Number), 1243 Action: plans.Delete, 1244 }, 1245 }), 1246 Action: plans.Delete, 1247 }, 1248 expected: ` 1249 [ 1250 - 1, 1251 ] -> null 1252 `, 1253 }, 1254 "set_create_element": { 1255 diff: computed.Diff{ 1256 Renderer: Set([]computed.Diff{ 1257 { 1258 Renderer: Primitive(nil, 1.0, cty.Number), 1259 Action: plans.Create, 1260 }, 1261 }), 1262 Action: plans.Update, 1263 }, 1264 expected: ` 1265 [ 1266 + 1, 1267 ] 1268 `, 1269 }, 1270 "set_update_element": { 1271 diff: computed.Diff{ 1272 Renderer: Set([]computed.Diff{ 1273 { 1274 Renderer: Primitive(0.0, 1.0, cty.Number), 1275 Action: plans.Update, 1276 }, 1277 }), 1278 Action: plans.Update, 1279 }, 1280 expected: ` 1281 [ 1282 ~ 0 -> 1, 1283 ] 1284 `, 1285 }, 1286 "set_replace_element": { 1287 diff: computed.Diff{ 1288 Renderer: Set([]computed.Diff{ 1289 { 1290 Renderer: Primitive(0.0, nil, cty.Number), 1291 Action: plans.Delete, 1292 }, 1293 { 1294 Renderer: Primitive(nil, 1.0, cty.Number), 1295 Action: plans.Create, 1296 }, 1297 }), 1298 Action: plans.Update, 1299 }, 1300 expected: ` 1301 [ 1302 - 0, 1303 + 1, 1304 ] 1305 `, 1306 }, 1307 "set_delete_element": { 1308 diff: computed.Diff{ 1309 Renderer: Set([]computed.Diff{ 1310 { 1311 Renderer: Primitive(0.0, nil, cty.Number), 1312 Action: plans.Delete, 1313 }, 1314 }), 1315 Action: plans.Update, 1316 }, 1317 expected: ` 1318 [ 1319 - 0, 1320 ] 1321 `, 1322 }, 1323 "set_update_forces_replacement": { 1324 diff: computed.Diff{ 1325 Renderer: Set([]computed.Diff{ 1326 { 1327 Renderer: Primitive(0.0, 1.0, cty.Number), 1328 Action: plans.Update, 1329 }, 1330 }), 1331 Action: plans.Update, 1332 Replace: true, 1333 }, 1334 expected: ` 1335 [ # forces replacement 1336 ~ 0 -> 1, 1337 ] 1338 `, 1339 }, 1340 "nested_set_update_forces_replacement": { 1341 diff: computed.Diff{ 1342 Renderer: NestedSet([]computed.Diff{ 1343 { 1344 Renderer: Object(map[string]computed.Diff{ 1345 "attribute_one": { 1346 Renderer: Primitive(0.0, 1.0, cty.Number), 1347 Action: plans.Update, 1348 }, 1349 }), 1350 Action: plans.Update, 1351 }, 1352 }), 1353 Action: plans.Update, 1354 Replace: true, 1355 }, 1356 expected: ` 1357 [ 1358 ~ { # forces replacement 1359 ~ attribute_one = 0 -> 1 1360 }, 1361 ] 1362 `, 1363 }, 1364 "set_update_ignores_unchanged": { 1365 diff: computed.Diff{ 1366 Renderer: Set([]computed.Diff{ 1367 { 1368 Renderer: Primitive(0.0, 0.0, cty.Number), 1369 Action: plans.NoOp, 1370 }, 1371 { 1372 Renderer: Primitive(1.0, 1.0, cty.Number), 1373 Action: plans.NoOp, 1374 }, 1375 { 1376 Renderer: Primitive(2.0, 5.0, cty.Number), 1377 Action: plans.Update, 1378 }, 1379 { 1380 Renderer: Primitive(3.0, 3.0, cty.Number), 1381 Action: plans.NoOp, 1382 }, 1383 { 1384 Renderer: Primitive(4.0, 4.0, cty.Number), 1385 Action: plans.NoOp, 1386 }, 1387 }), 1388 Action: plans.Update, 1389 }, 1390 expected: ` 1391 [ 1392 ~ 2 -> 5, 1393 # (4 unchanged elements hidden) 1394 ] 1395 `, 1396 }, 1397 "set_create_sensitive_element": { 1398 diff: computed.Diff{ 1399 Renderer: Set([]computed.Diff{ 1400 { 1401 Renderer: Sensitive(computed.Diff{ 1402 Renderer: Primitive(nil, 1.0, cty.Number), 1403 Action: plans.Create, 1404 }, false, true), 1405 Action: plans.Create, 1406 }, 1407 }), 1408 Action: plans.Update, 1409 }, 1410 expected: ` 1411 [ 1412 + (sensitive value), 1413 ] 1414 `, 1415 }, 1416 "set_delete_sensitive_element": { 1417 diff: computed.Diff{ 1418 Renderer: Set([]computed.Diff{ 1419 { 1420 Renderer: Sensitive(computed.Diff{ 1421 Renderer: Primitive(1.0, nil, cty.Number), 1422 Action: plans.Delete, 1423 }, false, true), 1424 Action: plans.Delete, 1425 }, 1426 }), 1427 Action: plans.Update, 1428 }, 1429 expected: ` 1430 [ 1431 - (sensitive value), 1432 ] 1433 `, 1434 }, 1435 "set_update_sensitive_element": { 1436 diff: computed.Diff{ 1437 Renderer: Set([]computed.Diff{ 1438 { 1439 Renderer: Sensitive(computed.Diff{ 1440 Renderer: Primitive(0.0, 1.0, cty.Number), 1441 Action: plans.Update, 1442 }, true, true), 1443 Action: plans.Update, 1444 }, 1445 }), 1446 Action: plans.Update, 1447 }, 1448 expected: ` 1449 [ 1450 ~ (sensitive value), 1451 ] 1452 `, 1453 }, 1454 "set_update_sensitive_element_status": { 1455 diff: computed.Diff{ 1456 Renderer: Set([]computed.Diff{ 1457 { 1458 Renderer: Sensitive(computed.Diff{ 1459 Renderer: Primitive(1.0, 2.0, cty.Number), 1460 Action: plans.Update, 1461 }, false, true), 1462 Action: plans.Update, 1463 }, 1464 }), 1465 Action: plans.Update, 1466 }, 1467 expected: ` 1468 [ 1469 # Warning: this attribute value will be marked as sensitive and will not 1470 # display in UI output after applying this change. 1471 ~ (sensitive value), 1472 ] 1473 `, 1474 }, 1475 "set_create_computed_element": { 1476 diff: computed.Diff{ 1477 Renderer: Set([]computed.Diff{ 1478 { 1479 Renderer: Unknown(computed.Diff{}), 1480 Action: plans.Create, 1481 }, 1482 }), 1483 Action: plans.Update, 1484 }, 1485 expected: ` 1486 [ 1487 + (known after apply), 1488 ] 1489 `, 1490 }, 1491 "set_update_computed_element": { 1492 diff: computed.Diff{ 1493 Renderer: Set([]computed.Diff{ 1494 { 1495 Renderer: Unknown(computed.Diff{ 1496 Renderer: Primitive(0.0, nil, cty.Number), 1497 Action: plans.Delete, 1498 }), 1499 Action: plans.Update, 1500 }, 1501 }), 1502 Action: plans.Update, 1503 }, 1504 expected: ` 1505 [ 1506 ~ 0 -> (known after apply), 1507 ] 1508 `, 1509 }, 1510 "create_empty_block": { 1511 diff: computed.Diff{ 1512 Renderer: Block(nil, Blocks{}), 1513 Action: plans.Create, 1514 }, 1515 expected: "{}", 1516 }, 1517 "create_populated_block": { 1518 diff: computed.Diff{ 1519 Renderer: Block(map[string]computed.Diff{ 1520 "string": { 1521 Renderer: Primitive(nil, "root", cty.String), 1522 Action: plans.Create, 1523 }, 1524 "boolean": { 1525 Renderer: Primitive(nil, true, cty.Bool), 1526 Action: plans.Create, 1527 }, 1528 }, Blocks{ 1529 SingleBlocks: map[string]computed.Diff{ 1530 "nested_block": { 1531 Renderer: Block(map[string]computed.Diff{ 1532 "string": { 1533 Renderer: Primitive(nil, "one", cty.String), 1534 Action: plans.Create, 1535 }, 1536 }, Blocks{}), 1537 Action: plans.Create, 1538 }, 1539 "nested_block_two": { 1540 Renderer: Block(map[string]computed.Diff{ 1541 "string": { 1542 Renderer: Primitive(nil, "two", cty.String), 1543 Action: plans.Create, 1544 }, 1545 }, Blocks{}), 1546 Action: plans.Create, 1547 }, 1548 }, 1549 }), 1550 Action: plans.Create, 1551 }, 1552 expected: ` 1553 { 1554 + boolean = true 1555 + string = "root" 1556 1557 + nested_block { 1558 + string = "one" 1559 } 1560 1561 + nested_block_two { 1562 + string = "two" 1563 } 1564 }`, 1565 }, 1566 "update_empty_block": { 1567 diff: computed.Diff{ 1568 Renderer: Block(map[string]computed.Diff{ 1569 "string": { 1570 Renderer: Primitive(nil, "root", cty.String), 1571 Action: plans.Create, 1572 }, 1573 "boolean": { 1574 Renderer: Primitive(nil, true, cty.Bool), 1575 Action: plans.Create, 1576 }, 1577 }, Blocks{ 1578 SingleBlocks: map[string]computed.Diff{ 1579 "nested_block": { 1580 1581 Renderer: Block(map[string]computed.Diff{ 1582 "string": { 1583 Renderer: Primitive(nil, "one", cty.String), 1584 Action: plans.Create, 1585 }, 1586 }, Blocks{}), 1587 Action: plans.Create, 1588 }, 1589 "nested_block_two": { 1590 1591 Renderer: Block(map[string]computed.Diff{ 1592 "string": { 1593 Renderer: Primitive(nil, "two", cty.String), 1594 Action: plans.Create, 1595 }, 1596 }, Blocks{}), 1597 Action: plans.Create, 1598 }, 1599 }, 1600 }), 1601 Action: plans.Update, 1602 }, 1603 expected: ` 1604 { 1605 + boolean = true 1606 + string = "root" 1607 1608 + nested_block { 1609 + string = "one" 1610 } 1611 1612 + nested_block_two { 1613 + string = "two" 1614 } 1615 }`, 1616 }, 1617 "update_populated_block": { 1618 diff: computed.Diff{ 1619 Renderer: Block(map[string]computed.Diff{ 1620 "string": { 1621 Renderer: Primitive(nil, "root", cty.String), 1622 Action: plans.Create, 1623 }, 1624 "boolean": { 1625 Renderer: Primitive(false, true, cty.Bool), 1626 Action: plans.Update, 1627 }, 1628 }, Blocks{ 1629 SingleBlocks: map[string]computed.Diff{ 1630 "nested_block": { 1631 Renderer: Block(map[string]computed.Diff{ 1632 "string": { 1633 Renderer: Primitive(nil, "one", cty.String), 1634 Action: plans.NoOp, 1635 }, 1636 }, Blocks{}), 1637 Action: plans.NoOp, 1638 }, 1639 "nested_block_two": { 1640 Renderer: Block(map[string]computed.Diff{ 1641 "string": { 1642 Renderer: Primitive(nil, "two", cty.String), 1643 Action: plans.Create, 1644 }, 1645 }, Blocks{}), 1646 Action: plans.Create, 1647 }, 1648 }, 1649 }), 1650 Action: plans.Update, 1651 }, 1652 expected: ` 1653 { 1654 ~ boolean = false -> true 1655 + string = "root" 1656 1657 + nested_block_two { 1658 + string = "two" 1659 } 1660 1661 # (1 unchanged block hidden) 1662 }`, 1663 }, 1664 "clear_populated_block": { 1665 diff: computed.Diff{ 1666 Renderer: Block(map[string]computed.Diff{ 1667 "string": { 1668 Renderer: Primitive("root", nil, cty.String), 1669 Action: plans.Delete, 1670 }, 1671 "boolean": { 1672 Renderer: Primitive(true, nil, cty.Bool), 1673 Action: plans.Delete, 1674 }, 1675 }, Blocks{ 1676 SingleBlocks: map[string]computed.Diff{ 1677 "nested_block": { 1678 Renderer: Block(map[string]computed.Diff{ 1679 "string": { 1680 Renderer: Primitive("one", nil, cty.String), 1681 Action: plans.Delete, 1682 }, 1683 }, Blocks{}), 1684 Action: plans.Delete, 1685 }, 1686 "nested_block_two": { 1687 Renderer: Block(map[string]computed.Diff{ 1688 "string": { 1689 Renderer: Primitive("two", nil, cty.String), 1690 Action: plans.Delete, 1691 }, 1692 }, Blocks{}), 1693 Action: plans.Delete, 1694 }, 1695 }, 1696 }), 1697 Action: plans.Update, 1698 }, 1699 expected: ` 1700 { 1701 - boolean = true -> null 1702 - string = "root" -> null 1703 1704 - nested_block { 1705 - string = "one" -> null 1706 } 1707 1708 - nested_block_two { 1709 - string = "two" -> null 1710 } 1711 }`, 1712 }, 1713 "delete_populated_block": { 1714 diff: computed.Diff{ 1715 Renderer: Block(map[string]computed.Diff{ 1716 "string": { 1717 Renderer: Primitive("root", nil, cty.String), 1718 Action: plans.Delete, 1719 }, 1720 "boolean": { 1721 Renderer: Primitive(true, nil, cty.Bool), 1722 Action: plans.Delete, 1723 }, 1724 }, Blocks{ 1725 SingleBlocks: map[string]computed.Diff{ 1726 "nested_block": { 1727 Renderer: Block(map[string]computed.Diff{ 1728 "string": { 1729 Renderer: Primitive("one", nil, cty.String), 1730 Action: plans.Delete, 1731 }, 1732 }, Blocks{}), 1733 Action: plans.Delete, 1734 }, 1735 "nested_block_two": { 1736 Renderer: Block(map[string]computed.Diff{ 1737 "string": { 1738 Renderer: Primitive("two", nil, cty.String), 1739 Action: plans.Delete, 1740 }, 1741 }, Blocks{}), 1742 Action: plans.Delete, 1743 }, 1744 }, 1745 }), 1746 Action: plans.Delete, 1747 }, 1748 expected: ` 1749 { 1750 - boolean = true -> null 1751 - string = "root" -> null 1752 1753 - nested_block { 1754 - string = "one" -> null 1755 } 1756 1757 - nested_block_two { 1758 - string = "two" -> null 1759 } 1760 }`, 1761 }, 1762 "list_block_update": { 1763 diff: computed.Diff{ 1764 Renderer: Block( 1765 nil, 1766 Blocks{ 1767 ListBlocks: map[string][]computed.Diff{ 1768 "list_blocks": { 1769 { 1770 Renderer: Block(map[string]computed.Diff{ 1771 "number": { 1772 Renderer: Primitive(1.0, 2.0, cty.Number), 1773 Action: plans.Update, 1774 }, 1775 "string": { 1776 Renderer: Primitive(nil, "new", cty.String), 1777 Action: plans.Create, 1778 }, 1779 }, Blocks{}), 1780 Action: plans.Update, 1781 }, 1782 { 1783 Renderer: Block(map[string]computed.Diff{ 1784 "number": { 1785 Renderer: Primitive(1.0, nil, cty.Number), 1786 Action: plans.Delete, 1787 }, 1788 "string": { 1789 Renderer: Primitive("old", "new", cty.String), 1790 Action: plans.Update, 1791 }, 1792 }, Blocks{}), 1793 Action: plans.Update, 1794 }, 1795 }, 1796 }, 1797 }), 1798 }, 1799 expected: ` 1800 { 1801 ~ list_blocks { 1802 ~ number = 1 -> 2 1803 + string = "new" 1804 } 1805 ~ list_blocks { 1806 - number = 1 -> null 1807 ~ string = "old" -> "new" 1808 } 1809 }`, 1810 }, 1811 "set_block_update": { 1812 diff: computed.Diff{ 1813 Renderer: Block( 1814 nil, 1815 Blocks{ 1816 SetBlocks: map[string][]computed.Diff{ 1817 "set_blocks": { 1818 { 1819 Renderer: Block(map[string]computed.Diff{ 1820 "number": { 1821 Renderer: Primitive(1.0, 2.0, cty.Number), 1822 Action: plans.Update, 1823 }, 1824 "string": { 1825 Renderer: Primitive(nil, "new", cty.String), 1826 Action: plans.Create, 1827 }, 1828 }, Blocks{}), 1829 Action: plans.Update, 1830 }, 1831 { 1832 Renderer: Block(map[string]computed.Diff{ 1833 "number": { 1834 Renderer: Primitive(1.0, nil, cty.Number), 1835 Action: plans.Delete, 1836 }, 1837 "string": { 1838 Renderer: Primitive("old", "new", cty.String), 1839 Action: plans.Update, 1840 }, 1841 }, Blocks{}), 1842 Action: plans.Update, 1843 }, 1844 }, 1845 }, 1846 }), 1847 }, 1848 expected: ` 1849 { 1850 ~ set_blocks { 1851 ~ number = 1 -> 2 1852 + string = "new" 1853 } 1854 ~ set_blocks { 1855 - number = 1 -> null 1856 ~ string = "old" -> "new" 1857 } 1858 }`, 1859 }, 1860 "map_block_update": { 1861 diff: computed.Diff{ 1862 Renderer: Block( 1863 nil, 1864 Blocks{ 1865 MapBlocks: map[string]map[string]computed.Diff{ 1866 "list_blocks": { 1867 "key_one": { 1868 Renderer: Block(map[string]computed.Diff{ 1869 "number": { 1870 Renderer: Primitive(1.0, 2.0, cty.Number), 1871 Action: plans.Update, 1872 }, 1873 "string": { 1874 Renderer: Primitive(nil, "new", cty.String), 1875 Action: plans.Create, 1876 }, 1877 }, Blocks{}), 1878 Action: plans.Update, 1879 }, 1880 "key:two": { 1881 Renderer: Block(map[string]computed.Diff{ 1882 "number": { 1883 Renderer: Primitive(1.0, nil, cty.Number), 1884 Action: plans.Delete, 1885 }, 1886 "string": { 1887 Renderer: Primitive("old", "new", cty.String), 1888 Action: plans.Update, 1889 }, 1890 }, Blocks{}), 1891 Action: plans.Update, 1892 }, 1893 }, 1894 }, 1895 }), 1896 }, 1897 expected: ` 1898 { 1899 ~ list_blocks "key:two" { 1900 - number = 1 -> null 1901 ~ string = "old" -> "new" 1902 } 1903 ~ list_blocks "key_one" { 1904 ~ number = 1 -> 2 1905 + string = "new" 1906 } 1907 } 1908 `, 1909 }, 1910 "sensitive_block": { 1911 diff: computed.Diff{ 1912 Renderer: SensitiveBlock(computed.Diff{ 1913 Renderer: Block(nil, Blocks{}), 1914 Action: plans.NoOp, 1915 }, true, true), 1916 Action: plans.Update, 1917 }, 1918 expected: ` 1919 { 1920 # At least one attribute in this block is (or was) sensitive, 1921 # so its contents will not be displayed. 1922 } 1923 `, 1924 }, 1925 "delete_empty_block": { 1926 diff: computed.Diff{ 1927 Renderer: Block(nil, Blocks{}), 1928 Action: plans.Delete, 1929 }, 1930 expected: "{}", 1931 }, 1932 "block_escapes_keys": { 1933 diff: computed.Diff{ 1934 Renderer: Block(map[string]computed.Diff{ 1935 "attribute_one": { 1936 Renderer: Primitive(1.0, 2.0, cty.Number), 1937 Action: plans.Update, 1938 }, 1939 "attribute:two": { 1940 Renderer: Primitive(2.0, 3.0, cty.Number), 1941 Action: plans.Update, 1942 }, 1943 "attribute_six": { 1944 Renderer: Primitive(3.0, 4.0, cty.Number), 1945 Action: plans.Update, 1946 }, 1947 }, Blocks{ 1948 SingleBlocks: map[string]computed.Diff{ 1949 "nested_block:one": { 1950 Renderer: Block(map[string]computed.Diff{ 1951 "string": { 1952 Renderer: Primitive("one", "four", cty.String), 1953 Action: plans.Update, 1954 }, 1955 }, Blocks{}), 1956 Action: plans.Update, 1957 }, 1958 "nested_block_two": { 1959 Renderer: Block(map[string]computed.Diff{ 1960 "string": { 1961 Renderer: Primitive("two", "three", cty.String), 1962 Action: plans.Update, 1963 }, 1964 }, Blocks{}), 1965 Action: plans.Update, 1966 }, 1967 }, 1968 }), 1969 Action: plans.Update, 1970 }, 1971 expected: ` 1972 { 1973 ~ "attribute:two" = 2 -> 3 1974 ~ attribute_one = 1 -> 2 1975 ~ attribute_six = 3 -> 4 1976 1977 ~ "nested_block:one" { 1978 ~ string = "one" -> "four" 1979 } 1980 1981 ~ nested_block_two { 1982 ~ string = "two" -> "three" 1983 } 1984 }`, 1985 }, 1986 "block_always_includes_important_attributes": { 1987 diff: computed.Diff{ 1988 Renderer: Block(map[string]computed.Diff{ 1989 "id": { 1990 Renderer: Primitive("root", "root", cty.String), 1991 Action: plans.NoOp, 1992 }, 1993 "boolean": { 1994 Renderer: Primitive(false, false, cty.Bool), 1995 Action: plans.NoOp, 1996 }, 1997 }, Blocks{ 1998 SingleBlocks: map[string]computed.Diff{ 1999 "nested_block": { 2000 Renderer: Block(map[string]computed.Diff{ 2001 "string": { 2002 Renderer: Primitive("one", "one", cty.String), 2003 Action: plans.NoOp, 2004 }, 2005 }, Blocks{}), 2006 Action: plans.NoOp, 2007 }, 2008 "nested_block_two": { 2009 Renderer: Block(map[string]computed.Diff{ 2010 "string": { 2011 Renderer: Primitive("two", "two", cty.String), 2012 Action: plans.NoOp, 2013 }, 2014 }, Blocks{}), 2015 Action: plans.NoOp, 2016 }, 2017 }, 2018 }), 2019 Action: plans.NoOp, 2020 }, 2021 expected: ` 2022 { 2023 id = "root" 2024 # (1 unchanged attribute hidden) 2025 2026 # (2 unchanged blocks hidden) 2027 }`, 2028 }, 2029 "output_map_to_list": { 2030 diff: computed.Diff{ 2031 Renderer: TypeChange(computed.Diff{ 2032 Renderer: Map(map[string]computed.Diff{ 2033 "element_one": { 2034 Renderer: Primitive(0.0, nil, cty.Number), 2035 Action: plans.Delete, 2036 }, 2037 "element_two": { 2038 Renderer: Primitive(1.0, nil, cty.Number), 2039 Action: plans.Delete, 2040 }, 2041 }), 2042 Action: plans.Delete, 2043 }, computed.Diff{ 2044 Renderer: List([]computed.Diff{ 2045 { 2046 Renderer: Primitive(nil, 0.0, cty.Number), 2047 Action: plans.Create, 2048 }, 2049 { 2050 Renderer: Primitive(nil, 1.0, cty.Number), 2051 Action: plans.Create, 2052 }, 2053 }), 2054 Action: plans.Create, 2055 }), 2056 }, 2057 expected: ` 2058 { 2059 - "element_one" = 0 2060 - "element_two" = 1 2061 } -> [ 2062 + 0, 2063 + 1, 2064 ] 2065 `, 2066 }, 2067 "json_string_no_symbols": { 2068 diff: computed.Diff{ 2069 Renderer: Primitive("{\"key\":\"value\"}", "{\"key\":\"value\"}", cty.String), 2070 Action: plans.NoOp, 2071 }, 2072 opts: computed.RenderHumanOpts{ 2073 HideDiffActionSymbols: true, 2074 ShowUnchangedChildren: true, 2075 }, 2076 expected: ` 2077 jsonencode( 2078 { 2079 key = "value" 2080 } 2081 ) 2082 `, 2083 }, 2084 } 2085 for name, tc := range tcs { 2086 t.Run(name, func(t *testing.T) { 2087 2088 opts := tc.opts.Clone() 2089 opts.Colorize = &colorize 2090 2091 expected := strings.TrimSpace(tc.expected) 2092 actual := tc.diff.RenderHuman(0, opts) 2093 if diff := cmp.Diff(expected, actual); len(diff) > 0 { 2094 t.Fatalf("\nexpected:\n%s\nactual:\n%s\ndiff:\n%s\n", expected, actual, diff) 2095 } 2096 }) 2097 } 2098 }