github.com/uchennaokeke444/nomad@v0.11.8/nomad/structs/diff_test.go (about) 1 package structs 2 3 import ( 4 "reflect" 5 "testing" 6 "time" 7 8 "github.com/hashicorp/nomad/helper" 9 "github.com/stretchr/testify/require" 10 ) 11 12 func TestJobDiff(t *testing.T) { 13 cases := []struct { 14 Old, New *Job 15 Expected *JobDiff 16 Error bool 17 Contextual bool 18 }{ 19 { 20 Old: nil, 21 New: nil, 22 Expected: &JobDiff{ 23 Type: DiffTypeNone, 24 }, 25 }, 26 { 27 // Different IDs 28 Old: &Job{ 29 ID: "foo", 30 }, 31 New: &Job{ 32 ID: "bar", 33 }, 34 Error: true, 35 }, 36 { 37 // Primitive only that is the same 38 Old: &Job{ 39 Region: "foo", 40 ID: "foo", 41 Name: "foo", 42 Type: "batch", 43 Priority: 10, 44 AllAtOnce: true, 45 Meta: map[string]string{ 46 "foo": "bar", 47 }, 48 }, 49 New: &Job{ 50 Region: "foo", 51 ID: "foo", 52 Name: "foo", 53 Type: "batch", 54 Priority: 10, 55 AllAtOnce: true, 56 Meta: map[string]string{ 57 "foo": "bar", 58 }, 59 }, 60 Expected: &JobDiff{ 61 Type: DiffTypeNone, 62 ID: "foo", 63 }, 64 }, 65 { 66 // Primitive only that is has diffs 67 Old: &Job{ 68 Region: "foo", 69 ID: "foo", 70 Name: "foo", 71 Type: "batch", 72 Priority: 10, 73 AllAtOnce: true, 74 Meta: map[string]string{ 75 "foo": "bar", 76 }, 77 }, 78 New: &Job{ 79 Region: "bar", 80 ID: "foo", 81 Name: "bar", 82 Type: "system", 83 Priority: 100, 84 AllAtOnce: false, 85 Meta: map[string]string{ 86 "foo": "baz", 87 }, 88 }, 89 Expected: &JobDiff{ 90 Type: DiffTypeEdited, 91 ID: "foo", 92 Fields: []*FieldDiff{ 93 { 94 Type: DiffTypeEdited, 95 Name: "AllAtOnce", 96 Old: "true", 97 New: "false", 98 }, 99 { 100 Type: DiffTypeEdited, 101 Name: "Meta[foo]", 102 Old: "bar", 103 New: "baz", 104 }, 105 { 106 Type: DiffTypeEdited, 107 Name: "Name", 108 Old: "foo", 109 New: "bar", 110 }, 111 { 112 Type: DiffTypeEdited, 113 Name: "Priority", 114 Old: "10", 115 New: "100", 116 }, 117 { 118 Type: DiffTypeEdited, 119 Name: "Region", 120 Old: "foo", 121 New: "bar", 122 }, 123 { 124 Type: DiffTypeEdited, 125 Name: "Type", 126 Old: "batch", 127 New: "system", 128 }, 129 }, 130 }, 131 }, 132 { 133 // Primitive only deleted job 134 Old: &Job{ 135 Region: "foo", 136 ID: "foo", 137 Name: "foo", 138 Type: "batch", 139 Priority: 10, 140 AllAtOnce: true, 141 Meta: map[string]string{ 142 "foo": "bar", 143 }, 144 }, 145 New: nil, 146 Expected: &JobDiff{ 147 Type: DiffTypeDeleted, 148 ID: "foo", 149 Fields: []*FieldDiff{ 150 { 151 Type: DiffTypeDeleted, 152 Name: "AllAtOnce", 153 Old: "true", 154 New: "", 155 }, 156 { 157 Type: DiffTypeDeleted, 158 Name: "Dispatched", 159 Old: "false", 160 New: "", 161 }, 162 { 163 Type: DiffTypeDeleted, 164 Name: "Meta[foo]", 165 Old: "bar", 166 New: "", 167 }, 168 { 169 Type: DiffTypeDeleted, 170 Name: "Name", 171 Old: "foo", 172 New: "", 173 }, 174 { 175 Type: DiffTypeDeleted, 176 Name: "Priority", 177 Old: "10", 178 New: "", 179 }, 180 { 181 Type: DiffTypeDeleted, 182 Name: "Region", 183 Old: "foo", 184 New: "", 185 }, 186 { 187 Type: DiffTypeDeleted, 188 Name: "Stop", 189 Old: "false", 190 New: "", 191 }, 192 { 193 Type: DiffTypeDeleted, 194 Name: "Type", 195 Old: "batch", 196 New: "", 197 }, 198 }, 199 }, 200 }, 201 { 202 // Primitive only added job 203 Old: nil, 204 New: &Job{ 205 Region: "foo", 206 ID: "foo", 207 Name: "foo", 208 Type: "batch", 209 Priority: 10, 210 AllAtOnce: true, 211 Meta: map[string]string{ 212 "foo": "bar", 213 }, 214 }, 215 Expected: &JobDiff{ 216 Type: DiffTypeAdded, 217 ID: "foo", 218 Fields: []*FieldDiff{ 219 { 220 Type: DiffTypeAdded, 221 Name: "AllAtOnce", 222 Old: "", 223 New: "true", 224 }, 225 { 226 Type: DiffTypeAdded, 227 Name: "Dispatched", 228 Old: "", 229 New: "false", 230 }, 231 { 232 Type: DiffTypeAdded, 233 Name: "Meta[foo]", 234 Old: "", 235 New: "bar", 236 }, 237 { 238 Type: DiffTypeAdded, 239 Name: "Name", 240 Old: "", 241 New: "foo", 242 }, 243 { 244 Type: DiffTypeAdded, 245 Name: "Priority", 246 Old: "", 247 New: "10", 248 }, 249 { 250 Type: DiffTypeAdded, 251 Name: "Region", 252 Old: "", 253 New: "foo", 254 }, 255 { 256 Type: DiffTypeAdded, 257 Name: "Stop", 258 Old: "", 259 New: "false", 260 }, 261 { 262 Type: DiffTypeAdded, 263 Name: "Type", 264 Old: "", 265 New: "batch", 266 }, 267 }, 268 }, 269 }, 270 { 271 // Map diff 272 Old: &Job{ 273 Meta: map[string]string{ 274 "foo": "foo", 275 "bar": "bar", 276 }, 277 }, 278 New: &Job{ 279 Meta: map[string]string{ 280 "bar": "bar", 281 "baz": "baz", 282 }, 283 }, 284 Expected: &JobDiff{ 285 Type: DiffTypeEdited, 286 Fields: []*FieldDiff{ 287 { 288 Type: DiffTypeAdded, 289 Name: "Meta[baz]", 290 Old: "", 291 New: "baz", 292 }, 293 { 294 Type: DiffTypeDeleted, 295 Name: "Meta[foo]", 296 Old: "foo", 297 New: "", 298 }, 299 }, 300 }, 301 }, 302 { 303 // Datacenter diff both added and removed 304 Old: &Job{ 305 Datacenters: []string{"foo", "bar"}, 306 }, 307 New: &Job{ 308 Datacenters: []string{"baz", "bar"}, 309 }, 310 Expected: &JobDiff{ 311 Type: DiffTypeEdited, 312 Objects: []*ObjectDiff{ 313 { 314 Type: DiffTypeEdited, 315 Name: "Datacenters", 316 Fields: []*FieldDiff{ 317 { 318 Type: DiffTypeAdded, 319 Name: "Datacenters", 320 Old: "", 321 New: "baz", 322 }, 323 { 324 Type: DiffTypeDeleted, 325 Name: "Datacenters", 326 Old: "foo", 327 New: "", 328 }, 329 }, 330 }, 331 }, 332 }, 333 }, 334 { 335 // Datacenter diff just added 336 Old: &Job{ 337 Datacenters: []string{"foo", "bar"}, 338 }, 339 New: &Job{ 340 Datacenters: []string{"foo", "bar", "baz"}, 341 }, 342 Expected: &JobDiff{ 343 Type: DiffTypeEdited, 344 Objects: []*ObjectDiff{ 345 { 346 Type: DiffTypeAdded, 347 Name: "Datacenters", 348 Fields: []*FieldDiff{ 349 { 350 Type: DiffTypeAdded, 351 Name: "Datacenters", 352 Old: "", 353 New: "baz", 354 }, 355 }, 356 }, 357 }, 358 }, 359 }, 360 { 361 // Datacenter diff just deleted 362 Old: &Job{ 363 Datacenters: []string{"foo", "bar"}, 364 }, 365 New: &Job{ 366 Datacenters: []string{"foo"}, 367 }, 368 Expected: &JobDiff{ 369 Type: DiffTypeEdited, 370 Objects: []*ObjectDiff{ 371 { 372 Type: DiffTypeDeleted, 373 Name: "Datacenters", 374 Fields: []*FieldDiff{ 375 { 376 Type: DiffTypeDeleted, 377 Name: "Datacenters", 378 Old: "bar", 379 New: "", 380 }, 381 }, 382 }, 383 }, 384 }, 385 }, 386 { 387 // Datacenter contextual no change 388 Contextual: true, 389 Old: &Job{ 390 Datacenters: []string{"foo", "bar"}, 391 }, 392 New: &Job{ 393 Datacenters: []string{"foo", "bar"}, 394 }, 395 Expected: &JobDiff{ 396 Type: DiffTypeNone, 397 }, 398 }, 399 { 400 // Datacenter contextual 401 Contextual: true, 402 Old: &Job{ 403 Datacenters: []string{"foo", "bar"}, 404 }, 405 New: &Job{ 406 Datacenters: []string{"foo", "bar", "baz"}, 407 }, 408 Expected: &JobDiff{ 409 Type: DiffTypeEdited, 410 Objects: []*ObjectDiff{ 411 { 412 Type: DiffTypeAdded, 413 Name: "Datacenters", 414 Fields: []*FieldDiff{ 415 { 416 Type: DiffTypeAdded, 417 Name: "Datacenters", 418 Old: "", 419 New: "baz", 420 }, 421 { 422 Type: DiffTypeNone, 423 Name: "Datacenters", 424 Old: "bar", 425 New: "bar", 426 }, 427 { 428 Type: DiffTypeNone, 429 Name: "Datacenters", 430 Old: "foo", 431 New: "foo", 432 }, 433 }, 434 }, 435 }, 436 }, 437 }, 438 { 439 // Periodic added 440 Old: &Job{}, 441 New: &Job{ 442 Periodic: &PeriodicConfig{ 443 Enabled: false, 444 Spec: "*/15 * * * * *", 445 SpecType: "foo", 446 ProhibitOverlap: false, 447 TimeZone: "Europe/Minsk", 448 }, 449 }, 450 Expected: &JobDiff{ 451 Type: DiffTypeEdited, 452 Objects: []*ObjectDiff{ 453 { 454 Type: DiffTypeAdded, 455 Name: "Periodic", 456 Fields: []*FieldDiff{ 457 { 458 Type: DiffTypeAdded, 459 Name: "Enabled", 460 Old: "", 461 New: "false", 462 }, 463 { 464 Type: DiffTypeAdded, 465 Name: "ProhibitOverlap", 466 Old: "", 467 New: "false", 468 }, 469 { 470 Type: DiffTypeAdded, 471 Name: "Spec", 472 Old: "", 473 New: "*/15 * * * * *", 474 }, 475 { 476 Type: DiffTypeAdded, 477 Name: "SpecType", 478 Old: "", 479 New: "foo", 480 }, 481 { 482 Type: DiffTypeAdded, 483 Name: "TimeZone", 484 Old: "", 485 New: "Europe/Minsk", 486 }, 487 }, 488 }, 489 }, 490 }, 491 }, 492 { 493 // Periodic deleted 494 Old: &Job{ 495 Periodic: &PeriodicConfig{ 496 Enabled: false, 497 Spec: "*/15 * * * * *", 498 SpecType: "foo", 499 ProhibitOverlap: false, 500 TimeZone: "Europe/Minsk", 501 }, 502 }, 503 New: &Job{}, 504 Expected: &JobDiff{ 505 Type: DiffTypeEdited, 506 Objects: []*ObjectDiff{ 507 { 508 Type: DiffTypeDeleted, 509 Name: "Periodic", 510 Fields: []*FieldDiff{ 511 { 512 Type: DiffTypeDeleted, 513 Name: "Enabled", 514 Old: "false", 515 New: "", 516 }, 517 { 518 Type: DiffTypeDeleted, 519 Name: "ProhibitOverlap", 520 Old: "false", 521 New: "", 522 }, 523 { 524 Type: DiffTypeDeleted, 525 Name: "Spec", 526 Old: "*/15 * * * * *", 527 New: "", 528 }, 529 { 530 Type: DiffTypeDeleted, 531 Name: "SpecType", 532 Old: "foo", 533 New: "", 534 }, 535 { 536 Type: DiffTypeDeleted, 537 Name: "TimeZone", 538 Old: "Europe/Minsk", 539 New: "", 540 }, 541 }, 542 }, 543 }, 544 }, 545 }, 546 { 547 // Periodic edited 548 Old: &Job{ 549 Periodic: &PeriodicConfig{ 550 Enabled: false, 551 Spec: "*/15 * * * * *", 552 SpecType: "foo", 553 ProhibitOverlap: false, 554 TimeZone: "Europe/Minsk", 555 }, 556 }, 557 New: &Job{ 558 Periodic: &PeriodicConfig{ 559 Enabled: true, 560 Spec: "* * * * * *", 561 SpecType: "cron", 562 ProhibitOverlap: true, 563 TimeZone: "America/Los_Angeles", 564 }, 565 }, 566 Expected: &JobDiff{ 567 Type: DiffTypeEdited, 568 Objects: []*ObjectDiff{ 569 { 570 Type: DiffTypeEdited, 571 Name: "Periodic", 572 Fields: []*FieldDiff{ 573 { 574 Type: DiffTypeEdited, 575 Name: "Enabled", 576 Old: "false", 577 New: "true", 578 }, 579 { 580 Type: DiffTypeEdited, 581 Name: "ProhibitOverlap", 582 Old: "false", 583 New: "true", 584 }, 585 { 586 Type: DiffTypeEdited, 587 Name: "Spec", 588 Old: "*/15 * * * * *", 589 New: "* * * * * *", 590 }, 591 { 592 Type: DiffTypeEdited, 593 Name: "SpecType", 594 Old: "foo", 595 New: "cron", 596 }, 597 { 598 Type: DiffTypeEdited, 599 Name: "TimeZone", 600 Old: "Europe/Minsk", 601 New: "America/Los_Angeles", 602 }, 603 }, 604 }, 605 }, 606 }, 607 }, 608 { 609 // Periodic edited with context 610 Contextual: true, 611 Old: &Job{ 612 Periodic: &PeriodicConfig{ 613 Enabled: false, 614 Spec: "*/15 * * * * *", 615 SpecType: "foo", 616 ProhibitOverlap: false, 617 TimeZone: "Europe/Minsk", 618 }, 619 }, 620 New: &Job{ 621 Periodic: &PeriodicConfig{ 622 Enabled: true, 623 Spec: "* * * * * *", 624 SpecType: "foo", 625 ProhibitOverlap: false, 626 TimeZone: "Europe/Minsk", 627 }, 628 }, 629 Expected: &JobDiff{ 630 Type: DiffTypeEdited, 631 Objects: []*ObjectDiff{ 632 { 633 Type: DiffTypeEdited, 634 Name: "Periodic", 635 Fields: []*FieldDiff{ 636 { 637 Type: DiffTypeEdited, 638 Name: "Enabled", 639 Old: "false", 640 New: "true", 641 }, 642 { 643 Type: DiffTypeNone, 644 Name: "ProhibitOverlap", 645 Old: "false", 646 New: "false", 647 }, 648 { 649 Type: DiffTypeEdited, 650 Name: "Spec", 651 Old: "*/15 * * * * *", 652 New: "* * * * * *", 653 }, 654 { 655 Type: DiffTypeNone, 656 Name: "SpecType", 657 Old: "foo", 658 New: "foo", 659 }, 660 { 661 Type: DiffTypeNone, 662 Name: "TimeZone", 663 Old: "Europe/Minsk", 664 New: "Europe/Minsk", 665 }, 666 }, 667 }, 668 }, 669 }, 670 }, 671 { 672 // Constraints edited 673 Old: &Job{ 674 Constraints: []*Constraint{ 675 { 676 LTarget: "foo", 677 RTarget: "foo", 678 Operand: "foo", 679 str: "foo", 680 }, 681 { 682 LTarget: "bar", 683 RTarget: "bar", 684 Operand: "bar", 685 str: "bar", 686 }, 687 }, 688 }, 689 New: &Job{ 690 Constraints: []*Constraint{ 691 { 692 LTarget: "foo", 693 RTarget: "foo", 694 Operand: "foo", 695 str: "foo", 696 }, 697 { 698 LTarget: "baz", 699 RTarget: "baz", 700 Operand: "baz", 701 str: "baz", 702 }, 703 }, 704 }, 705 Expected: &JobDiff{ 706 Type: DiffTypeEdited, 707 Objects: []*ObjectDiff{ 708 { 709 Type: DiffTypeAdded, 710 Name: "Constraint", 711 Fields: []*FieldDiff{ 712 { 713 Type: DiffTypeAdded, 714 Name: "LTarget", 715 Old: "", 716 New: "baz", 717 }, 718 { 719 Type: DiffTypeAdded, 720 Name: "Operand", 721 Old: "", 722 New: "baz", 723 }, 724 { 725 Type: DiffTypeAdded, 726 Name: "RTarget", 727 Old: "", 728 New: "baz", 729 }, 730 }, 731 }, 732 { 733 Type: DiffTypeDeleted, 734 Name: "Constraint", 735 Fields: []*FieldDiff{ 736 { 737 Type: DiffTypeDeleted, 738 Name: "LTarget", 739 Old: "bar", 740 New: "", 741 }, 742 { 743 Type: DiffTypeDeleted, 744 Name: "Operand", 745 Old: "bar", 746 New: "", 747 }, 748 { 749 Type: DiffTypeDeleted, 750 Name: "RTarget", 751 Old: "bar", 752 New: "", 753 }, 754 }, 755 }, 756 }, 757 }, 758 }, 759 { 760 // Affinities edited 761 Old: &Job{ 762 Affinities: []*Affinity{ 763 { 764 LTarget: "foo", 765 RTarget: "foo", 766 Operand: "foo", 767 Weight: 20, 768 str: "foo", 769 }, 770 { 771 LTarget: "bar", 772 RTarget: "bar", 773 Operand: "bar", 774 Weight: 20, 775 str: "bar", 776 }, 777 }, 778 }, 779 New: &Job{ 780 Affinities: []*Affinity{ 781 { 782 LTarget: "foo", 783 RTarget: "foo", 784 Operand: "foo", 785 Weight: 20, 786 str: "foo", 787 }, 788 { 789 LTarget: "baz", 790 RTarget: "baz", 791 Operand: "baz", 792 Weight: 20, 793 str: "baz", 794 }, 795 }, 796 }, 797 Expected: &JobDiff{ 798 Type: DiffTypeEdited, 799 Objects: []*ObjectDiff{ 800 { 801 Type: DiffTypeAdded, 802 Name: "Affinity", 803 Fields: []*FieldDiff{ 804 { 805 Type: DiffTypeAdded, 806 Name: "LTarget", 807 Old: "", 808 New: "baz", 809 }, 810 { 811 Type: DiffTypeAdded, 812 Name: "Operand", 813 Old: "", 814 New: "baz", 815 }, 816 { 817 Type: DiffTypeAdded, 818 Name: "RTarget", 819 Old: "", 820 New: "baz", 821 }, 822 { 823 Type: DiffTypeAdded, 824 Name: "Weight", 825 Old: "", 826 New: "20", 827 }, 828 }, 829 }, 830 { 831 Type: DiffTypeDeleted, 832 Name: "Affinity", 833 Fields: []*FieldDiff{ 834 { 835 Type: DiffTypeDeleted, 836 Name: "LTarget", 837 Old: "bar", 838 New: "", 839 }, 840 { 841 Type: DiffTypeDeleted, 842 Name: "Operand", 843 Old: "bar", 844 New: "", 845 }, 846 { 847 Type: DiffTypeDeleted, 848 Name: "RTarget", 849 Old: "bar", 850 New: "", 851 }, 852 { 853 Type: DiffTypeDeleted, 854 Name: "Weight", 855 Old: "20", 856 New: "", 857 }, 858 }, 859 }, 860 }, 861 }, 862 }, 863 { 864 // Task groups edited 865 Old: &Job{ 866 TaskGroups: []*TaskGroup{ 867 { 868 Name: "foo", 869 Count: 1, 870 }, 871 { 872 Name: "bar", 873 Count: 1, 874 }, 875 { 876 Name: "baz", 877 Count: 1, 878 }, 879 }, 880 }, 881 New: &Job{ 882 TaskGroups: []*TaskGroup{ 883 { 884 Name: "bar", 885 Count: 1, 886 }, 887 { 888 Name: "baz", 889 Count: 2, 890 }, 891 { 892 Name: "bam", 893 Count: 1, 894 }, 895 }, 896 }, 897 Expected: &JobDiff{ 898 Type: DiffTypeEdited, 899 TaskGroups: []*TaskGroupDiff{ 900 { 901 Type: DiffTypeAdded, 902 Name: "bam", 903 Fields: []*FieldDiff{ 904 { 905 Type: DiffTypeAdded, 906 Name: "Count", 907 Old: "", 908 New: "1", 909 }, 910 }, 911 }, 912 { 913 Type: DiffTypeNone, 914 Name: "bar", 915 }, 916 { 917 Type: DiffTypeEdited, 918 Name: "baz", 919 Fields: []*FieldDiff{ 920 { 921 Type: DiffTypeEdited, 922 Name: "Count", 923 Old: "1", 924 New: "2", 925 }, 926 }, 927 }, 928 { 929 Type: DiffTypeDeleted, 930 Name: "foo", 931 Fields: []*FieldDiff{ 932 { 933 Type: DiffTypeDeleted, 934 Name: "Count", 935 Old: "1", 936 New: "", 937 }, 938 }, 939 }, 940 }, 941 }, 942 }, 943 { 944 // Parameterized Job added 945 Old: &Job{}, 946 New: &Job{ 947 ParameterizedJob: &ParameterizedJobConfig{ 948 Payload: DispatchPayloadRequired, 949 MetaOptional: []string{"foo"}, 950 MetaRequired: []string{"bar"}, 951 }, 952 }, 953 Expected: &JobDiff{ 954 Type: DiffTypeEdited, 955 Objects: []*ObjectDiff{ 956 { 957 Type: DiffTypeAdded, 958 Name: "ParameterizedJob", 959 Fields: []*FieldDiff{ 960 { 961 Type: DiffTypeAdded, 962 Name: "Payload", 963 Old: "", 964 New: DispatchPayloadRequired, 965 }, 966 }, 967 Objects: []*ObjectDiff{ 968 { 969 Type: DiffTypeAdded, 970 Name: "MetaOptional", 971 Fields: []*FieldDiff{ 972 { 973 Type: DiffTypeAdded, 974 Name: "MetaOptional", 975 Old: "", 976 New: "foo", 977 }, 978 }, 979 }, 980 { 981 Type: DiffTypeAdded, 982 Name: "MetaRequired", 983 Fields: []*FieldDiff{ 984 { 985 Type: DiffTypeAdded, 986 Name: "MetaRequired", 987 Old: "", 988 New: "bar", 989 }, 990 }, 991 }, 992 }, 993 }, 994 }, 995 }, 996 }, 997 { 998 // Parameterized Job deleted 999 Old: &Job{ 1000 ParameterizedJob: &ParameterizedJobConfig{ 1001 Payload: DispatchPayloadRequired, 1002 MetaOptional: []string{"foo"}, 1003 MetaRequired: []string{"bar"}, 1004 }, 1005 }, 1006 New: &Job{}, 1007 Expected: &JobDiff{ 1008 Type: DiffTypeEdited, 1009 Objects: []*ObjectDiff{ 1010 { 1011 Type: DiffTypeDeleted, 1012 Name: "ParameterizedJob", 1013 Fields: []*FieldDiff{ 1014 { 1015 Type: DiffTypeDeleted, 1016 Name: "Payload", 1017 Old: DispatchPayloadRequired, 1018 New: "", 1019 }, 1020 }, 1021 Objects: []*ObjectDiff{ 1022 { 1023 Type: DiffTypeDeleted, 1024 Name: "MetaOptional", 1025 Fields: []*FieldDiff{ 1026 { 1027 Type: DiffTypeDeleted, 1028 Name: "MetaOptional", 1029 Old: "foo", 1030 New: "", 1031 }, 1032 }, 1033 }, 1034 { 1035 Type: DiffTypeDeleted, 1036 Name: "MetaRequired", 1037 Fields: []*FieldDiff{ 1038 { 1039 Type: DiffTypeDeleted, 1040 Name: "MetaRequired", 1041 Old: "bar", 1042 New: "", 1043 }, 1044 }, 1045 }, 1046 }, 1047 }, 1048 }, 1049 }, 1050 }, 1051 { 1052 // Parameterized Job edited 1053 Old: &Job{ 1054 ParameterizedJob: &ParameterizedJobConfig{ 1055 Payload: DispatchPayloadRequired, 1056 MetaOptional: []string{"foo"}, 1057 MetaRequired: []string{"bar"}, 1058 }, 1059 }, 1060 New: &Job{ 1061 ParameterizedJob: &ParameterizedJobConfig{ 1062 Payload: DispatchPayloadOptional, 1063 MetaOptional: []string{"bam"}, 1064 MetaRequired: []string{"bang"}, 1065 }, 1066 }, 1067 Expected: &JobDiff{ 1068 Type: DiffTypeEdited, 1069 Objects: []*ObjectDiff{ 1070 { 1071 Type: DiffTypeEdited, 1072 Name: "ParameterizedJob", 1073 Fields: []*FieldDiff{ 1074 { 1075 Type: DiffTypeEdited, 1076 Name: "Payload", 1077 Old: DispatchPayloadRequired, 1078 New: DispatchPayloadOptional, 1079 }, 1080 }, 1081 Objects: []*ObjectDiff{ 1082 { 1083 Type: DiffTypeEdited, 1084 Name: "MetaOptional", 1085 Fields: []*FieldDiff{ 1086 { 1087 Type: DiffTypeAdded, 1088 Name: "MetaOptional", 1089 Old: "", 1090 New: "bam", 1091 }, 1092 { 1093 Type: DiffTypeDeleted, 1094 Name: "MetaOptional", 1095 Old: "foo", 1096 New: "", 1097 }, 1098 }, 1099 }, 1100 { 1101 Type: DiffTypeEdited, 1102 Name: "MetaRequired", 1103 Fields: []*FieldDiff{ 1104 { 1105 Type: DiffTypeAdded, 1106 Name: "MetaRequired", 1107 Old: "", 1108 New: "bang", 1109 }, 1110 { 1111 Type: DiffTypeDeleted, 1112 Name: "MetaRequired", 1113 Old: "bar", 1114 New: "", 1115 }, 1116 }, 1117 }, 1118 }, 1119 }, 1120 }, 1121 }, 1122 }, 1123 { 1124 // Parameterized Job edited with context 1125 Contextual: true, 1126 Old: &Job{ 1127 ParameterizedJob: &ParameterizedJobConfig{ 1128 Payload: DispatchPayloadRequired, 1129 MetaOptional: []string{"foo"}, 1130 MetaRequired: []string{"bar"}, 1131 }, 1132 }, 1133 New: &Job{ 1134 ParameterizedJob: &ParameterizedJobConfig{ 1135 Payload: DispatchPayloadOptional, 1136 MetaOptional: []string{"foo"}, 1137 MetaRequired: []string{"bar"}, 1138 }, 1139 }, 1140 Expected: &JobDiff{ 1141 Type: DiffTypeEdited, 1142 Objects: []*ObjectDiff{ 1143 { 1144 Type: DiffTypeEdited, 1145 Name: "ParameterizedJob", 1146 Fields: []*FieldDiff{ 1147 { 1148 Type: DiffTypeEdited, 1149 Name: "Payload", 1150 Old: DispatchPayloadRequired, 1151 New: DispatchPayloadOptional, 1152 }, 1153 }, 1154 Objects: []*ObjectDiff{ 1155 { 1156 Type: DiffTypeNone, 1157 Name: "MetaOptional", 1158 Fields: []*FieldDiff{ 1159 { 1160 Type: DiffTypeNone, 1161 Name: "MetaOptional", 1162 Old: "foo", 1163 New: "foo", 1164 }, 1165 }, 1166 }, 1167 { 1168 Type: DiffTypeNone, 1169 Name: "MetaRequired", 1170 Fields: []*FieldDiff{ 1171 { 1172 Type: DiffTypeNone, 1173 Name: "MetaRequired", 1174 Old: "bar", 1175 New: "bar", 1176 }, 1177 }, 1178 }, 1179 }, 1180 }, 1181 }, 1182 }, 1183 }, 1184 } 1185 1186 for i, c := range cases { 1187 actual, err := c.Old.Diff(c.New, c.Contextual) 1188 if c.Error && err == nil { 1189 t.Fatalf("case %d: expected errored", i+1) 1190 } else if err != nil { 1191 if !c.Error { 1192 t.Fatalf("case %d: errored %#v", i+1, err) 1193 } else { 1194 continue 1195 } 1196 } 1197 1198 if !reflect.DeepEqual(actual, c.Expected) { 1199 t.Fatalf("case %d: got:\n%#v\n want:\n%#v\n", 1200 i+1, actual, c.Expected) 1201 } 1202 } 1203 } 1204 1205 func TestTaskGroupDiff(t *testing.T) { 1206 cases := []struct { 1207 TestCase string 1208 Old, New *TaskGroup 1209 Expected *TaskGroupDiff 1210 ExpErr bool 1211 Contextual bool 1212 }{ 1213 { 1214 TestCase: "Empty", 1215 Old: nil, 1216 New: nil, 1217 Expected: &TaskGroupDiff{ 1218 Type: DiffTypeNone, 1219 }, 1220 }, 1221 { 1222 TestCase: "Primitive only that has different names", 1223 Old: &TaskGroup{ 1224 Name: "foo", 1225 Count: 10, 1226 Meta: map[string]string{ 1227 "foo": "bar", 1228 }, 1229 }, 1230 New: &TaskGroup{ 1231 Name: "bar", 1232 Count: 10, 1233 Meta: map[string]string{ 1234 "foo": "bar", 1235 }, 1236 }, 1237 ExpErr: true, 1238 }, 1239 { 1240 TestCase: "Primitive only that is the same", 1241 Old: &TaskGroup{ 1242 Name: "foo", 1243 Count: 10, 1244 Meta: map[string]string{ 1245 "foo": "bar", 1246 }, 1247 }, 1248 New: &TaskGroup{ 1249 Name: "foo", 1250 Count: 10, 1251 Meta: map[string]string{ 1252 "foo": "bar", 1253 }, 1254 }, 1255 Expected: &TaskGroupDiff{ 1256 Type: DiffTypeNone, 1257 Name: "foo", 1258 }, 1259 }, 1260 { 1261 TestCase: "Primitive only that has diffs", 1262 Old: &TaskGroup{ 1263 Name: "foo", 1264 Count: 10, 1265 Meta: map[string]string{ 1266 "foo": "bar", 1267 }, 1268 }, 1269 New: &TaskGroup{ 1270 Name: "foo", 1271 Count: 100, 1272 Meta: map[string]string{ 1273 "foo": "baz", 1274 }, 1275 }, 1276 Expected: &TaskGroupDiff{ 1277 Type: DiffTypeEdited, 1278 Name: "foo", 1279 Fields: []*FieldDiff{ 1280 { 1281 Type: DiffTypeEdited, 1282 Name: "Count", 1283 Old: "10", 1284 New: "100", 1285 }, 1286 { 1287 Type: DiffTypeEdited, 1288 Name: "Meta[foo]", 1289 Old: "bar", 1290 New: "baz", 1291 }, 1292 }, 1293 }, 1294 }, 1295 { 1296 TestCase: "Map diff", 1297 Old: &TaskGroup{ 1298 Meta: map[string]string{ 1299 "foo": "foo", 1300 "bar": "bar", 1301 }, 1302 }, 1303 New: &TaskGroup{ 1304 Meta: map[string]string{ 1305 "bar": "bar", 1306 "baz": "baz", 1307 }, 1308 }, 1309 Expected: &TaskGroupDiff{ 1310 Type: DiffTypeEdited, 1311 Fields: []*FieldDiff{ 1312 { 1313 Type: DiffTypeAdded, 1314 Name: "Meta[baz]", 1315 Old: "", 1316 New: "baz", 1317 }, 1318 { 1319 Type: DiffTypeDeleted, 1320 Name: "Meta[foo]", 1321 Old: "foo", 1322 New: "", 1323 }, 1324 }, 1325 }, 1326 }, 1327 { 1328 TestCase: "Constraints edited", 1329 Old: &TaskGroup{ 1330 Constraints: []*Constraint{ 1331 { 1332 LTarget: "foo", 1333 RTarget: "foo", 1334 Operand: "foo", 1335 str: "foo", 1336 }, 1337 { 1338 LTarget: "bar", 1339 RTarget: "bar", 1340 Operand: "bar", 1341 str: "bar", 1342 }, 1343 }, 1344 }, 1345 New: &TaskGroup{ 1346 Constraints: []*Constraint{ 1347 { 1348 LTarget: "foo", 1349 RTarget: "foo", 1350 Operand: "foo", 1351 str: "foo", 1352 }, 1353 { 1354 LTarget: "baz", 1355 RTarget: "baz", 1356 Operand: "baz", 1357 str: "baz", 1358 }, 1359 }, 1360 }, 1361 Expected: &TaskGroupDiff{ 1362 Type: DiffTypeEdited, 1363 Objects: []*ObjectDiff{ 1364 { 1365 Type: DiffTypeAdded, 1366 Name: "Constraint", 1367 Fields: []*FieldDiff{ 1368 { 1369 Type: DiffTypeAdded, 1370 Name: "LTarget", 1371 Old: "", 1372 New: "baz", 1373 }, 1374 { 1375 Type: DiffTypeAdded, 1376 Name: "Operand", 1377 Old: "", 1378 New: "baz", 1379 }, 1380 { 1381 Type: DiffTypeAdded, 1382 Name: "RTarget", 1383 Old: "", 1384 New: "baz", 1385 }, 1386 }, 1387 }, 1388 { 1389 Type: DiffTypeDeleted, 1390 Name: "Constraint", 1391 Fields: []*FieldDiff{ 1392 { 1393 Type: DiffTypeDeleted, 1394 Name: "LTarget", 1395 Old: "bar", 1396 New: "", 1397 }, 1398 { 1399 Type: DiffTypeDeleted, 1400 Name: "Operand", 1401 Old: "bar", 1402 New: "", 1403 }, 1404 { 1405 Type: DiffTypeDeleted, 1406 Name: "RTarget", 1407 Old: "bar", 1408 New: "", 1409 }, 1410 }, 1411 }, 1412 }, 1413 }, 1414 }, 1415 { 1416 TestCase: "Affinities edited", 1417 Old: &TaskGroup{ 1418 Affinities: []*Affinity{ 1419 { 1420 LTarget: "foo", 1421 RTarget: "foo", 1422 Operand: "foo", 1423 Weight: 20, 1424 str: "foo", 1425 }, 1426 { 1427 LTarget: "bar", 1428 RTarget: "bar", 1429 Operand: "bar", 1430 Weight: 20, 1431 str: "bar", 1432 }, 1433 }, 1434 }, 1435 New: &TaskGroup{ 1436 Affinities: []*Affinity{ 1437 { 1438 LTarget: "foo", 1439 RTarget: "foo", 1440 Operand: "foo", 1441 Weight: 20, 1442 str: "foo", 1443 }, 1444 { 1445 LTarget: "baz", 1446 RTarget: "baz", 1447 Operand: "baz", 1448 Weight: 20, 1449 str: "baz", 1450 }, 1451 }, 1452 }, 1453 Expected: &TaskGroupDiff{ 1454 Type: DiffTypeEdited, 1455 Objects: []*ObjectDiff{ 1456 { 1457 Type: DiffTypeAdded, 1458 Name: "Affinity", 1459 Fields: []*FieldDiff{ 1460 { 1461 Type: DiffTypeAdded, 1462 Name: "LTarget", 1463 Old: "", 1464 New: "baz", 1465 }, 1466 { 1467 Type: DiffTypeAdded, 1468 Name: "Operand", 1469 Old: "", 1470 New: "baz", 1471 }, 1472 { 1473 Type: DiffTypeAdded, 1474 Name: "RTarget", 1475 Old: "", 1476 New: "baz", 1477 }, 1478 { 1479 Type: DiffTypeAdded, 1480 Name: "Weight", 1481 Old: "", 1482 New: "20", 1483 }, 1484 }, 1485 }, 1486 { 1487 Type: DiffTypeDeleted, 1488 Name: "Affinity", 1489 Fields: []*FieldDiff{ 1490 { 1491 Type: DiffTypeDeleted, 1492 Name: "LTarget", 1493 Old: "bar", 1494 New: "", 1495 }, 1496 { 1497 Type: DiffTypeDeleted, 1498 Name: "Operand", 1499 Old: "bar", 1500 New: "", 1501 }, 1502 { 1503 Type: DiffTypeDeleted, 1504 Name: "RTarget", 1505 Old: "bar", 1506 New: "", 1507 }, 1508 { 1509 Type: DiffTypeDeleted, 1510 Name: "Weight", 1511 Old: "20", 1512 New: "", 1513 }, 1514 }, 1515 }, 1516 }, 1517 }, 1518 }, 1519 { 1520 TestCase: "RestartPolicy added", 1521 Old: &TaskGroup{}, 1522 New: &TaskGroup{ 1523 RestartPolicy: &RestartPolicy{ 1524 Attempts: 1, 1525 Interval: 1 * time.Second, 1526 Delay: 1 * time.Second, 1527 Mode: "fail", 1528 }, 1529 }, 1530 Expected: &TaskGroupDiff{ 1531 Type: DiffTypeEdited, 1532 Objects: []*ObjectDiff{ 1533 { 1534 Type: DiffTypeAdded, 1535 Name: "RestartPolicy", 1536 Fields: []*FieldDiff{ 1537 { 1538 Type: DiffTypeAdded, 1539 Name: "Attempts", 1540 Old: "", 1541 New: "1", 1542 }, 1543 { 1544 Type: DiffTypeAdded, 1545 Name: "Delay", 1546 Old: "", 1547 New: "1000000000", 1548 }, 1549 { 1550 Type: DiffTypeAdded, 1551 Name: "Interval", 1552 Old: "", 1553 New: "1000000000", 1554 }, 1555 { 1556 Type: DiffTypeAdded, 1557 Name: "Mode", 1558 Old: "", 1559 New: "fail", 1560 }, 1561 }, 1562 }, 1563 }, 1564 }, 1565 }, 1566 { 1567 TestCase: "RestartPolicy deleted", 1568 Old: &TaskGroup{ 1569 RestartPolicy: &RestartPolicy{ 1570 Attempts: 1, 1571 Interval: 1 * time.Second, 1572 Delay: 1 * time.Second, 1573 Mode: "fail", 1574 }, 1575 }, 1576 New: &TaskGroup{}, 1577 Expected: &TaskGroupDiff{ 1578 Type: DiffTypeEdited, 1579 Objects: []*ObjectDiff{ 1580 { 1581 Type: DiffTypeDeleted, 1582 Name: "RestartPolicy", 1583 Fields: []*FieldDiff{ 1584 { 1585 Type: DiffTypeDeleted, 1586 Name: "Attempts", 1587 Old: "1", 1588 New: "", 1589 }, 1590 { 1591 Type: DiffTypeDeleted, 1592 Name: "Delay", 1593 Old: "1000000000", 1594 New: "", 1595 }, 1596 { 1597 Type: DiffTypeDeleted, 1598 Name: "Interval", 1599 Old: "1000000000", 1600 New: "", 1601 }, 1602 { 1603 Type: DiffTypeDeleted, 1604 Name: "Mode", 1605 Old: "fail", 1606 New: "", 1607 }, 1608 }, 1609 }, 1610 }, 1611 }, 1612 }, 1613 { 1614 TestCase: "RestartPolicy edited", 1615 Old: &TaskGroup{ 1616 RestartPolicy: &RestartPolicy{ 1617 Attempts: 1, 1618 Interval: 1 * time.Second, 1619 Delay: 1 * time.Second, 1620 Mode: "fail", 1621 }, 1622 }, 1623 New: &TaskGroup{ 1624 RestartPolicy: &RestartPolicy{ 1625 Attempts: 2, 1626 Interval: 2 * time.Second, 1627 Delay: 2 * time.Second, 1628 Mode: "delay", 1629 }, 1630 }, 1631 Expected: &TaskGroupDiff{ 1632 Type: DiffTypeEdited, 1633 Objects: []*ObjectDiff{ 1634 { 1635 Type: DiffTypeEdited, 1636 Name: "RestartPolicy", 1637 Fields: []*FieldDiff{ 1638 { 1639 Type: DiffTypeEdited, 1640 Name: "Attempts", 1641 Old: "1", 1642 New: "2", 1643 }, 1644 { 1645 Type: DiffTypeEdited, 1646 Name: "Delay", 1647 Old: "1000000000", 1648 New: "2000000000", 1649 }, 1650 { 1651 Type: DiffTypeEdited, 1652 Name: "Interval", 1653 Old: "1000000000", 1654 New: "2000000000", 1655 }, 1656 { 1657 Type: DiffTypeEdited, 1658 Name: "Mode", 1659 Old: "fail", 1660 New: "delay", 1661 }, 1662 }, 1663 }, 1664 }, 1665 }, 1666 }, 1667 { 1668 TestCase: "RestartPolicy edited with context", 1669 Contextual: true, 1670 Old: &TaskGroup{ 1671 RestartPolicy: &RestartPolicy{ 1672 Attempts: 1, 1673 Interval: 1 * time.Second, 1674 Delay: 1 * time.Second, 1675 Mode: "fail", 1676 }, 1677 }, 1678 New: &TaskGroup{ 1679 RestartPolicy: &RestartPolicy{ 1680 Attempts: 2, 1681 Interval: 2 * time.Second, 1682 Delay: 1 * time.Second, 1683 Mode: "fail", 1684 }, 1685 }, 1686 Expected: &TaskGroupDiff{ 1687 Type: DiffTypeEdited, 1688 Objects: []*ObjectDiff{ 1689 { 1690 Type: DiffTypeEdited, 1691 Name: "RestartPolicy", 1692 Fields: []*FieldDiff{ 1693 { 1694 Type: DiffTypeEdited, 1695 Name: "Attempts", 1696 Old: "1", 1697 New: "2", 1698 }, 1699 { 1700 Type: DiffTypeNone, 1701 Name: "Delay", 1702 Old: "1000000000", 1703 New: "1000000000", 1704 }, 1705 { 1706 Type: DiffTypeEdited, 1707 Name: "Interval", 1708 Old: "1000000000", 1709 New: "2000000000", 1710 }, 1711 { 1712 Type: DiffTypeNone, 1713 Name: "Mode", 1714 Old: "fail", 1715 New: "fail", 1716 }, 1717 }, 1718 }, 1719 }, 1720 }, 1721 }, 1722 { 1723 TestCase: "ReschedulePolicy added", 1724 Old: &TaskGroup{}, 1725 New: &TaskGroup{ 1726 ReschedulePolicy: &ReschedulePolicy{ 1727 Attempts: 1, 1728 Interval: 15 * time.Second, 1729 Delay: 5 * time.Second, 1730 MaxDelay: 20 * time.Second, 1731 DelayFunction: "exponential", 1732 Unlimited: false, 1733 }, 1734 }, 1735 Expected: &TaskGroupDiff{ 1736 Type: DiffTypeEdited, 1737 Objects: []*ObjectDiff{ 1738 { 1739 Type: DiffTypeAdded, 1740 Name: "ReschedulePolicy", 1741 Fields: []*FieldDiff{ 1742 { 1743 Type: DiffTypeAdded, 1744 Name: "Attempts", 1745 Old: "", 1746 New: "1", 1747 }, 1748 { 1749 Type: DiffTypeAdded, 1750 Name: "Delay", 1751 Old: "", 1752 New: "5000000000", 1753 }, 1754 { 1755 Type: DiffTypeAdded, 1756 Name: "DelayFunction", 1757 Old: "", 1758 New: "exponential", 1759 }, 1760 { 1761 Type: DiffTypeAdded, 1762 Name: "Interval", 1763 Old: "", 1764 New: "15000000000", 1765 }, 1766 { 1767 Type: DiffTypeAdded, 1768 Name: "MaxDelay", 1769 Old: "", 1770 New: "20000000000", 1771 }, 1772 { 1773 Type: DiffTypeAdded, 1774 Name: "Unlimited", 1775 Old: "", 1776 New: "false", 1777 }, 1778 }, 1779 }, 1780 }, 1781 }, 1782 }, 1783 { 1784 TestCase: "ReschedulePolicy deleted", 1785 Old: &TaskGroup{ 1786 ReschedulePolicy: &ReschedulePolicy{ 1787 Attempts: 1, 1788 Interval: 15 * time.Second, 1789 Delay: 5 * time.Second, 1790 MaxDelay: 20 * time.Second, 1791 DelayFunction: "exponential", 1792 Unlimited: false, 1793 }, 1794 }, 1795 New: &TaskGroup{}, 1796 Expected: &TaskGroupDiff{ 1797 Type: DiffTypeEdited, 1798 Objects: []*ObjectDiff{ 1799 { 1800 Type: DiffTypeDeleted, 1801 Name: "ReschedulePolicy", 1802 Fields: []*FieldDiff{ 1803 { 1804 Type: DiffTypeDeleted, 1805 Name: "Attempts", 1806 Old: "1", 1807 New: "", 1808 }, 1809 { 1810 Type: DiffTypeDeleted, 1811 Name: "Delay", 1812 Old: "5000000000", 1813 New: "", 1814 }, 1815 { 1816 Type: DiffTypeDeleted, 1817 Name: "DelayFunction", 1818 Old: "exponential", 1819 New: "", 1820 }, 1821 { 1822 Type: DiffTypeDeleted, 1823 Name: "Interval", 1824 Old: "15000000000", 1825 New: "", 1826 }, 1827 { 1828 Type: DiffTypeDeleted, 1829 Name: "MaxDelay", 1830 Old: "20000000000", 1831 New: "", 1832 }, 1833 { 1834 Type: DiffTypeDeleted, 1835 Name: "Unlimited", 1836 Old: "false", 1837 New: "", 1838 }, 1839 }, 1840 }, 1841 }, 1842 }, 1843 }, 1844 { 1845 TestCase: "ReschedulePolicy edited", 1846 Old: &TaskGroup{ 1847 ReschedulePolicy: &ReschedulePolicy{ 1848 Attempts: 1, 1849 Interval: 1 * time.Second, 1850 DelayFunction: "exponential", 1851 Delay: 20 * time.Second, 1852 MaxDelay: 1 * time.Minute, 1853 Unlimited: false, 1854 }, 1855 }, 1856 New: &TaskGroup{ 1857 ReschedulePolicy: &ReschedulePolicy{ 1858 Attempts: 2, 1859 Interval: 2 * time.Second, 1860 DelayFunction: "constant", 1861 Delay: 30 * time.Second, 1862 MaxDelay: 1 * time.Minute, 1863 Unlimited: true, 1864 }, 1865 }, 1866 Expected: &TaskGroupDiff{ 1867 Type: DiffTypeEdited, 1868 Objects: []*ObjectDiff{ 1869 { 1870 Type: DiffTypeEdited, 1871 Name: "ReschedulePolicy", 1872 Fields: []*FieldDiff{ 1873 { 1874 Type: DiffTypeEdited, 1875 Name: "Attempts", 1876 Old: "1", 1877 New: "2", 1878 }, 1879 { 1880 Type: DiffTypeEdited, 1881 Name: "Delay", 1882 Old: "20000000000", 1883 New: "30000000000", 1884 }, 1885 { 1886 Type: DiffTypeEdited, 1887 Name: "DelayFunction", 1888 Old: "exponential", 1889 New: "constant", 1890 }, 1891 { 1892 Type: DiffTypeEdited, 1893 Name: "Interval", 1894 Old: "1000000000", 1895 New: "2000000000", 1896 }, 1897 { 1898 Type: DiffTypeEdited, 1899 Name: "Unlimited", 1900 Old: "false", 1901 New: "true", 1902 }, 1903 }, 1904 }, 1905 }, 1906 }, 1907 }, 1908 { 1909 TestCase: "ReschedulePolicy edited with context", 1910 Contextual: true, 1911 Old: &TaskGroup{ 1912 ReschedulePolicy: &ReschedulePolicy{ 1913 Attempts: 1, 1914 Interval: 1 * time.Second, 1915 }, 1916 }, 1917 New: &TaskGroup{ 1918 ReschedulePolicy: &ReschedulePolicy{ 1919 Attempts: 1, 1920 Interval: 2 * time.Second, 1921 }, 1922 }, 1923 Expected: &TaskGroupDiff{ 1924 Type: DiffTypeEdited, 1925 Objects: []*ObjectDiff{ 1926 { 1927 Type: DiffTypeEdited, 1928 Name: "ReschedulePolicy", 1929 Fields: []*FieldDiff{ 1930 { 1931 Type: DiffTypeNone, 1932 Name: "Attempts", 1933 Old: "1", 1934 New: "1", 1935 }, 1936 { 1937 Type: DiffTypeNone, 1938 Name: "Delay", 1939 Old: "0", 1940 New: "0", 1941 }, 1942 { 1943 Type: DiffTypeNone, 1944 Name: "DelayFunction", 1945 Old: "", 1946 New: "", 1947 }, 1948 { 1949 Type: DiffTypeEdited, 1950 Name: "Interval", 1951 Old: "1000000000", 1952 New: "2000000000", 1953 }, 1954 { 1955 Type: DiffTypeNone, 1956 Name: "MaxDelay", 1957 Old: "0", 1958 New: "0", 1959 }, 1960 { 1961 Type: DiffTypeNone, 1962 Name: "Unlimited", 1963 Old: "false", 1964 New: "false", 1965 }, 1966 }, 1967 }, 1968 }, 1969 }, 1970 }, 1971 { 1972 TestCase: "Update strategy deleted", 1973 Old: &TaskGroup{ 1974 Update: &UpdateStrategy{ 1975 AutoRevert: true, 1976 }, 1977 }, 1978 New: &TaskGroup{}, 1979 Expected: &TaskGroupDiff{ 1980 Type: DiffTypeEdited, 1981 Objects: []*ObjectDiff{ 1982 { 1983 Type: DiffTypeDeleted, 1984 Name: "Update", 1985 Fields: []*FieldDiff{ 1986 { 1987 Type: DiffTypeDeleted, 1988 Name: "AutoPromote", 1989 Old: "false", 1990 New: "", 1991 }, 1992 { 1993 Type: DiffTypeDeleted, 1994 Name: "AutoRevert", 1995 Old: "true", 1996 New: "", 1997 }, 1998 { 1999 Type: DiffTypeDeleted, 2000 Name: "Canary", 2001 Old: "0", 2002 New: "", 2003 }, 2004 { 2005 Type: DiffTypeDeleted, 2006 Name: "HealthyDeadline", 2007 Old: "0", 2008 New: "", 2009 }, 2010 { 2011 Type: DiffTypeDeleted, 2012 Name: "MaxParallel", 2013 Old: "0", 2014 New: "", 2015 }, 2016 { 2017 Type: DiffTypeDeleted, 2018 Name: "MinHealthyTime", 2019 Old: "0", 2020 New: "", 2021 }, 2022 { 2023 Type: DiffTypeDeleted, 2024 Name: "ProgressDeadline", 2025 Old: "0", 2026 New: "", 2027 }, 2028 }, 2029 }, 2030 }, 2031 }, 2032 }, 2033 { 2034 TestCase: "Update strategy added", 2035 Old: &TaskGroup{}, 2036 New: &TaskGroup{ 2037 Update: &UpdateStrategy{ 2038 AutoRevert: true, 2039 }, 2040 }, 2041 Expected: &TaskGroupDiff{ 2042 Type: DiffTypeEdited, 2043 Objects: []*ObjectDiff{ 2044 { 2045 Type: DiffTypeAdded, 2046 Name: "Update", 2047 Fields: []*FieldDiff{ 2048 { 2049 Type: DiffTypeAdded, 2050 Name: "AutoPromote", 2051 Old: "", 2052 New: "false", 2053 }, 2054 { 2055 Type: DiffTypeAdded, 2056 Name: "AutoRevert", 2057 Old: "", 2058 New: "true", 2059 }, 2060 { 2061 Type: DiffTypeAdded, 2062 Name: "Canary", 2063 Old: "", 2064 New: "0", 2065 }, 2066 { 2067 Type: DiffTypeAdded, 2068 Name: "HealthyDeadline", 2069 Old: "", 2070 New: "0", 2071 }, 2072 { 2073 Type: DiffTypeAdded, 2074 Name: "MaxParallel", 2075 Old: "", 2076 New: "0", 2077 }, 2078 { 2079 Type: DiffTypeAdded, 2080 Name: "MinHealthyTime", 2081 Old: "", 2082 New: "0", 2083 }, 2084 { 2085 Type: DiffTypeAdded, 2086 Name: "ProgressDeadline", 2087 Old: "", 2088 New: "0", 2089 }, 2090 }, 2091 }, 2092 }, 2093 }, 2094 }, 2095 { 2096 TestCase: "Update strategy edited", 2097 Old: &TaskGroup{ 2098 Update: &UpdateStrategy{ 2099 MaxParallel: 5, 2100 HealthCheck: "foo", 2101 MinHealthyTime: 1 * time.Second, 2102 HealthyDeadline: 30 * time.Second, 2103 ProgressDeadline: 29 * time.Second, 2104 AutoRevert: true, 2105 AutoPromote: true, 2106 Canary: 2, 2107 }, 2108 }, 2109 New: &TaskGroup{ 2110 Update: &UpdateStrategy{ 2111 MaxParallel: 7, 2112 HealthCheck: "bar", 2113 MinHealthyTime: 2 * time.Second, 2114 HealthyDeadline: 31 * time.Second, 2115 ProgressDeadline: 32 * time.Second, 2116 AutoRevert: false, 2117 AutoPromote: false, 2118 Canary: 1, 2119 }, 2120 }, 2121 Expected: &TaskGroupDiff{ 2122 Type: DiffTypeEdited, 2123 Objects: []*ObjectDiff{ 2124 { 2125 Type: DiffTypeEdited, 2126 Name: "Update", 2127 Fields: []*FieldDiff{ 2128 { 2129 Type: DiffTypeEdited, 2130 Name: "AutoPromote", 2131 Old: "true", 2132 New: "false", 2133 }, 2134 { 2135 Type: DiffTypeEdited, 2136 Name: "AutoRevert", 2137 Old: "true", 2138 New: "false", 2139 }, 2140 { 2141 Type: DiffTypeEdited, 2142 Name: "Canary", 2143 Old: "2", 2144 New: "1", 2145 }, 2146 { 2147 Type: DiffTypeEdited, 2148 Name: "HealthCheck", 2149 Old: "foo", 2150 New: "bar", 2151 }, 2152 { 2153 Type: DiffTypeEdited, 2154 Name: "HealthyDeadline", 2155 Old: "30000000000", 2156 New: "31000000000", 2157 }, 2158 { 2159 Type: DiffTypeEdited, 2160 Name: "MaxParallel", 2161 Old: "5", 2162 New: "7", 2163 }, 2164 { 2165 Type: DiffTypeEdited, 2166 Name: "MinHealthyTime", 2167 Old: "1000000000", 2168 New: "2000000000", 2169 }, 2170 { 2171 Type: DiffTypeEdited, 2172 Name: "ProgressDeadline", 2173 Old: "29000000000", 2174 New: "32000000000", 2175 }, 2176 }, 2177 }, 2178 }, 2179 }, 2180 }, 2181 { 2182 TestCase: "Update strategy edited with context", 2183 Contextual: true, 2184 Old: &TaskGroup{ 2185 Update: &UpdateStrategy{ 2186 MaxParallel: 5, 2187 HealthCheck: "foo", 2188 MinHealthyTime: 1 * time.Second, 2189 HealthyDeadline: 30 * time.Second, 2190 ProgressDeadline: 30 * time.Second, 2191 AutoRevert: true, 2192 AutoPromote: true, 2193 Canary: 2, 2194 }, 2195 }, 2196 New: &TaskGroup{ 2197 Update: &UpdateStrategy{ 2198 MaxParallel: 7, 2199 HealthCheck: "foo", 2200 MinHealthyTime: 1 * time.Second, 2201 HealthyDeadline: 30 * time.Second, 2202 ProgressDeadline: 30 * time.Second, 2203 AutoRevert: true, 2204 AutoPromote: true, 2205 Canary: 2, 2206 }, 2207 }, 2208 Expected: &TaskGroupDiff{ 2209 Type: DiffTypeEdited, 2210 Objects: []*ObjectDiff{ 2211 { 2212 Type: DiffTypeEdited, 2213 Name: "Update", 2214 Fields: []*FieldDiff{ 2215 { 2216 Type: DiffTypeNone, 2217 Name: "AutoPromote", 2218 Old: "true", 2219 New: "true", 2220 }, 2221 { 2222 Type: DiffTypeNone, 2223 Name: "AutoRevert", 2224 Old: "true", 2225 New: "true", 2226 }, 2227 { 2228 Type: DiffTypeNone, 2229 Name: "Canary", 2230 Old: "2", 2231 New: "2", 2232 }, 2233 { 2234 Type: DiffTypeNone, 2235 Name: "HealthCheck", 2236 Old: "foo", 2237 New: "foo", 2238 }, 2239 { 2240 Type: DiffTypeNone, 2241 Name: "HealthyDeadline", 2242 Old: "30000000000", 2243 New: "30000000000", 2244 }, 2245 { 2246 Type: DiffTypeEdited, 2247 Name: "MaxParallel", 2248 Old: "5", 2249 New: "7", 2250 }, 2251 { 2252 Type: DiffTypeNone, 2253 Name: "MinHealthyTime", 2254 Old: "1000000000", 2255 New: "1000000000", 2256 }, 2257 { 2258 Type: DiffTypeNone, 2259 Name: "ProgressDeadline", 2260 Old: "30000000000", 2261 New: "30000000000", 2262 }, 2263 }, 2264 }, 2265 }, 2266 }, 2267 }, 2268 { 2269 TestCase: "EphemeralDisk added", 2270 Old: &TaskGroup{}, 2271 New: &TaskGroup{ 2272 EphemeralDisk: &EphemeralDisk{ 2273 Migrate: true, 2274 Sticky: true, 2275 SizeMB: 100, 2276 }, 2277 }, 2278 Expected: &TaskGroupDiff{ 2279 Type: DiffTypeEdited, 2280 Objects: []*ObjectDiff{ 2281 { 2282 Type: DiffTypeAdded, 2283 Name: "EphemeralDisk", 2284 Fields: []*FieldDiff{ 2285 { 2286 Type: DiffTypeAdded, 2287 Name: "Migrate", 2288 Old: "", 2289 New: "true", 2290 }, 2291 { 2292 Type: DiffTypeAdded, 2293 Name: "SizeMB", 2294 Old: "", 2295 New: "100", 2296 }, 2297 { 2298 Type: DiffTypeAdded, 2299 Name: "Sticky", 2300 Old: "", 2301 New: "true", 2302 }, 2303 }, 2304 }, 2305 }, 2306 }, 2307 }, 2308 { 2309 TestCase: "EphemeralDisk deleted", 2310 Old: &TaskGroup{ 2311 EphemeralDisk: &EphemeralDisk{ 2312 Migrate: true, 2313 Sticky: true, 2314 SizeMB: 100, 2315 }, 2316 }, 2317 New: &TaskGroup{}, 2318 Expected: &TaskGroupDiff{ 2319 Type: DiffTypeEdited, 2320 Objects: []*ObjectDiff{ 2321 { 2322 Type: DiffTypeDeleted, 2323 Name: "EphemeralDisk", 2324 Fields: []*FieldDiff{ 2325 { 2326 Type: DiffTypeDeleted, 2327 Name: "Migrate", 2328 Old: "true", 2329 New: "", 2330 }, 2331 { 2332 Type: DiffTypeDeleted, 2333 Name: "SizeMB", 2334 Old: "100", 2335 New: "", 2336 }, 2337 { 2338 Type: DiffTypeDeleted, 2339 Name: "Sticky", 2340 Old: "true", 2341 New: "", 2342 }, 2343 }, 2344 }, 2345 }, 2346 }, 2347 }, 2348 { 2349 TestCase: "EphemeralDisk edited", 2350 Old: &TaskGroup{ 2351 EphemeralDisk: &EphemeralDisk{ 2352 Migrate: true, 2353 Sticky: true, 2354 SizeMB: 150, 2355 }, 2356 }, 2357 New: &TaskGroup{ 2358 EphemeralDisk: &EphemeralDisk{ 2359 Migrate: false, 2360 Sticky: false, 2361 SizeMB: 90, 2362 }, 2363 }, 2364 Expected: &TaskGroupDiff{ 2365 Type: DiffTypeEdited, 2366 Objects: []*ObjectDiff{ 2367 { 2368 Type: DiffTypeEdited, 2369 Name: "EphemeralDisk", 2370 Fields: []*FieldDiff{ 2371 { 2372 Type: DiffTypeEdited, 2373 Name: "Migrate", 2374 Old: "true", 2375 New: "false", 2376 }, 2377 { 2378 Type: DiffTypeEdited, 2379 Name: "SizeMB", 2380 Old: "150", 2381 New: "90", 2382 }, 2383 2384 { 2385 Type: DiffTypeEdited, 2386 Name: "Sticky", 2387 Old: "true", 2388 New: "false", 2389 }, 2390 }, 2391 }, 2392 }, 2393 }, 2394 }, 2395 { 2396 TestCase: "EphemeralDisk edited with context", 2397 Contextual: true, 2398 Old: &TaskGroup{ 2399 EphemeralDisk: &EphemeralDisk{ 2400 Migrate: false, 2401 Sticky: false, 2402 SizeMB: 100, 2403 }, 2404 }, 2405 New: &TaskGroup{ 2406 EphemeralDisk: &EphemeralDisk{ 2407 Migrate: true, 2408 Sticky: true, 2409 SizeMB: 90, 2410 }, 2411 }, 2412 Expected: &TaskGroupDiff{ 2413 Type: DiffTypeEdited, 2414 Objects: []*ObjectDiff{ 2415 { 2416 Type: DiffTypeEdited, 2417 Name: "EphemeralDisk", 2418 Fields: []*FieldDiff{ 2419 { 2420 Type: DiffTypeEdited, 2421 Name: "Migrate", 2422 Old: "false", 2423 New: "true", 2424 }, 2425 { 2426 Type: DiffTypeEdited, 2427 Name: "SizeMB", 2428 Old: "100", 2429 New: "90", 2430 }, 2431 { 2432 Type: DiffTypeEdited, 2433 Name: "Sticky", 2434 Old: "false", 2435 New: "true", 2436 }, 2437 }, 2438 }, 2439 }, 2440 }, 2441 }, 2442 { 2443 TestCase: "TaskGroup Services edited", 2444 Contextual: true, 2445 Old: &TaskGroup{ 2446 Services: []*Service{ 2447 { 2448 Name: "foo", 2449 EnableTagOverride: false, 2450 Checks: []*ServiceCheck{ 2451 { 2452 Name: "foo", 2453 Type: "http", 2454 Command: "foo", 2455 Args: []string{"foo"}, 2456 Path: "foo", 2457 Protocol: "http", 2458 Expose: true, 2459 Interval: 1 * time.Second, 2460 Timeout: 1 * time.Second, 2461 }, 2462 }, 2463 Connect: &ConsulConnect{ 2464 SidecarTask: &SidecarTask{ 2465 Name: "sidecar", 2466 Driver: "docker", 2467 Env: map[string]string{ 2468 "FOO": "BAR", 2469 }, 2470 Config: map[string]interface{}{ 2471 "foo": "baz", 2472 }, 2473 }, 2474 }, 2475 }, 2476 }, 2477 }, 2478 2479 New: &TaskGroup{ 2480 Services: []*Service{ 2481 { 2482 Name: "foo", 2483 EnableTagOverride: true, 2484 Checks: []*ServiceCheck{ 2485 { 2486 Name: "foo", 2487 Type: "tcp", 2488 Command: "bar", 2489 Path: "bar", 2490 Protocol: "tcp", 2491 Expose: false, 2492 Interval: 2 * time.Second, 2493 Timeout: 2 * time.Second, 2494 Header: map[string][]string{ 2495 "Foo": {"baz"}, 2496 }, 2497 }, 2498 }, 2499 Connect: &ConsulConnect{ 2500 SidecarService: &ConsulSidecarService{ 2501 Port: "http", 2502 Proxy: &ConsulProxy{ 2503 LocalServiceAddress: "127.0.0.1", 2504 LocalServicePort: 8080, 2505 Upstreams: []ConsulUpstream{ 2506 { 2507 DestinationName: "foo", 2508 LocalBindPort: 8000, 2509 }, 2510 }, 2511 Config: map[string]interface{}{ 2512 "foo": "qux", 2513 }, 2514 }, 2515 }, 2516 }, 2517 }, 2518 }, 2519 }, 2520 2521 Expected: &TaskGroupDiff{ 2522 Type: DiffTypeEdited, 2523 Objects: []*ObjectDiff{ 2524 { 2525 Type: DiffTypeEdited, 2526 Name: "Service", 2527 Fields: []*FieldDiff{ 2528 { 2529 Type: DiffTypeNone, 2530 Name: "AddressMode", 2531 Old: "", 2532 New: "", 2533 }, 2534 { 2535 Type: DiffTypeEdited, 2536 Name: "EnableTagOverride", 2537 Old: "false", 2538 New: "true", 2539 }, 2540 { 2541 Type: DiffTypeNone, 2542 Name: "Name", 2543 Old: "foo", 2544 New: "foo", 2545 }, 2546 { 2547 Type: DiffTypeNone, 2548 Name: "PortLabel", 2549 Old: "", 2550 New: "", 2551 }, 2552 }, 2553 Objects: []*ObjectDiff{ 2554 { 2555 Type: DiffTypeEdited, 2556 Name: "Check", 2557 Fields: []*FieldDiff{ 2558 { 2559 Type: DiffTypeNone, 2560 Name: "AddressMode", 2561 Old: "", 2562 New: "", 2563 }, 2564 { 2565 Type: DiffTypeEdited, 2566 Name: "Command", 2567 Old: "foo", 2568 New: "bar", 2569 }, 2570 { 2571 Type: DiffTypeEdited, 2572 Name: "Expose", 2573 Old: "true", 2574 New: "false", 2575 }, 2576 { 2577 Type: DiffTypeNone, 2578 Name: "GRPCService", 2579 Old: "", 2580 New: "", 2581 }, 2582 { 2583 Type: DiffTypeNone, 2584 Name: "GRPCUseTLS", 2585 Old: "false", 2586 New: "false", 2587 }, 2588 { 2589 Type: DiffTypeNone, 2590 Name: "InitialStatus", 2591 Old: "", 2592 New: "", 2593 }, 2594 { 2595 Type: DiffTypeEdited, 2596 Name: "Interval", 2597 Old: "1000000000", 2598 New: "2000000000", 2599 }, 2600 { 2601 Type: DiffTypeNone, 2602 Name: "Method", 2603 Old: "", 2604 New: "", 2605 }, 2606 { 2607 Type: DiffTypeNone, 2608 Name: "Name", 2609 Old: "foo", 2610 New: "foo", 2611 }, 2612 { 2613 Type: DiffTypeEdited, 2614 Name: "Path", 2615 Old: "foo", 2616 New: "bar", 2617 }, 2618 { 2619 Type: DiffTypeNone, 2620 Name: "PortLabel", 2621 Old: "", 2622 New: "", 2623 }, 2624 { 2625 Type: DiffTypeEdited, 2626 Name: "Protocol", 2627 Old: "http", 2628 New: "tcp", 2629 }, 2630 2631 { 2632 Type: DiffTypeNone, 2633 Name: "TLSSkipVerify", 2634 Old: "false", 2635 New: "false", 2636 }, 2637 { 2638 Type: DiffTypeNone, 2639 Name: "TaskName", 2640 Old: "", 2641 New: "", 2642 }, 2643 { 2644 Type: DiffTypeEdited, 2645 Name: "Timeout", 2646 Old: "1000000000", 2647 New: "2000000000", 2648 }, 2649 { 2650 Type: DiffTypeEdited, 2651 Name: "Type", 2652 Old: "http", 2653 New: "tcp", 2654 }, 2655 }, 2656 Objects: []*ObjectDiff{ 2657 { 2658 Type: DiffTypeAdded, 2659 Name: "Header", 2660 Fields: []*FieldDiff{ 2661 { 2662 Type: DiffTypeAdded, 2663 Name: "Foo[0]", 2664 Old: "", 2665 New: "baz", 2666 }, 2667 }, 2668 }, 2669 }, 2670 }, 2671 2672 { 2673 Type: DiffTypeEdited, 2674 Name: "ConsulConnect", 2675 Fields: []*FieldDiff{ 2676 { 2677 Type: DiffTypeNone, 2678 Name: "Native", 2679 Old: "false", 2680 New: "false", 2681 }, 2682 }, 2683 Objects: []*ObjectDiff{ 2684 2685 { 2686 Type: DiffTypeAdded, 2687 Name: "SidecarService", 2688 Fields: []*FieldDiff{ 2689 { 2690 Type: DiffTypeAdded, 2691 Name: "Port", 2692 Old: "", 2693 New: "http", 2694 }, 2695 }, 2696 Objects: []*ObjectDiff{ 2697 { 2698 Type: DiffTypeAdded, 2699 Name: "ConsulProxy", 2700 Fields: []*FieldDiff{ 2701 { 2702 Type: DiffTypeAdded, 2703 Name: "LocalServiceAddress", 2704 Old: "", 2705 New: "127.0.0.1", 2706 }, { 2707 Type: DiffTypeAdded, 2708 Name: "LocalServicePort", 2709 Old: "", 2710 New: "8080", 2711 }, 2712 }, 2713 Objects: []*ObjectDiff{ 2714 { 2715 Type: DiffTypeAdded, 2716 Name: "ConsulUpstreams", 2717 Fields: []*FieldDiff{ 2718 { 2719 Type: DiffTypeAdded, 2720 Name: "DestinationName", 2721 Old: "", 2722 New: "foo", 2723 }, 2724 { 2725 Type: DiffTypeAdded, 2726 Name: "LocalBindPort", 2727 Old: "", 2728 New: "8000", 2729 }, 2730 }, 2731 }, 2732 { 2733 Type: DiffTypeAdded, 2734 Name: "Config", 2735 Fields: []*FieldDiff{ 2736 { 2737 Type: DiffTypeAdded, 2738 Name: "foo", 2739 Old: "", 2740 New: "qux", 2741 }, 2742 }, 2743 }, 2744 }, 2745 }, 2746 }, 2747 }, 2748 2749 { 2750 Type: DiffTypeDeleted, 2751 Name: "SidecarTask", 2752 Fields: []*FieldDiff{ 2753 { 2754 Type: DiffTypeDeleted, 2755 Name: "Driver", 2756 Old: "docker", 2757 New: "", 2758 }, 2759 { 2760 Type: DiffTypeDeleted, 2761 Name: "Env[FOO]", 2762 Old: "BAR", 2763 New: "", 2764 }, 2765 { 2766 Type: DiffTypeDeleted, 2767 Name: "Name", 2768 Old: "sidecar", 2769 New: "", 2770 }, 2771 }, 2772 Objects: []*ObjectDiff{ 2773 { 2774 Type: DiffTypeDeleted, 2775 Name: "Config", 2776 Fields: []*FieldDiff{ 2777 { 2778 Type: DiffTypeDeleted, 2779 Name: "foo", 2780 Old: "baz", 2781 New: "", 2782 }, 2783 }, 2784 }, 2785 }, 2786 }, 2787 }, 2788 }, 2789 }, 2790 }, 2791 }, 2792 }, 2793 }, 2794 { 2795 TestCase: "TaskGroup Networks edited", 2796 Contextual: true, 2797 Old: &TaskGroup{ 2798 Networks: Networks{ 2799 { 2800 Device: "foo", 2801 CIDR: "foo", 2802 IP: "foo", 2803 MBits: 100, 2804 ReservedPorts: []Port{ 2805 { 2806 Label: "foo", 2807 Value: 80, 2808 }, 2809 }, 2810 }, 2811 }, 2812 }, 2813 New: &TaskGroup{ 2814 Networks: Networks{ 2815 { 2816 Device: "bar", 2817 CIDR: "bar", 2818 IP: "bar", 2819 MBits: 200, 2820 DynamicPorts: []Port{ 2821 { 2822 Label: "bar", 2823 To: 8081, 2824 }, 2825 }, 2826 }, 2827 }, 2828 }, 2829 Expected: &TaskGroupDiff{ 2830 Type: DiffTypeEdited, 2831 Objects: []*ObjectDiff{ 2832 { 2833 Type: DiffTypeAdded, 2834 Name: "Network", 2835 Fields: []*FieldDiff{ 2836 { 2837 Type: DiffTypeAdded, 2838 Name: "MBits", 2839 Old: "", 2840 New: "200", 2841 }, 2842 { 2843 Type: DiffTypeNone, 2844 Name: "Mode", 2845 Old: "", 2846 New: "", 2847 }, 2848 }, 2849 Objects: []*ObjectDiff{ 2850 { 2851 Type: DiffTypeAdded, 2852 Name: "Dynamic Port", 2853 Fields: []*FieldDiff{ 2854 { 2855 Type: DiffTypeAdded, 2856 Name: "Label", 2857 Old: "", 2858 New: "bar", 2859 }, 2860 { 2861 Type: DiffTypeAdded, 2862 Name: "To", 2863 Old: "", 2864 New: "8081", 2865 }, 2866 }, 2867 }, 2868 }, 2869 }, 2870 { 2871 Type: DiffTypeDeleted, 2872 Name: "Network", 2873 Fields: []*FieldDiff{ 2874 { 2875 Type: DiffTypeDeleted, 2876 Name: "MBits", 2877 Old: "100", 2878 New: "", 2879 }, 2880 { 2881 Type: DiffTypeNone, 2882 Name: "Mode", 2883 Old: "", 2884 New: "", 2885 }, 2886 }, 2887 Objects: []*ObjectDiff{ 2888 { 2889 Type: DiffTypeDeleted, 2890 Name: "Static Port", 2891 Fields: []*FieldDiff{ 2892 { 2893 Type: DiffTypeDeleted, 2894 Name: "Label", 2895 Old: "foo", 2896 New: "", 2897 }, 2898 { 2899 Type: DiffTypeDeleted, 2900 Name: "To", 2901 Old: "0", 2902 New: "", 2903 }, 2904 { 2905 Type: DiffTypeDeleted, 2906 Name: "Value", 2907 Old: "80", 2908 New: "", 2909 }, 2910 }, 2911 }, 2912 }, 2913 }, 2914 }, 2915 }, 2916 }, 2917 { 2918 TestCase: "Tasks edited", 2919 Old: &TaskGroup{ 2920 Tasks: []*Task{ 2921 { 2922 Name: "foo", 2923 Driver: "docker", 2924 }, 2925 { 2926 Name: "bar", 2927 Driver: "docker", 2928 }, 2929 { 2930 Name: "baz", 2931 ShutdownDelay: 1 * time.Second, 2932 }, 2933 }, 2934 }, 2935 New: &TaskGroup{ 2936 Tasks: []*Task{ 2937 { 2938 Name: "bar", 2939 Driver: "docker", 2940 }, 2941 { 2942 Name: "bam", 2943 Driver: "docker", 2944 }, 2945 { 2946 Name: "baz", 2947 ShutdownDelay: 2 * time.Second, 2948 }, 2949 }, 2950 }, 2951 Expected: &TaskGroupDiff{ 2952 Type: DiffTypeEdited, 2953 Tasks: []*TaskDiff{ 2954 { 2955 Type: DiffTypeAdded, 2956 Name: "bam", 2957 Fields: []*FieldDiff{ 2958 { 2959 Type: DiffTypeAdded, 2960 Name: "Driver", 2961 Old: "", 2962 New: "docker", 2963 }, 2964 { 2965 Type: DiffTypeAdded, 2966 Name: "KillTimeout", 2967 Old: "", 2968 New: "0", 2969 }, 2970 { 2971 Type: DiffTypeAdded, 2972 Name: "Leader", 2973 Old: "", 2974 New: "false", 2975 }, 2976 { 2977 Type: DiffTypeAdded, 2978 Name: "ShutdownDelay", 2979 Old: "", 2980 New: "0", 2981 }, 2982 }, 2983 }, 2984 { 2985 Type: DiffTypeNone, 2986 Name: "bar", 2987 }, 2988 { 2989 Type: DiffTypeEdited, 2990 Name: "baz", 2991 Fields: []*FieldDiff{ 2992 { 2993 Type: DiffTypeEdited, 2994 Name: "ShutdownDelay", 2995 Old: "1000000000", 2996 New: "2000000000", 2997 }, 2998 }, 2999 }, 3000 { 3001 Type: DiffTypeDeleted, 3002 Name: "foo", 3003 Fields: []*FieldDiff{ 3004 { 3005 Type: DiffTypeDeleted, 3006 Name: "Driver", 3007 Old: "docker", 3008 New: "", 3009 }, 3010 { 3011 Type: DiffTypeDeleted, 3012 Name: "KillTimeout", 3013 Old: "0", 3014 New: "", 3015 }, 3016 { 3017 Type: DiffTypeDeleted, 3018 Name: "Leader", 3019 Old: "false", 3020 New: "", 3021 }, 3022 { 3023 Type: DiffTypeDeleted, 3024 Name: "ShutdownDelay", 3025 Old: "0", 3026 New: "", 3027 }, 3028 }, 3029 }, 3030 }, 3031 }, 3032 }, 3033 { 3034 TestCase: "TaskGroup shutdown_delay edited", 3035 Old: &TaskGroup{ 3036 ShutdownDelay: helper.TimeToPtr(30 * time.Second), 3037 }, 3038 New: &TaskGroup{ 3039 ShutdownDelay: helper.TimeToPtr(5 * time.Second), 3040 }, 3041 Expected: &TaskGroupDiff{ 3042 Type: DiffTypeEdited, 3043 Fields: []*FieldDiff{ 3044 { 3045 Type: DiffTypeEdited, 3046 Name: "ShutdownDelay", 3047 Old: "30000000000", 3048 New: "5000000000", 3049 }, 3050 }, 3051 }, 3052 }, 3053 { 3054 TestCase: "TaskGroup shutdown_delay removed", 3055 Old: &TaskGroup{ 3056 ShutdownDelay: helper.TimeToPtr(30 * time.Second), 3057 }, 3058 New: &TaskGroup{}, 3059 Expected: &TaskGroupDiff{ 3060 Type: DiffTypeEdited, 3061 Fields: []*FieldDiff{ 3062 { 3063 Type: DiffTypeDeleted, 3064 Name: "ShutdownDelay", 3065 Old: "30000000000", 3066 New: "", 3067 }, 3068 }, 3069 }, 3070 }, 3071 { 3072 TestCase: "TaskGroup shutdown_delay added", 3073 Old: &TaskGroup{}, 3074 New: &TaskGroup{ 3075 ShutdownDelay: helper.TimeToPtr(30 * time.Second), 3076 }, 3077 Expected: &TaskGroupDiff{ 3078 Type: DiffTypeEdited, 3079 Fields: []*FieldDiff{ 3080 { 3081 Type: DiffTypeAdded, 3082 Name: "ShutdownDelay", 3083 Old: "", 3084 New: "30000000000", 3085 }, 3086 }, 3087 }, 3088 }, 3089 } 3090 3091 for i, c := range cases { 3092 require.NotEmpty(t, c.TestCase, "case #%d needs a name", i+1) 3093 3094 t.Run(c.TestCase, func(t *testing.T) { 3095 result, err := c.Old.Diff(c.New, c.Contextual) 3096 switch c.ExpErr { 3097 case true: 3098 require.Error(t, err, "case %q expected error", c.TestCase) 3099 case false: 3100 require.NoError(t, err, "case %q expected no error", c.TestCase) 3101 require.True(t, reflect.DeepEqual(result, c.Expected), 3102 "case %q got\n%#v\nwant:\n%#v\n", c.TestCase, result, c.Expected) 3103 } 3104 }) 3105 } 3106 } 3107 3108 func TestTaskDiff(t *testing.T) { 3109 cases := []struct { 3110 Name string 3111 Old, New *Task 3112 Expected *TaskDiff 3113 Error bool 3114 Contextual bool 3115 }{ 3116 { 3117 Name: "Empty", 3118 Old: nil, 3119 New: nil, 3120 Expected: &TaskDiff{ 3121 Type: DiffTypeNone, 3122 }, 3123 }, 3124 { 3125 Name: "Primitive only that has different names", 3126 Old: &Task{ 3127 Name: "foo", 3128 Meta: map[string]string{ 3129 "foo": "bar", 3130 }, 3131 }, 3132 New: &Task{ 3133 Name: "bar", 3134 Meta: map[string]string{ 3135 "foo": "bar", 3136 }, 3137 }, 3138 Error: true, 3139 }, 3140 { 3141 Name: "Primitive only that is the same", 3142 Old: &Task{ 3143 Name: "foo", 3144 Driver: "exec", 3145 User: "foo", 3146 Env: map[string]string{ 3147 "FOO": "bar", 3148 }, 3149 Meta: map[string]string{ 3150 "foo": "bar", 3151 }, 3152 KillTimeout: 1 * time.Second, 3153 Leader: true, 3154 }, 3155 New: &Task{ 3156 Name: "foo", 3157 Driver: "exec", 3158 User: "foo", 3159 Env: map[string]string{ 3160 "FOO": "bar", 3161 }, 3162 Meta: map[string]string{ 3163 "foo": "bar", 3164 }, 3165 KillTimeout: 1 * time.Second, 3166 Leader: true, 3167 }, 3168 Expected: &TaskDiff{ 3169 Type: DiffTypeNone, 3170 Name: "foo", 3171 }, 3172 }, 3173 { 3174 Name: "Primitive only that has diffs", 3175 Old: &Task{ 3176 Name: "foo", 3177 Driver: "exec", 3178 User: "foo", 3179 Env: map[string]string{ 3180 "FOO": "bar", 3181 }, 3182 Meta: map[string]string{ 3183 "foo": "bar", 3184 }, 3185 KillTimeout: 1 * time.Second, 3186 Leader: true, 3187 }, 3188 New: &Task{ 3189 Name: "foo", 3190 Driver: "docker", 3191 User: "bar", 3192 Env: map[string]string{ 3193 "FOO": "baz", 3194 }, 3195 Meta: map[string]string{ 3196 "foo": "baz", 3197 }, 3198 KillTimeout: 2 * time.Second, 3199 Leader: false, 3200 }, 3201 Expected: &TaskDiff{ 3202 Type: DiffTypeEdited, 3203 Name: "foo", 3204 Fields: []*FieldDiff{ 3205 { 3206 Type: DiffTypeEdited, 3207 Name: "Driver", 3208 Old: "exec", 3209 New: "docker", 3210 }, 3211 { 3212 Type: DiffTypeEdited, 3213 Name: "Env[FOO]", 3214 Old: "bar", 3215 New: "baz", 3216 }, 3217 { 3218 Type: DiffTypeEdited, 3219 Name: "KillTimeout", 3220 Old: "1000000000", 3221 New: "2000000000", 3222 }, 3223 { 3224 Type: DiffTypeEdited, 3225 Name: "Leader", 3226 Old: "true", 3227 New: "false", 3228 }, 3229 { 3230 Type: DiffTypeEdited, 3231 Name: "Meta[foo]", 3232 Old: "bar", 3233 New: "baz", 3234 }, 3235 { 3236 Type: DiffTypeEdited, 3237 Name: "User", 3238 Old: "foo", 3239 New: "bar", 3240 }, 3241 }, 3242 }, 3243 }, 3244 { 3245 Name: "Map diff", 3246 Old: &Task{ 3247 Meta: map[string]string{ 3248 "foo": "foo", 3249 "bar": "bar", 3250 }, 3251 Env: map[string]string{ 3252 "foo": "foo", 3253 "bar": "bar", 3254 }, 3255 }, 3256 New: &Task{ 3257 Meta: map[string]string{ 3258 "bar": "bar", 3259 "baz": "baz", 3260 }, 3261 Env: map[string]string{ 3262 "bar": "bar", 3263 "baz": "baz", 3264 }, 3265 }, 3266 Expected: &TaskDiff{ 3267 Type: DiffTypeEdited, 3268 Fields: []*FieldDiff{ 3269 { 3270 Type: DiffTypeAdded, 3271 Name: "Env[baz]", 3272 Old: "", 3273 New: "baz", 3274 }, 3275 { 3276 Type: DiffTypeDeleted, 3277 Name: "Env[foo]", 3278 Old: "foo", 3279 New: "", 3280 }, 3281 { 3282 Type: DiffTypeAdded, 3283 Name: "Meta[baz]", 3284 Old: "", 3285 New: "baz", 3286 }, 3287 { 3288 Type: DiffTypeDeleted, 3289 Name: "Meta[foo]", 3290 Old: "foo", 3291 New: "", 3292 }, 3293 }, 3294 }, 3295 }, 3296 { 3297 Name: "Constraints edited", 3298 Old: &Task{ 3299 Constraints: []*Constraint{ 3300 { 3301 LTarget: "foo", 3302 RTarget: "foo", 3303 Operand: "foo", 3304 str: "foo", 3305 }, 3306 { 3307 LTarget: "bar", 3308 RTarget: "bar", 3309 Operand: "bar", 3310 str: "bar", 3311 }, 3312 }, 3313 }, 3314 New: &Task{ 3315 Constraints: []*Constraint{ 3316 { 3317 LTarget: "foo", 3318 RTarget: "foo", 3319 Operand: "foo", 3320 str: "foo", 3321 }, 3322 { 3323 LTarget: "baz", 3324 RTarget: "baz", 3325 Operand: "baz", 3326 str: "baz", 3327 }, 3328 }, 3329 }, 3330 Expected: &TaskDiff{ 3331 Type: DiffTypeEdited, 3332 Objects: []*ObjectDiff{ 3333 { 3334 Type: DiffTypeAdded, 3335 Name: "Constraint", 3336 Fields: []*FieldDiff{ 3337 { 3338 Type: DiffTypeAdded, 3339 Name: "LTarget", 3340 Old: "", 3341 New: "baz", 3342 }, 3343 { 3344 Type: DiffTypeAdded, 3345 Name: "Operand", 3346 Old: "", 3347 New: "baz", 3348 }, 3349 { 3350 Type: DiffTypeAdded, 3351 Name: "RTarget", 3352 Old: "", 3353 New: "baz", 3354 }, 3355 }, 3356 }, 3357 { 3358 Type: DiffTypeDeleted, 3359 Name: "Constraint", 3360 Fields: []*FieldDiff{ 3361 { 3362 Type: DiffTypeDeleted, 3363 Name: "LTarget", 3364 Old: "bar", 3365 New: "", 3366 }, 3367 { 3368 Type: DiffTypeDeleted, 3369 Name: "Operand", 3370 Old: "bar", 3371 New: "", 3372 }, 3373 { 3374 Type: DiffTypeDeleted, 3375 Name: "RTarget", 3376 Old: "bar", 3377 New: "", 3378 }, 3379 }, 3380 }, 3381 }, 3382 }, 3383 }, 3384 { 3385 Name: "Affinities edited", 3386 Old: &Task{ 3387 Affinities: []*Affinity{ 3388 { 3389 LTarget: "foo", 3390 RTarget: "foo", 3391 Operand: "foo", 3392 Weight: 20, 3393 str: "foo", 3394 }, 3395 { 3396 LTarget: "bar", 3397 RTarget: "bar", 3398 Operand: "bar", 3399 Weight: 20, 3400 str: "bar", 3401 }, 3402 }, 3403 }, 3404 New: &Task{ 3405 Affinities: []*Affinity{ 3406 { 3407 LTarget: "foo", 3408 RTarget: "foo", 3409 Operand: "foo", 3410 Weight: 20, 3411 str: "foo", 3412 }, 3413 { 3414 LTarget: "baz", 3415 RTarget: "baz", 3416 Operand: "baz", 3417 Weight: 20, 3418 str: "baz", 3419 }, 3420 }, 3421 }, 3422 Expected: &TaskDiff{ 3423 Type: DiffTypeEdited, 3424 Objects: []*ObjectDiff{ 3425 { 3426 Type: DiffTypeAdded, 3427 Name: "Affinity", 3428 Fields: []*FieldDiff{ 3429 { 3430 Type: DiffTypeAdded, 3431 Name: "LTarget", 3432 Old: "", 3433 New: "baz", 3434 }, 3435 { 3436 Type: DiffTypeAdded, 3437 Name: "Operand", 3438 Old: "", 3439 New: "baz", 3440 }, 3441 { 3442 Type: DiffTypeAdded, 3443 Name: "RTarget", 3444 Old: "", 3445 New: "baz", 3446 }, 3447 { 3448 Type: DiffTypeAdded, 3449 Name: "Weight", 3450 Old: "", 3451 New: "20", 3452 }, 3453 }, 3454 }, 3455 { 3456 Type: DiffTypeDeleted, 3457 Name: "Affinity", 3458 Fields: []*FieldDiff{ 3459 { 3460 Type: DiffTypeDeleted, 3461 Name: "LTarget", 3462 Old: "bar", 3463 New: "", 3464 }, 3465 { 3466 Type: DiffTypeDeleted, 3467 Name: "Operand", 3468 Old: "bar", 3469 New: "", 3470 }, 3471 { 3472 Type: DiffTypeDeleted, 3473 Name: "RTarget", 3474 Old: "bar", 3475 New: "", 3476 }, 3477 { 3478 Type: DiffTypeDeleted, 3479 Name: "Weight", 3480 Old: "20", 3481 New: "", 3482 }, 3483 }, 3484 }, 3485 }, 3486 }, 3487 }, 3488 { 3489 Name: "LogConfig added", 3490 Old: &Task{}, 3491 New: &Task{ 3492 LogConfig: &LogConfig{ 3493 MaxFiles: 1, 3494 MaxFileSizeMB: 10, 3495 }, 3496 }, 3497 Expected: &TaskDiff{ 3498 Type: DiffTypeEdited, 3499 Objects: []*ObjectDiff{ 3500 { 3501 Type: DiffTypeAdded, 3502 Name: "LogConfig", 3503 Fields: []*FieldDiff{ 3504 { 3505 Type: DiffTypeAdded, 3506 Name: "MaxFileSizeMB", 3507 Old: "", 3508 New: "10", 3509 }, 3510 { 3511 Type: DiffTypeAdded, 3512 Name: "MaxFiles", 3513 Old: "", 3514 New: "1", 3515 }, 3516 }, 3517 }, 3518 }, 3519 }, 3520 }, 3521 { 3522 Name: "LogConfig deleted", 3523 Old: &Task{ 3524 LogConfig: &LogConfig{ 3525 MaxFiles: 1, 3526 MaxFileSizeMB: 10, 3527 }, 3528 }, 3529 New: &Task{}, 3530 Expected: &TaskDiff{ 3531 Type: DiffTypeEdited, 3532 Objects: []*ObjectDiff{ 3533 { 3534 Type: DiffTypeDeleted, 3535 Name: "LogConfig", 3536 Fields: []*FieldDiff{ 3537 { 3538 Type: DiffTypeDeleted, 3539 Name: "MaxFileSizeMB", 3540 Old: "10", 3541 New: "", 3542 }, 3543 { 3544 Type: DiffTypeDeleted, 3545 Name: "MaxFiles", 3546 Old: "1", 3547 New: "", 3548 }, 3549 }, 3550 }, 3551 }, 3552 }, 3553 }, 3554 { 3555 Name: "LogConfig edited", 3556 Old: &Task{ 3557 LogConfig: &LogConfig{ 3558 MaxFiles: 1, 3559 MaxFileSizeMB: 10, 3560 }, 3561 }, 3562 New: &Task{ 3563 LogConfig: &LogConfig{ 3564 MaxFiles: 2, 3565 MaxFileSizeMB: 20, 3566 }, 3567 }, 3568 Expected: &TaskDiff{ 3569 Type: DiffTypeEdited, 3570 Objects: []*ObjectDiff{ 3571 { 3572 Type: DiffTypeEdited, 3573 Name: "LogConfig", 3574 Fields: []*FieldDiff{ 3575 { 3576 Type: DiffTypeEdited, 3577 Name: "MaxFileSizeMB", 3578 Old: "10", 3579 New: "20", 3580 }, 3581 { 3582 Type: DiffTypeEdited, 3583 Name: "MaxFiles", 3584 Old: "1", 3585 New: "2", 3586 }, 3587 }, 3588 }, 3589 }, 3590 }, 3591 }, 3592 { 3593 Name: "LogConfig edited with context", 3594 Contextual: true, 3595 Old: &Task{ 3596 LogConfig: &LogConfig{ 3597 MaxFiles: 1, 3598 MaxFileSizeMB: 10, 3599 }, 3600 }, 3601 New: &Task{ 3602 LogConfig: &LogConfig{ 3603 MaxFiles: 1, 3604 MaxFileSizeMB: 20, 3605 }, 3606 }, 3607 Expected: &TaskDiff{ 3608 Type: DiffTypeEdited, 3609 Objects: []*ObjectDiff{ 3610 { 3611 Type: DiffTypeEdited, 3612 Name: "LogConfig", 3613 Fields: []*FieldDiff{ 3614 { 3615 Type: DiffTypeEdited, 3616 Name: "MaxFileSizeMB", 3617 Old: "10", 3618 New: "20", 3619 }, 3620 { 3621 Type: DiffTypeNone, 3622 Name: "MaxFiles", 3623 Old: "1", 3624 New: "1", 3625 }, 3626 }, 3627 }, 3628 }, 3629 }, 3630 }, 3631 { 3632 Name: "Artifacts edited", 3633 Old: &Task{ 3634 Artifacts: []*TaskArtifact{ 3635 { 3636 GetterSource: "foo", 3637 GetterOptions: map[string]string{ 3638 "foo": "bar", 3639 }, 3640 RelativeDest: "foo", 3641 }, 3642 { 3643 GetterSource: "bar", 3644 GetterOptions: map[string]string{ 3645 "bar": "baz", 3646 }, 3647 GetterMode: "dir", 3648 RelativeDest: "bar", 3649 }, 3650 }, 3651 }, 3652 New: &Task{ 3653 Artifacts: []*TaskArtifact{ 3654 { 3655 GetterSource: "foo", 3656 GetterOptions: map[string]string{ 3657 "foo": "bar", 3658 }, 3659 RelativeDest: "foo", 3660 }, 3661 { 3662 GetterSource: "bam", 3663 GetterOptions: map[string]string{ 3664 "bam": "baz", 3665 }, 3666 GetterMode: "file", 3667 RelativeDest: "bam", 3668 }, 3669 }, 3670 }, 3671 Expected: &TaskDiff{ 3672 Type: DiffTypeEdited, 3673 Objects: []*ObjectDiff{ 3674 { 3675 Type: DiffTypeAdded, 3676 Name: "Artifact", 3677 Fields: []*FieldDiff{ 3678 { 3679 Type: DiffTypeAdded, 3680 Name: "GetterMode", 3681 Old: "", 3682 New: "file", 3683 }, 3684 { 3685 Type: DiffTypeAdded, 3686 Name: "GetterOptions[bam]", 3687 Old: "", 3688 New: "baz", 3689 }, 3690 { 3691 Type: DiffTypeAdded, 3692 Name: "GetterSource", 3693 Old: "", 3694 New: "bam", 3695 }, 3696 { 3697 Type: DiffTypeAdded, 3698 Name: "RelativeDest", 3699 Old: "", 3700 New: "bam", 3701 }, 3702 }, 3703 }, 3704 { 3705 Type: DiffTypeDeleted, 3706 Name: "Artifact", 3707 Fields: []*FieldDiff{ 3708 { 3709 Type: DiffTypeDeleted, 3710 Name: "GetterMode", 3711 Old: "dir", 3712 New: "", 3713 }, 3714 { 3715 Type: DiffTypeDeleted, 3716 Name: "GetterOptions[bar]", 3717 Old: "baz", 3718 New: "", 3719 }, 3720 { 3721 Type: DiffTypeDeleted, 3722 Name: "GetterSource", 3723 Old: "bar", 3724 New: "", 3725 }, 3726 { 3727 Type: DiffTypeDeleted, 3728 Name: "RelativeDest", 3729 Old: "bar", 3730 New: "", 3731 }, 3732 }, 3733 }, 3734 }, 3735 }, 3736 }, 3737 { 3738 Name: "Resources edited (no networks)", 3739 Old: &Task{ 3740 Resources: &Resources{ 3741 CPU: 100, 3742 MemoryMB: 100, 3743 DiskMB: 100, 3744 }, 3745 }, 3746 New: &Task{ 3747 Resources: &Resources{ 3748 CPU: 200, 3749 MemoryMB: 200, 3750 DiskMB: 200, 3751 }, 3752 }, 3753 Expected: &TaskDiff{ 3754 Type: DiffTypeEdited, 3755 Objects: []*ObjectDiff{ 3756 { 3757 Type: DiffTypeEdited, 3758 Name: "Resources", 3759 Fields: []*FieldDiff{ 3760 { 3761 Type: DiffTypeEdited, 3762 Name: "CPU", 3763 Old: "100", 3764 New: "200", 3765 }, 3766 { 3767 Type: DiffTypeEdited, 3768 Name: "DiskMB", 3769 Old: "100", 3770 New: "200", 3771 }, 3772 { 3773 Type: DiffTypeEdited, 3774 Name: "MemoryMB", 3775 Old: "100", 3776 New: "200", 3777 }, 3778 }, 3779 }, 3780 }, 3781 }, 3782 }, 3783 { 3784 Name: "Resources edited (no networks) with context", 3785 Contextual: true, 3786 Old: &Task{ 3787 Resources: &Resources{ 3788 CPU: 100, 3789 MemoryMB: 100, 3790 DiskMB: 100, 3791 }, 3792 }, 3793 New: &Task{ 3794 Resources: &Resources{ 3795 CPU: 200, 3796 MemoryMB: 100, 3797 DiskMB: 200, 3798 }, 3799 }, 3800 Expected: &TaskDiff{ 3801 Type: DiffTypeEdited, 3802 Objects: []*ObjectDiff{ 3803 { 3804 Type: DiffTypeEdited, 3805 Name: "Resources", 3806 Fields: []*FieldDiff{ 3807 { 3808 Type: DiffTypeEdited, 3809 Name: "CPU", 3810 Old: "100", 3811 New: "200", 3812 }, 3813 { 3814 Type: DiffTypeEdited, 3815 Name: "DiskMB", 3816 Old: "100", 3817 New: "200", 3818 }, 3819 { 3820 Type: DiffTypeNone, 3821 Name: "IOPS", 3822 Old: "0", 3823 New: "0", 3824 }, 3825 { 3826 Type: DiffTypeNone, 3827 Name: "MemoryMB", 3828 Old: "100", 3829 New: "100", 3830 }, 3831 }, 3832 }, 3833 }, 3834 }, 3835 }, 3836 { 3837 Name: "Network Resources edited", 3838 Old: &Task{ 3839 Resources: &Resources{ 3840 Networks: []*NetworkResource{ 3841 { 3842 Device: "foo", 3843 CIDR: "foo", 3844 IP: "foo", 3845 MBits: 100, 3846 ReservedPorts: []Port{ 3847 { 3848 Label: "foo", 3849 Value: 80, 3850 }, 3851 }, 3852 DynamicPorts: []Port{ 3853 { 3854 Label: "bar", 3855 To: 8080, 3856 }, 3857 }, 3858 }, 3859 }, 3860 }, 3861 }, 3862 New: &Task{ 3863 Resources: &Resources{ 3864 Networks: []*NetworkResource{ 3865 { 3866 Device: "bar", 3867 CIDR: "bar", 3868 IP: "bar", 3869 MBits: 200, 3870 ReservedPorts: []Port{ 3871 { 3872 Label: "foo", 3873 Value: 81, 3874 }, 3875 }, 3876 DynamicPorts: []Port{ 3877 { 3878 Label: "baz", 3879 To: 8081, 3880 }, 3881 }, 3882 }, 3883 }, 3884 }, 3885 }, 3886 Expected: &TaskDiff{ 3887 Type: DiffTypeEdited, 3888 Objects: []*ObjectDiff{ 3889 { 3890 Type: DiffTypeEdited, 3891 Name: "Resources", 3892 Objects: []*ObjectDiff{ 3893 { 3894 Type: DiffTypeAdded, 3895 Name: "Network", 3896 Fields: []*FieldDiff{ 3897 { 3898 Type: DiffTypeAdded, 3899 Name: "MBits", 3900 Old: "", 3901 New: "200", 3902 }, 3903 }, 3904 Objects: []*ObjectDiff{ 3905 { 3906 Type: DiffTypeAdded, 3907 Name: "Static Port", 3908 Fields: []*FieldDiff{ 3909 { 3910 Type: DiffTypeAdded, 3911 Name: "Label", 3912 Old: "", 3913 New: "foo", 3914 }, 3915 { 3916 Type: DiffTypeAdded, 3917 Name: "To", 3918 Old: "", 3919 New: "0", 3920 }, 3921 { 3922 Type: DiffTypeAdded, 3923 Name: "Value", 3924 Old: "", 3925 New: "81", 3926 }, 3927 }, 3928 }, 3929 { 3930 Type: DiffTypeAdded, 3931 Name: "Dynamic Port", 3932 Fields: []*FieldDiff{ 3933 { 3934 Type: DiffTypeAdded, 3935 Name: "Label", 3936 Old: "", 3937 New: "baz", 3938 }, 3939 { 3940 Type: DiffTypeAdded, 3941 Name: "To", 3942 Old: "", 3943 New: "8081", 3944 }, 3945 }, 3946 }, 3947 }, 3948 }, 3949 { 3950 Type: DiffTypeDeleted, 3951 Name: "Network", 3952 Fields: []*FieldDiff{ 3953 { 3954 Type: DiffTypeDeleted, 3955 Name: "MBits", 3956 Old: "100", 3957 New: "", 3958 }, 3959 }, 3960 Objects: []*ObjectDiff{ 3961 { 3962 Type: DiffTypeDeleted, 3963 Name: "Static Port", 3964 Fields: []*FieldDiff{ 3965 { 3966 Type: DiffTypeDeleted, 3967 Name: "Label", 3968 Old: "foo", 3969 New: "", 3970 }, 3971 { 3972 Type: DiffTypeDeleted, 3973 Name: "To", 3974 Old: "0", 3975 New: "", 3976 }, 3977 { 3978 Type: DiffTypeDeleted, 3979 Name: "Value", 3980 Old: "80", 3981 New: "", 3982 }, 3983 }, 3984 }, 3985 { 3986 Type: DiffTypeDeleted, 3987 Name: "Dynamic Port", 3988 Fields: []*FieldDiff{ 3989 { 3990 Type: DiffTypeDeleted, 3991 Name: "Label", 3992 Old: "bar", 3993 New: "", 3994 }, 3995 { 3996 Type: DiffTypeDeleted, 3997 Name: "To", 3998 Old: "8080", 3999 New: "", 4000 }, 4001 }, 4002 }, 4003 }, 4004 }, 4005 }, 4006 }, 4007 }, 4008 }, 4009 }, 4010 { 4011 Name: "Device Resources edited", 4012 Old: &Task{ 4013 Resources: &Resources{ 4014 Devices: []*RequestedDevice{ 4015 { 4016 Name: "foo", 4017 Count: 2, 4018 }, 4019 { 4020 Name: "bar", 4021 Count: 2, 4022 }, 4023 { 4024 Name: "baz", 4025 Count: 2, 4026 }, 4027 }, 4028 }, 4029 }, 4030 New: &Task{ 4031 Resources: &Resources{ 4032 Devices: []*RequestedDevice{ 4033 { 4034 Name: "foo", 4035 Count: 2, 4036 }, 4037 { 4038 Name: "bar", 4039 Count: 3, 4040 }, 4041 { 4042 Name: "bam", 4043 Count: 2, 4044 }, 4045 }, 4046 }, 4047 }, 4048 Expected: &TaskDiff{ 4049 Type: DiffTypeEdited, 4050 Objects: []*ObjectDiff{ 4051 { 4052 Type: DiffTypeEdited, 4053 Name: "Resources", 4054 Objects: []*ObjectDiff{ 4055 { 4056 Type: DiffTypeEdited, 4057 Name: "Device", 4058 Fields: []*FieldDiff{ 4059 { 4060 Type: DiffTypeEdited, 4061 Name: "Count", 4062 Old: "2", 4063 New: "3", 4064 }, 4065 }, 4066 }, 4067 { 4068 Type: DiffTypeAdded, 4069 Name: "Device", 4070 Fields: []*FieldDiff{ 4071 { 4072 Type: DiffTypeAdded, 4073 Name: "Count", 4074 Old: "", 4075 New: "2", 4076 }, 4077 { 4078 Type: DiffTypeAdded, 4079 Name: "Name", 4080 Old: "", 4081 New: "bam", 4082 }, 4083 }, 4084 }, 4085 { 4086 Type: DiffTypeDeleted, 4087 Name: "Device", 4088 Fields: []*FieldDiff{ 4089 { 4090 Type: DiffTypeDeleted, 4091 Name: "Count", 4092 Old: "2", 4093 New: "", 4094 }, 4095 { 4096 Type: DiffTypeDeleted, 4097 Name: "Name", 4098 Old: "baz", 4099 New: "", 4100 }, 4101 }, 4102 }, 4103 }, 4104 }, 4105 }, 4106 }, 4107 }, 4108 { 4109 Name: "Device Resources edited with context", 4110 Contextual: true, 4111 Old: &Task{ 4112 Resources: &Resources{ 4113 CPU: 100, 4114 MemoryMB: 100, 4115 DiskMB: 100, 4116 Devices: []*RequestedDevice{ 4117 { 4118 Name: "foo", 4119 Count: 2, 4120 }, 4121 { 4122 Name: "bar", 4123 Count: 2, 4124 }, 4125 { 4126 Name: "baz", 4127 Count: 2, 4128 }, 4129 }, 4130 }, 4131 }, 4132 New: &Task{ 4133 Resources: &Resources{ 4134 CPU: 100, 4135 MemoryMB: 100, 4136 DiskMB: 100, 4137 Devices: []*RequestedDevice{ 4138 { 4139 Name: "foo", 4140 Count: 2, 4141 }, 4142 { 4143 Name: "bar", 4144 Count: 3, 4145 }, 4146 { 4147 Name: "bam", 4148 Count: 2, 4149 }, 4150 }, 4151 }, 4152 }, 4153 Expected: &TaskDiff{ 4154 Type: DiffTypeEdited, 4155 Objects: []*ObjectDiff{ 4156 { 4157 Type: DiffTypeEdited, 4158 Name: "Resources", 4159 Fields: []*FieldDiff{ 4160 { 4161 Type: DiffTypeNone, 4162 Name: "CPU", 4163 Old: "100", 4164 New: "100", 4165 }, 4166 { 4167 Type: DiffTypeNone, 4168 Name: "DiskMB", 4169 Old: "100", 4170 New: "100", 4171 }, 4172 { 4173 Type: DiffTypeNone, 4174 Name: "IOPS", 4175 Old: "0", 4176 New: "0", 4177 }, 4178 { 4179 Type: DiffTypeNone, 4180 Name: "MemoryMB", 4181 Old: "100", 4182 New: "100", 4183 }, 4184 }, 4185 Objects: []*ObjectDiff{ 4186 { 4187 Type: DiffTypeEdited, 4188 Name: "Device", 4189 Fields: []*FieldDiff{ 4190 { 4191 Type: DiffTypeEdited, 4192 Name: "Count", 4193 Old: "2", 4194 New: "3", 4195 }, 4196 { 4197 Type: DiffTypeNone, 4198 Name: "Name", 4199 Old: "bar", 4200 New: "bar", 4201 }, 4202 }, 4203 }, 4204 { 4205 Type: DiffTypeAdded, 4206 Name: "Device", 4207 Fields: []*FieldDiff{ 4208 { 4209 Type: DiffTypeAdded, 4210 Name: "Count", 4211 Old: "", 4212 New: "2", 4213 }, 4214 { 4215 Type: DiffTypeAdded, 4216 Name: "Name", 4217 Old: "", 4218 New: "bam", 4219 }, 4220 }, 4221 }, 4222 { 4223 Type: DiffTypeDeleted, 4224 Name: "Device", 4225 Fields: []*FieldDiff{ 4226 { 4227 Type: DiffTypeDeleted, 4228 Name: "Count", 4229 Old: "2", 4230 New: "", 4231 }, 4232 { 4233 Type: DiffTypeDeleted, 4234 Name: "Name", 4235 Old: "baz", 4236 New: "", 4237 }, 4238 }, 4239 }, 4240 }, 4241 }, 4242 }, 4243 }, 4244 }, 4245 { 4246 Name: "Config same", 4247 Old: &Task{ 4248 Config: map[string]interface{}{ 4249 "foo": 1, 4250 "bar": "bar", 4251 "bam": []string{"a", "b"}, 4252 "baz": map[string]int{ 4253 "a": 1, 4254 "b": 2, 4255 }, 4256 "boom": &Port{ 4257 Label: "boom_port", 4258 }, 4259 }, 4260 }, 4261 New: &Task{ 4262 Config: map[string]interface{}{ 4263 "foo": 1, 4264 "bar": "bar", 4265 "bam": []string{"a", "b"}, 4266 "baz": map[string]int{ 4267 "a": 1, 4268 "b": 2, 4269 }, 4270 "boom": &Port{ 4271 Label: "boom_port", 4272 }, 4273 }, 4274 }, 4275 Expected: &TaskDiff{ 4276 Type: DiffTypeNone, 4277 }, 4278 }, 4279 { 4280 Name: "Config edited", 4281 Old: &Task{ 4282 Config: map[string]interface{}{ 4283 "foo": 1, 4284 "bar": "baz", 4285 "bam": []string{"a", "b"}, 4286 "baz": map[string]int{ 4287 "a": 1, 4288 "b": 2, 4289 }, 4290 "boom": &Port{ 4291 Label: "boom_port", 4292 }, 4293 }, 4294 }, 4295 New: &Task{ 4296 Config: map[string]interface{}{ 4297 "foo": 2, 4298 "bar": "baz", 4299 "bam": []string{"a", "c", "d"}, 4300 "baz": map[string]int{ 4301 "b": 3, 4302 "c": 4, 4303 }, 4304 "boom": &Port{ 4305 Label: "boom_port2", 4306 }, 4307 }, 4308 }, 4309 Expected: &TaskDiff{ 4310 Type: DiffTypeEdited, 4311 Objects: []*ObjectDiff{ 4312 { 4313 Type: DiffTypeEdited, 4314 Name: "Config", 4315 Fields: []*FieldDiff{ 4316 { 4317 Type: DiffTypeEdited, 4318 Name: "bam[1]", 4319 Old: "b", 4320 New: "c", 4321 }, 4322 { 4323 Type: DiffTypeAdded, 4324 Name: "bam[2]", 4325 Old: "", 4326 New: "d", 4327 }, 4328 { 4329 Type: DiffTypeDeleted, 4330 Name: "baz[a]", 4331 Old: "1", 4332 New: "", 4333 }, 4334 { 4335 Type: DiffTypeEdited, 4336 Name: "baz[b]", 4337 Old: "2", 4338 New: "3", 4339 }, 4340 { 4341 Type: DiffTypeAdded, 4342 Name: "baz[c]", 4343 Old: "", 4344 New: "4", 4345 }, 4346 { 4347 Type: DiffTypeEdited, 4348 Name: "boom.Label", 4349 Old: "boom_port", 4350 New: "boom_port2", 4351 }, 4352 { 4353 Type: DiffTypeEdited, 4354 Name: "foo", 4355 Old: "1", 4356 New: "2", 4357 }, 4358 }, 4359 }, 4360 }, 4361 }, 4362 }, 4363 { 4364 Name: "Config edited with context", 4365 Contextual: true, 4366 Old: &Task{ 4367 Config: map[string]interface{}{ 4368 "foo": 1, 4369 "bar": "baz", 4370 "bam": []string{"a", "b"}, 4371 "baz": map[string]int{ 4372 "a": 1, 4373 "b": 2, 4374 }, 4375 "boom": &Port{ 4376 Label: "boom_port", 4377 }, 4378 }, 4379 }, 4380 New: &Task{ 4381 Config: map[string]interface{}{ 4382 "foo": 2, 4383 "bar": "baz", 4384 "bam": []string{"a", "c", "d"}, 4385 "baz": map[string]int{ 4386 "a": 1, 4387 "b": 2, 4388 }, 4389 "boom": &Port{ 4390 Label: "boom_port", 4391 }, 4392 }, 4393 }, 4394 Expected: &TaskDiff{ 4395 Type: DiffTypeEdited, 4396 Objects: []*ObjectDiff{ 4397 { 4398 Type: DiffTypeEdited, 4399 Name: "Config", 4400 Fields: []*FieldDiff{ 4401 { 4402 Type: DiffTypeNone, 4403 Name: "bam[0]", 4404 Old: "a", 4405 New: "a", 4406 }, 4407 { 4408 Type: DiffTypeEdited, 4409 Name: "bam[1]", 4410 Old: "b", 4411 New: "c", 4412 }, 4413 { 4414 Type: DiffTypeAdded, 4415 Name: "bam[2]", 4416 Old: "", 4417 New: "d", 4418 }, 4419 { 4420 Type: DiffTypeNone, 4421 Name: "bar", 4422 Old: "baz", 4423 New: "baz", 4424 }, 4425 { 4426 Type: DiffTypeNone, 4427 Name: "baz[a]", 4428 Old: "1", 4429 New: "1", 4430 }, 4431 { 4432 Type: DiffTypeNone, 4433 Name: "baz[b]", 4434 Old: "2", 4435 New: "2", 4436 }, 4437 { 4438 Type: DiffTypeNone, 4439 Name: "boom.Label", 4440 Old: "boom_port", 4441 New: "boom_port", 4442 }, 4443 { 4444 Type: DiffTypeNone, 4445 Name: "boom.To", 4446 Old: "0", 4447 New: "0", 4448 }, 4449 { 4450 Type: DiffTypeNone, 4451 Name: "boom.Value", 4452 Old: "0", 4453 New: "0", 4454 }, 4455 { 4456 Type: DiffTypeEdited, 4457 Name: "foo", 4458 Old: "1", 4459 New: "2", 4460 }, 4461 }, 4462 }, 4463 }, 4464 }, 4465 }, 4466 { 4467 Name: "Services edited (no checks)", 4468 Old: &Task{ 4469 Services: []*Service{ 4470 { 4471 Name: "foo", 4472 PortLabel: "foo", 4473 }, 4474 { 4475 Name: "bar", 4476 PortLabel: "bar", 4477 }, 4478 { 4479 Name: "baz", 4480 PortLabel: "baz", 4481 }, 4482 }, 4483 }, 4484 New: &Task{ 4485 Services: []*Service{ 4486 { 4487 Name: "bar", 4488 PortLabel: "bar", 4489 }, 4490 { 4491 Name: "baz", 4492 PortLabel: "baz2", 4493 }, 4494 { 4495 Name: "bam", 4496 PortLabel: "bam", 4497 }, 4498 }, 4499 }, 4500 Expected: &TaskDiff{ 4501 Type: DiffTypeEdited, 4502 Objects: []*ObjectDiff{ 4503 { 4504 Type: DiffTypeEdited, 4505 Name: "Service", 4506 Fields: []*FieldDiff{ 4507 { 4508 Type: DiffTypeEdited, 4509 Name: "PortLabel", 4510 Old: "baz", 4511 New: "baz2", 4512 }, 4513 }, 4514 }, 4515 { 4516 Type: DiffTypeAdded, 4517 Name: "Service", 4518 Fields: []*FieldDiff{ 4519 { 4520 Type: DiffTypeAdded, 4521 Name: "EnableTagOverride", 4522 Old: "", 4523 New: "false", 4524 }, 4525 { 4526 Type: DiffTypeAdded, 4527 Name: "Name", 4528 Old: "", 4529 New: "bam", 4530 }, 4531 { 4532 Type: DiffTypeAdded, 4533 Name: "PortLabel", 4534 Old: "", 4535 New: "bam", 4536 }, 4537 }, 4538 }, 4539 { 4540 Type: DiffTypeDeleted, 4541 Name: "Service", 4542 Fields: []*FieldDiff{ 4543 { 4544 Type: DiffTypeDeleted, 4545 Name: "EnableTagOverride", 4546 Old: "false", 4547 New: "", 4548 }, 4549 { 4550 Type: DiffTypeDeleted, 4551 Name: "Name", 4552 Old: "foo", 4553 New: "", 4554 }, 4555 { 4556 Type: DiffTypeDeleted, 4557 Name: "PortLabel", 4558 Old: "foo", 4559 New: "", 4560 }, 4561 }, 4562 }, 4563 }, 4564 }, 4565 }, 4566 { 4567 Name: "Services edited (no checks) with context", 4568 Contextual: true, 4569 Old: &Task{ 4570 Services: []*Service{ 4571 { 4572 Name: "foo", 4573 PortLabel: "foo", 4574 }, 4575 }, 4576 }, 4577 New: &Task{ 4578 Services: []*Service{ 4579 { 4580 Name: "foo", 4581 PortLabel: "bar", 4582 AddressMode: "driver", 4583 }, 4584 }, 4585 }, 4586 Expected: &TaskDiff{ 4587 Type: DiffTypeEdited, 4588 Objects: []*ObjectDiff{ 4589 { 4590 Type: DiffTypeEdited, 4591 Name: "Service", 4592 Fields: []*FieldDiff{ 4593 { 4594 Type: DiffTypeAdded, 4595 Name: "AddressMode", 4596 Old: "", 4597 New: "driver", 4598 }, 4599 { 4600 Type: DiffTypeNone, 4601 Name: "EnableTagOverride", 4602 Old: "false", 4603 New: "false", 4604 }, 4605 { 4606 Type: DiffTypeNone, 4607 Name: "Name", 4608 Old: "foo", 4609 New: "foo", 4610 }, 4611 { 4612 Type: DiffTypeEdited, 4613 Name: "PortLabel", 4614 Old: "foo", 4615 New: "bar", 4616 }, 4617 }, 4618 }, 4619 }, 4620 }, 4621 }, 4622 { 4623 Name: "Service EnableTagOverride edited no context", 4624 Contextual: false, 4625 Old: &Task{ 4626 Services: []*Service{{ 4627 EnableTagOverride: false, 4628 }}, 4629 }, 4630 New: &Task{ 4631 Services: []*Service{{ 4632 EnableTagOverride: true, 4633 }}, 4634 }, 4635 Expected: &TaskDiff{ 4636 Type: DiffTypeEdited, 4637 Objects: []*ObjectDiff{ 4638 { 4639 Type: DiffTypeEdited, 4640 Name: "Service", 4641 Fields: []*FieldDiff{ 4642 { 4643 Type: DiffTypeEdited, 4644 Name: "EnableTagOverride", 4645 Old: "false", 4646 New: "true", 4647 }, 4648 }, 4649 }, 4650 }, 4651 }, 4652 }, 4653 { 4654 Name: "Services tags edited (no checks) with context", 4655 Contextual: true, 4656 Old: &Task{ 4657 Services: []*Service{ 4658 { 4659 Tags: []string{"foo", "bar"}, 4660 CanaryTags: []string{"foo", "bar"}, 4661 }, 4662 }, 4663 }, 4664 New: &Task{ 4665 Services: []*Service{ 4666 { 4667 Tags: []string{"bar", "bam"}, 4668 CanaryTags: []string{"bar", "bam"}, 4669 }, 4670 }, 4671 }, 4672 Expected: &TaskDiff{ 4673 Type: DiffTypeEdited, 4674 Objects: []*ObjectDiff{ 4675 { 4676 Type: DiffTypeEdited, 4677 Name: "Service", 4678 Objects: []*ObjectDiff{ 4679 { 4680 Type: DiffTypeEdited, 4681 Name: "CanaryTags", 4682 Fields: []*FieldDiff{ 4683 { 4684 Type: DiffTypeAdded, 4685 Name: "CanaryTags", 4686 Old: "", 4687 New: "bam", 4688 }, 4689 { 4690 Type: DiffTypeNone, 4691 Name: "CanaryTags", 4692 Old: "bar", 4693 New: "bar", 4694 }, 4695 { 4696 Type: DiffTypeDeleted, 4697 Name: "CanaryTags", 4698 Old: "foo", 4699 New: "", 4700 }, 4701 }, 4702 }, 4703 { 4704 Type: DiffTypeEdited, 4705 Name: "Tags", 4706 Fields: []*FieldDiff{ 4707 { 4708 Type: DiffTypeAdded, 4709 Name: "Tags", 4710 Old: "", 4711 New: "bam", 4712 }, 4713 { 4714 Type: DiffTypeNone, 4715 Name: "Tags", 4716 Old: "bar", 4717 New: "bar", 4718 }, 4719 { 4720 Type: DiffTypeDeleted, 4721 Name: "Tags", 4722 Old: "foo", 4723 New: "", 4724 }, 4725 }, 4726 }, 4727 }, 4728 Fields: []*FieldDiff{ 4729 { 4730 Type: DiffTypeNone, 4731 Name: "AddressMode", 4732 }, 4733 { 4734 Type: DiffTypeNone, 4735 Name: "EnableTagOverride", 4736 Old: "false", 4737 New: "false", 4738 }, 4739 { 4740 Type: DiffTypeNone, 4741 Name: "Name", 4742 }, 4743 { 4744 Type: DiffTypeNone, 4745 Name: "PortLabel", 4746 }, 4747 }, 4748 }, 4749 }, 4750 }, 4751 }, 4752 4753 { 4754 Name: "Service with Connect", 4755 Old: &Task{ 4756 Services: []*Service{ 4757 { 4758 Name: "foo", 4759 }, 4760 }, 4761 }, 4762 New: &Task{ 4763 Services: []*Service{ 4764 { 4765 Name: "foo", 4766 Connect: &ConsulConnect{ 4767 SidecarService: &ConsulSidecarService{}, 4768 }, 4769 }, 4770 }, 4771 }, 4772 Expected: &TaskDiff{ 4773 Type: DiffTypeEdited, 4774 Objects: []*ObjectDiff{ 4775 { 4776 Type: DiffTypeEdited, 4777 Name: "Service", 4778 Objects: []*ObjectDiff{ 4779 { 4780 Type: DiffTypeAdded, 4781 Name: "ConsulConnect", 4782 Fields: []*FieldDiff{ 4783 { 4784 Type: DiffTypeAdded, 4785 Name: "Native", 4786 Old: "", 4787 New: "false", 4788 }, 4789 }, 4790 Objects: []*ObjectDiff{ 4791 { 4792 Type: DiffTypeAdded, 4793 Name: "SidecarService", 4794 }, 4795 }, 4796 }, 4797 }, 4798 }, 4799 }, 4800 }, 4801 }, 4802 4803 { 4804 Name: "Service Checks edited", 4805 Old: &Task{ 4806 Services: []*Service{ 4807 { 4808 Name: "foo", 4809 Checks: []*ServiceCheck{ 4810 { 4811 Name: "foo", 4812 Type: "http", 4813 Command: "foo", 4814 Args: []string{"foo"}, 4815 Path: "foo", 4816 Protocol: "http", 4817 Interval: 1 * time.Second, 4818 Timeout: 1 * time.Second, 4819 Header: map[string][]string{ 4820 "Foo": {"bar"}, 4821 }, 4822 }, 4823 { 4824 Name: "bar", 4825 Type: "http", 4826 Command: "foo", 4827 Args: []string{"foo"}, 4828 Path: "foo", 4829 Protocol: "http", 4830 Interval: 1 * time.Second, 4831 Timeout: 1 * time.Second, 4832 }, 4833 { 4834 Name: "baz", 4835 Type: "http", 4836 Command: "foo", 4837 Args: []string{"foo"}, 4838 Path: "foo", 4839 Protocol: "http", 4840 Interval: 1 * time.Second, 4841 Timeout: 1 * time.Second, 4842 }, 4843 }, 4844 }, 4845 }, 4846 }, 4847 New: &Task{ 4848 Services: []*Service{ 4849 { 4850 Name: "foo", 4851 Checks: []*ServiceCheck{ 4852 { 4853 Name: "bar", 4854 Type: "http", 4855 Command: "foo", 4856 Args: []string{"foo"}, 4857 Path: "foo", 4858 Protocol: "http", 4859 Interval: 1 * time.Second, 4860 Timeout: 1 * time.Second, 4861 }, 4862 { 4863 Name: "baz", 4864 Type: "tcp", 4865 Command: "foo", 4866 Args: []string{"foo"}, 4867 Path: "foo", 4868 Protocol: "http", 4869 Interval: 1 * time.Second, 4870 Timeout: 1 * time.Second, 4871 Header: map[string][]string{ 4872 "Eggs": {"spam"}, 4873 }, 4874 }, 4875 { 4876 Name: "bam", 4877 Type: "http", 4878 Command: "foo", 4879 Args: []string{"foo"}, 4880 Path: "foo", 4881 Protocol: "http", 4882 Interval: 1 * time.Second, 4883 Timeout: 1 * time.Second, 4884 }, 4885 }, 4886 }, 4887 }, 4888 }, 4889 Expected: &TaskDiff{ 4890 Type: DiffTypeEdited, 4891 Objects: []*ObjectDiff{ 4892 { 4893 Type: DiffTypeEdited, 4894 Name: "Service", 4895 Objects: []*ObjectDiff{ 4896 { 4897 Type: DiffTypeEdited, 4898 Name: "Check", 4899 Fields: []*FieldDiff{ 4900 { 4901 Type: DiffTypeEdited, 4902 Name: "Type", 4903 Old: "http", 4904 New: "tcp", 4905 }, 4906 }, 4907 Objects: []*ObjectDiff{ 4908 { 4909 Type: DiffTypeAdded, 4910 Name: "Header", 4911 Fields: []*FieldDiff{ 4912 { 4913 Type: DiffTypeAdded, 4914 Name: "Eggs[0]", 4915 Old: "", 4916 New: "spam", 4917 }, 4918 }, 4919 }, 4920 }, 4921 }, 4922 { 4923 Type: DiffTypeAdded, 4924 Name: "Check", 4925 Fields: []*FieldDiff{ 4926 { 4927 Type: DiffTypeAdded, 4928 Name: "Command", 4929 Old: "", 4930 New: "foo", 4931 }, 4932 { 4933 Type: DiffTypeAdded, 4934 Name: "Expose", 4935 Old: "", 4936 New: "false", 4937 }, 4938 { 4939 Type: DiffTypeAdded, 4940 Name: "GRPCUseTLS", 4941 Old: "", 4942 New: "false", 4943 }, 4944 { 4945 Type: DiffTypeAdded, 4946 Name: "Interval", 4947 Old: "", 4948 New: "1000000000", 4949 }, 4950 { 4951 Type: DiffTypeAdded, 4952 Name: "Name", 4953 Old: "", 4954 New: "bam", 4955 }, 4956 { 4957 Type: DiffTypeAdded, 4958 Name: "Path", 4959 Old: "", 4960 New: "foo", 4961 }, 4962 { 4963 Type: DiffTypeAdded, 4964 Name: "Protocol", 4965 Old: "", 4966 New: "http", 4967 }, 4968 { 4969 Type: DiffTypeAdded, 4970 Name: "TLSSkipVerify", 4971 Old: "", 4972 New: "false", 4973 }, 4974 { 4975 Type: DiffTypeAdded, 4976 Name: "Timeout", 4977 Old: "", 4978 New: "1000000000", 4979 }, 4980 { 4981 Type: DiffTypeAdded, 4982 Name: "Type", 4983 Old: "", 4984 New: "http", 4985 }, 4986 }, 4987 }, 4988 { 4989 Type: DiffTypeDeleted, 4990 Name: "Check", 4991 Fields: []*FieldDiff{ 4992 { 4993 Type: DiffTypeDeleted, 4994 Name: "Command", 4995 Old: "foo", 4996 New: "", 4997 }, 4998 { 4999 Type: DiffTypeDeleted, 5000 Name: "Expose", 5001 Old: "false", 5002 New: "", 5003 }, 5004 { 5005 Type: DiffTypeDeleted, 5006 Name: "GRPCUseTLS", 5007 Old: "false", 5008 New: "", 5009 }, 5010 { 5011 Type: DiffTypeDeleted, 5012 Name: "Interval", 5013 Old: "1000000000", 5014 New: "", 5015 }, 5016 { 5017 Type: DiffTypeDeleted, 5018 Name: "Name", 5019 Old: "foo", 5020 New: "", 5021 }, 5022 { 5023 Type: DiffTypeDeleted, 5024 Name: "Path", 5025 Old: "foo", 5026 New: "", 5027 }, 5028 { 5029 Type: DiffTypeDeleted, 5030 Name: "Protocol", 5031 Old: "http", 5032 New: "", 5033 }, 5034 { 5035 Type: DiffTypeDeleted, 5036 Name: "TLSSkipVerify", 5037 Old: "false", 5038 New: "", 5039 }, 5040 { 5041 Type: DiffTypeDeleted, 5042 Name: "Timeout", 5043 Old: "1000000000", 5044 New: "", 5045 }, 5046 { 5047 Type: DiffTypeDeleted, 5048 Name: "Type", 5049 Old: "http", 5050 New: "", 5051 }, 5052 }, 5053 Objects: []*ObjectDiff{ 5054 { 5055 Type: DiffTypeDeleted, 5056 Name: "Header", 5057 Fields: []*FieldDiff{ 5058 { 5059 Type: DiffTypeDeleted, 5060 Name: "Foo[0]", 5061 Old: "bar", 5062 }, 5063 }, 5064 }, 5065 }, 5066 }, 5067 }, 5068 }, 5069 }, 5070 }, 5071 }, 5072 { 5073 Name: "Service Checks edited with context", 5074 Contextual: true, 5075 Old: &Task{ 5076 Services: []*Service{ 5077 { 5078 Name: "foo", 5079 Checks: []*ServiceCheck{ 5080 { 5081 Name: "foo", 5082 Type: "http", 5083 Command: "foo", 5084 Args: []string{"foo"}, 5085 Path: "foo", 5086 Protocol: "http", 5087 Interval: 1 * time.Second, 5088 Timeout: 1 * time.Second, 5089 InitialStatus: "critical", 5090 Header: map[string][]string{ 5091 "Foo": {"bar"}, 5092 }, 5093 }, 5094 }, 5095 }, 5096 }, 5097 }, 5098 New: &Task{ 5099 Services: []*Service{ 5100 { 5101 Name: "foo", 5102 Checks: []*ServiceCheck{ 5103 { 5104 Name: "foo", 5105 Type: "tcp", 5106 Command: "foo", 5107 Args: []string{"foo"}, 5108 Path: "foo", 5109 Protocol: "http", 5110 Interval: 1 * time.Second, 5111 Timeout: 1 * time.Second, 5112 InitialStatus: "passing", 5113 Method: "POST", 5114 Header: map[string][]string{ 5115 "Foo": {"bar", "baz"}, 5116 "Eggs": {"spam"}, 5117 }, 5118 }, 5119 }, 5120 }, 5121 }, 5122 }, 5123 Expected: &TaskDiff{ 5124 Type: DiffTypeEdited, 5125 Objects: []*ObjectDiff{ 5126 { 5127 Type: DiffTypeEdited, 5128 Name: "Service", 5129 Fields: []*FieldDiff{ 5130 { 5131 Type: DiffTypeNone, 5132 Name: "AddressMode", 5133 Old: "", 5134 New: "", 5135 }, 5136 { 5137 Type: DiffTypeNone, 5138 Name: "EnableTagOverride", 5139 Old: "false", 5140 New: "false", 5141 }, 5142 { 5143 Type: DiffTypeNone, 5144 Name: "Name", 5145 Old: "foo", 5146 New: "foo", 5147 }, 5148 { 5149 Type: DiffTypeNone, 5150 Name: "PortLabel", 5151 Old: "", 5152 New: "", 5153 }, 5154 }, 5155 Objects: []*ObjectDiff{ 5156 { 5157 Type: DiffTypeEdited, 5158 Name: "Check", 5159 Fields: []*FieldDiff{ 5160 { 5161 Type: DiffTypeNone, 5162 Name: "AddressMode", 5163 Old: "", 5164 New: "", 5165 }, 5166 { 5167 Type: DiffTypeNone, 5168 Name: "Command", 5169 Old: "foo", 5170 New: "foo", 5171 }, 5172 { 5173 Type: DiffTypeNone, 5174 Name: "Expose", 5175 Old: "false", 5176 New: "false", 5177 }, 5178 { 5179 Type: DiffTypeNone, 5180 Name: "GRPCService", 5181 Old: "", 5182 New: "", 5183 }, 5184 { 5185 Type: DiffTypeNone, 5186 Name: "GRPCUseTLS", 5187 Old: "false", 5188 New: "false", 5189 }, 5190 { 5191 Type: DiffTypeEdited, 5192 Name: "InitialStatus", 5193 Old: "critical", 5194 New: "passing", 5195 }, 5196 { 5197 Type: DiffTypeNone, 5198 Name: "Interval", 5199 Old: "1000000000", 5200 New: "1000000000", 5201 }, 5202 { 5203 Type: DiffTypeAdded, 5204 Name: "Method", 5205 Old: "", 5206 New: "POST", 5207 }, 5208 { 5209 Type: DiffTypeNone, 5210 Name: "Name", 5211 Old: "foo", 5212 New: "foo", 5213 }, 5214 { 5215 Type: DiffTypeNone, 5216 Name: "Path", 5217 Old: "foo", 5218 New: "foo", 5219 }, 5220 { 5221 Type: DiffTypeNone, 5222 Name: "PortLabel", 5223 Old: "", 5224 New: "", 5225 }, 5226 { 5227 Type: DiffTypeNone, 5228 Name: "Protocol", 5229 Old: "http", 5230 New: "http", 5231 }, 5232 { 5233 Type: DiffTypeNone, 5234 Name: "TLSSkipVerify", 5235 Old: "false", 5236 New: "false", 5237 }, 5238 { 5239 Type: DiffTypeNone, 5240 Name: "TaskName", 5241 Old: "", 5242 New: "", 5243 }, 5244 { 5245 Type: DiffTypeNone, 5246 Name: "Timeout", 5247 Old: "1000000000", 5248 New: "1000000000", 5249 }, 5250 { 5251 Type: DiffTypeEdited, 5252 Name: "Type", 5253 Old: "http", 5254 New: "tcp", 5255 }, 5256 }, 5257 Objects: []*ObjectDiff{ 5258 { 5259 Type: DiffTypeEdited, 5260 Name: "Header", 5261 Fields: []*FieldDiff{ 5262 { 5263 Type: DiffTypeAdded, 5264 Name: "Eggs[0]", 5265 Old: "", 5266 New: "spam", 5267 }, 5268 { 5269 Type: DiffTypeNone, 5270 Name: "Foo[0]", 5271 Old: "bar", 5272 New: "bar", 5273 }, 5274 { 5275 Type: DiffTypeAdded, 5276 Name: "Foo[1]", 5277 Old: "", 5278 New: "baz", 5279 }, 5280 }, 5281 }, 5282 }, 5283 }, 5284 }, 5285 }, 5286 }, 5287 }, 5288 }, 5289 { 5290 Name: "CheckRestart edited", 5291 Old: &Task{ 5292 Services: []*Service{ 5293 { 5294 Name: "foo", 5295 Checks: []*ServiceCheck{ 5296 { 5297 Name: "foo", 5298 Type: "http", 5299 Command: "foo", 5300 Args: []string{"foo"}, 5301 Path: "foo", 5302 Protocol: "http", 5303 Interval: 1 * time.Second, 5304 Timeout: 1 * time.Second, 5305 }, 5306 { 5307 Name: "bar", 5308 Type: "http", 5309 Command: "foo", 5310 Args: []string{"foo"}, 5311 Path: "foo", 5312 Protocol: "http", 5313 Interval: 1 * time.Second, 5314 Timeout: 1 * time.Second, 5315 CheckRestart: &CheckRestart{ 5316 Limit: 2, 5317 Grace: 2 * time.Second, 5318 }, 5319 }, 5320 { 5321 Name: "baz", 5322 Type: "http", 5323 Command: "foo", 5324 Args: []string{"foo"}, 5325 Path: "foo", 5326 Protocol: "http", 5327 Interval: 1 * time.Second, 5328 Timeout: 1 * time.Second, 5329 CheckRestart: &CheckRestart{ 5330 Limit: 3, 5331 Grace: 3 * time.Second, 5332 }, 5333 }, 5334 }, 5335 }, 5336 }, 5337 }, 5338 New: &Task{ 5339 Services: []*Service{ 5340 { 5341 Name: "foo", 5342 Checks: []*ServiceCheck{ 5343 { 5344 Name: "foo", 5345 Type: "http", 5346 Command: "foo", 5347 Args: []string{"foo"}, 5348 Path: "foo", 5349 Protocol: "http", 5350 Interval: 1 * time.Second, 5351 Timeout: 1 * time.Second, 5352 CheckRestart: &CheckRestart{ 5353 Limit: 1, 5354 Grace: 1 * time.Second, 5355 }, 5356 }, 5357 { 5358 Name: "bar", 5359 Type: "http", 5360 Command: "foo", 5361 Args: []string{"foo"}, 5362 Path: "foo", 5363 Protocol: "http", 5364 Interval: 1 * time.Second, 5365 Timeout: 1 * time.Second, 5366 }, 5367 { 5368 Name: "baz", 5369 Type: "http", 5370 Command: "foo", 5371 Args: []string{"foo"}, 5372 Path: "foo", 5373 Protocol: "http", 5374 Interval: 1 * time.Second, 5375 Timeout: 1 * time.Second, 5376 CheckRestart: &CheckRestart{ 5377 Limit: 4, 5378 Grace: 4 * time.Second, 5379 }, 5380 }, 5381 }, 5382 }, 5383 }, 5384 }, 5385 Expected: &TaskDiff{ 5386 Type: DiffTypeEdited, 5387 Objects: []*ObjectDiff{ 5388 { 5389 Type: DiffTypeEdited, 5390 Name: "Service", 5391 Objects: []*ObjectDiff{ 5392 { 5393 Type: DiffTypeEdited, 5394 Name: "Check", 5395 Objects: []*ObjectDiff{ 5396 { 5397 Type: DiffTypeEdited, 5398 Name: "CheckRestart", 5399 Fields: []*FieldDiff{ 5400 { 5401 Type: DiffTypeEdited, 5402 Name: "Grace", 5403 Old: "3000000000", 5404 New: "4000000000", 5405 }, 5406 { 5407 Type: DiffTypeEdited, 5408 Name: "Limit", 5409 Old: "3", 5410 New: "4", 5411 }, 5412 }, 5413 }, 5414 }, 5415 }, 5416 { 5417 Type: DiffTypeEdited, 5418 Name: "Check", 5419 Objects: []*ObjectDiff{ 5420 { 5421 Type: DiffTypeAdded, 5422 Name: "CheckRestart", 5423 Fields: []*FieldDiff{ 5424 { 5425 Type: DiffTypeAdded, 5426 Name: "Grace", 5427 New: "1000000000", 5428 }, 5429 { 5430 Type: DiffTypeAdded, 5431 Name: "IgnoreWarnings", 5432 New: "false", 5433 }, 5434 { 5435 Type: DiffTypeAdded, 5436 Name: "Limit", 5437 New: "1", 5438 }, 5439 }, 5440 }, 5441 }, 5442 }, 5443 { 5444 Type: DiffTypeEdited, 5445 Name: "Check", 5446 Objects: []*ObjectDiff{ 5447 { 5448 Type: DiffTypeDeleted, 5449 Name: "CheckRestart", 5450 Fields: []*FieldDiff{ 5451 { 5452 Type: DiffTypeDeleted, 5453 Name: "Grace", 5454 Old: "2000000000", 5455 }, 5456 { 5457 Type: DiffTypeDeleted, 5458 Name: "IgnoreWarnings", 5459 Old: "false", 5460 }, 5461 { 5462 Type: DiffTypeDeleted, 5463 Name: "Limit", 5464 Old: "2", 5465 }, 5466 }, 5467 }, 5468 }, 5469 }, 5470 }, 5471 }, 5472 }, 5473 }, 5474 }, 5475 { 5476 Name: "Vault added", 5477 Old: &Task{}, 5478 New: &Task{ 5479 Vault: &Vault{ 5480 Policies: []string{"foo", "bar"}, 5481 Env: true, 5482 ChangeMode: "signal", 5483 ChangeSignal: "SIGUSR1", 5484 }, 5485 }, 5486 Expected: &TaskDiff{ 5487 Type: DiffTypeEdited, 5488 Objects: []*ObjectDiff{ 5489 { 5490 Type: DiffTypeAdded, 5491 Name: "Vault", 5492 Fields: []*FieldDiff{ 5493 { 5494 Type: DiffTypeAdded, 5495 Name: "ChangeMode", 5496 Old: "", 5497 New: "signal", 5498 }, 5499 { 5500 Type: DiffTypeAdded, 5501 Name: "ChangeSignal", 5502 Old: "", 5503 New: "SIGUSR1", 5504 }, 5505 { 5506 Type: DiffTypeAdded, 5507 Name: "Env", 5508 Old: "", 5509 New: "true", 5510 }, 5511 }, 5512 Objects: []*ObjectDiff{ 5513 { 5514 Type: DiffTypeAdded, 5515 Name: "Policies", 5516 Fields: []*FieldDiff{ 5517 { 5518 Type: DiffTypeAdded, 5519 Name: "Policies", 5520 Old: "", 5521 New: "bar", 5522 }, 5523 { 5524 Type: DiffTypeAdded, 5525 Name: "Policies", 5526 Old: "", 5527 New: "foo", 5528 }, 5529 }, 5530 }, 5531 }, 5532 }, 5533 }, 5534 }, 5535 }, 5536 { 5537 Name: "Vault deleted", 5538 Old: &Task{ 5539 Vault: &Vault{ 5540 Policies: []string{"foo", "bar"}, 5541 Env: true, 5542 ChangeMode: "signal", 5543 ChangeSignal: "SIGUSR1", 5544 }, 5545 }, 5546 New: &Task{}, 5547 Expected: &TaskDiff{ 5548 Type: DiffTypeEdited, 5549 Objects: []*ObjectDiff{ 5550 { 5551 Type: DiffTypeDeleted, 5552 Name: "Vault", 5553 Fields: []*FieldDiff{ 5554 { 5555 Type: DiffTypeDeleted, 5556 Name: "ChangeMode", 5557 Old: "signal", 5558 New: "", 5559 }, 5560 { 5561 Type: DiffTypeDeleted, 5562 Name: "ChangeSignal", 5563 Old: "SIGUSR1", 5564 New: "", 5565 }, 5566 { 5567 Type: DiffTypeDeleted, 5568 Name: "Env", 5569 Old: "true", 5570 New: "", 5571 }, 5572 }, 5573 Objects: []*ObjectDiff{ 5574 { 5575 Type: DiffTypeDeleted, 5576 Name: "Policies", 5577 Fields: []*FieldDiff{ 5578 { 5579 Type: DiffTypeDeleted, 5580 Name: "Policies", 5581 Old: "bar", 5582 New: "", 5583 }, 5584 { 5585 Type: DiffTypeDeleted, 5586 Name: "Policies", 5587 Old: "foo", 5588 New: "", 5589 }, 5590 }, 5591 }, 5592 }, 5593 }, 5594 }, 5595 }, 5596 }, 5597 { 5598 Name: "Vault edited", 5599 Old: &Task{ 5600 Vault: &Vault{ 5601 Policies: []string{"foo", "bar"}, 5602 Env: true, 5603 ChangeMode: "signal", 5604 ChangeSignal: "SIGUSR1", 5605 }, 5606 }, 5607 New: &Task{ 5608 Vault: &Vault{ 5609 Policies: []string{"bar", "baz"}, 5610 Env: false, 5611 ChangeMode: "restart", 5612 ChangeSignal: "foo", 5613 }, 5614 }, 5615 Expected: &TaskDiff{ 5616 Type: DiffTypeEdited, 5617 Objects: []*ObjectDiff{ 5618 { 5619 Type: DiffTypeEdited, 5620 Name: "Vault", 5621 Fields: []*FieldDiff{ 5622 { 5623 Type: DiffTypeEdited, 5624 Name: "ChangeMode", 5625 Old: "signal", 5626 New: "restart", 5627 }, 5628 { 5629 Type: DiffTypeEdited, 5630 Name: "ChangeSignal", 5631 Old: "SIGUSR1", 5632 New: "foo", 5633 }, 5634 { 5635 Type: DiffTypeEdited, 5636 Name: "Env", 5637 Old: "true", 5638 New: "false", 5639 }, 5640 }, 5641 Objects: []*ObjectDiff{ 5642 { 5643 Type: DiffTypeEdited, 5644 Name: "Policies", 5645 Fields: []*FieldDiff{ 5646 { 5647 Type: DiffTypeAdded, 5648 Name: "Policies", 5649 Old: "", 5650 New: "baz", 5651 }, 5652 { 5653 Type: DiffTypeDeleted, 5654 Name: "Policies", 5655 Old: "foo", 5656 New: "", 5657 }, 5658 }, 5659 }, 5660 }, 5661 }, 5662 }, 5663 }, 5664 }, 5665 { 5666 Name: "Vault edited with context", 5667 Contextual: true, 5668 Old: &Task{ 5669 Vault: &Vault{ 5670 Policies: []string{"foo", "bar"}, 5671 Env: true, 5672 ChangeMode: "signal", 5673 ChangeSignal: "SIGUSR1", 5674 }, 5675 }, 5676 New: &Task{ 5677 Vault: &Vault{ 5678 Policies: []string{"bar", "baz"}, 5679 Env: true, 5680 ChangeMode: "signal", 5681 ChangeSignal: "SIGUSR1", 5682 }, 5683 }, 5684 Expected: &TaskDiff{ 5685 Type: DiffTypeEdited, 5686 Objects: []*ObjectDiff{ 5687 { 5688 Type: DiffTypeEdited, 5689 Name: "Vault", 5690 Fields: []*FieldDiff{ 5691 { 5692 Type: DiffTypeNone, 5693 Name: "ChangeMode", 5694 Old: "signal", 5695 New: "signal", 5696 }, 5697 { 5698 Type: DiffTypeNone, 5699 Name: "ChangeSignal", 5700 Old: "SIGUSR1", 5701 New: "SIGUSR1", 5702 }, 5703 { 5704 Type: DiffTypeNone, 5705 Name: "Env", 5706 Old: "true", 5707 New: "true", 5708 }, 5709 }, 5710 Objects: []*ObjectDiff{ 5711 { 5712 Type: DiffTypeEdited, 5713 Name: "Policies", 5714 Fields: []*FieldDiff{ 5715 { 5716 Type: DiffTypeAdded, 5717 Name: "Policies", 5718 Old: "", 5719 New: "baz", 5720 }, 5721 { 5722 Type: DiffTypeNone, 5723 Name: "Policies", 5724 Old: "bar", 5725 New: "bar", 5726 }, 5727 { 5728 Type: DiffTypeDeleted, 5729 Name: "Policies", 5730 Old: "foo", 5731 New: "", 5732 }, 5733 }, 5734 }, 5735 }, 5736 }, 5737 }, 5738 }, 5739 }, 5740 { 5741 Name: "Template edited", 5742 Old: &Task{ 5743 Templates: []*Template{ 5744 { 5745 SourcePath: "foo", 5746 DestPath: "bar", 5747 EmbeddedTmpl: "baz", 5748 ChangeMode: "bam", 5749 ChangeSignal: "SIGHUP", 5750 Splay: 1, 5751 Perms: "0644", 5752 }, 5753 { 5754 SourcePath: "foo2", 5755 DestPath: "bar2", 5756 EmbeddedTmpl: "baz2", 5757 ChangeMode: "bam2", 5758 ChangeSignal: "SIGHUP2", 5759 Splay: 2, 5760 Perms: "0666", 5761 Envvars: true, 5762 }, 5763 }, 5764 }, 5765 New: &Task{ 5766 Templates: []*Template{ 5767 { 5768 SourcePath: "foo", 5769 DestPath: "bar", 5770 EmbeddedTmpl: "baz", 5771 ChangeMode: "bam", 5772 ChangeSignal: "SIGHUP", 5773 Splay: 1, 5774 Perms: "0644", 5775 }, 5776 { 5777 SourcePath: "foo3", 5778 DestPath: "bar3", 5779 EmbeddedTmpl: "baz3", 5780 ChangeMode: "bam3", 5781 ChangeSignal: "SIGHUP3", 5782 Splay: 3, 5783 Perms: "0776", 5784 }, 5785 }, 5786 }, 5787 Expected: &TaskDiff{ 5788 Type: DiffTypeEdited, 5789 Objects: []*ObjectDiff{ 5790 { 5791 Type: DiffTypeAdded, 5792 Name: "Template", 5793 Fields: []*FieldDiff{ 5794 { 5795 Type: DiffTypeAdded, 5796 Name: "ChangeMode", 5797 Old: "", 5798 New: "bam3", 5799 }, 5800 { 5801 Type: DiffTypeAdded, 5802 Name: "ChangeSignal", 5803 Old: "", 5804 New: "SIGHUP3", 5805 }, 5806 { 5807 Type: DiffTypeAdded, 5808 Name: "DestPath", 5809 Old: "", 5810 New: "bar3", 5811 }, 5812 { 5813 Type: DiffTypeAdded, 5814 Name: "EmbeddedTmpl", 5815 Old: "", 5816 New: "baz3", 5817 }, 5818 { 5819 Type: DiffTypeAdded, 5820 Name: "Envvars", 5821 Old: "", 5822 New: "false", 5823 }, 5824 { 5825 Type: DiffTypeAdded, 5826 Name: "Perms", 5827 Old: "", 5828 New: "0776", 5829 }, 5830 { 5831 Type: DiffTypeAdded, 5832 Name: "SourcePath", 5833 Old: "", 5834 New: "foo3", 5835 }, 5836 { 5837 Type: DiffTypeAdded, 5838 Name: "Splay", 5839 Old: "", 5840 New: "3", 5841 }, 5842 { 5843 Type: DiffTypeAdded, 5844 Name: "VaultGrace", 5845 Old: "", 5846 New: "0", 5847 }, 5848 }, 5849 }, 5850 { 5851 Type: DiffTypeDeleted, 5852 Name: "Template", 5853 Fields: []*FieldDiff{ 5854 { 5855 Type: DiffTypeDeleted, 5856 Name: "ChangeMode", 5857 Old: "bam2", 5858 New: "", 5859 }, 5860 { 5861 Type: DiffTypeDeleted, 5862 Name: "ChangeSignal", 5863 Old: "SIGHUP2", 5864 New: "", 5865 }, 5866 { 5867 Type: DiffTypeDeleted, 5868 Name: "DestPath", 5869 Old: "bar2", 5870 New: "", 5871 }, 5872 { 5873 Type: DiffTypeDeleted, 5874 Name: "EmbeddedTmpl", 5875 Old: "baz2", 5876 New: "", 5877 }, 5878 { 5879 Type: DiffTypeDeleted, 5880 Name: "Envvars", 5881 Old: "true", 5882 New: "", 5883 }, 5884 { 5885 Type: DiffTypeDeleted, 5886 Name: "Perms", 5887 Old: "0666", 5888 New: "", 5889 }, 5890 { 5891 Type: DiffTypeDeleted, 5892 Name: "SourcePath", 5893 Old: "foo2", 5894 New: "", 5895 }, 5896 { 5897 Type: DiffTypeDeleted, 5898 Name: "Splay", 5899 Old: "2", 5900 New: "", 5901 }, 5902 { 5903 Type: DiffTypeDeleted, 5904 Name: "VaultGrace", 5905 Old: "0", 5906 New: "", 5907 }, 5908 }, 5909 }, 5910 }, 5911 }, 5912 }, 5913 { 5914 Name: "DispatchPayload added", 5915 Old: &Task{}, 5916 New: &Task{ 5917 DispatchPayload: &DispatchPayloadConfig{ 5918 File: "foo", 5919 }, 5920 }, 5921 Expected: &TaskDiff{ 5922 Type: DiffTypeEdited, 5923 Objects: []*ObjectDiff{ 5924 { 5925 Type: DiffTypeAdded, 5926 Name: "DispatchPayload", 5927 Fields: []*FieldDiff{ 5928 { 5929 Type: DiffTypeAdded, 5930 Name: "File", 5931 Old: "", 5932 New: "foo", 5933 }, 5934 }, 5935 }, 5936 }, 5937 }, 5938 }, 5939 { 5940 Name: "DispatchPayload deleted", 5941 Old: &Task{ 5942 DispatchPayload: &DispatchPayloadConfig{ 5943 File: "foo", 5944 }, 5945 }, 5946 New: &Task{}, 5947 Expected: &TaskDiff{ 5948 Type: DiffTypeEdited, 5949 Objects: []*ObjectDiff{ 5950 { 5951 Type: DiffTypeDeleted, 5952 Name: "DispatchPayload", 5953 Fields: []*FieldDiff{ 5954 { 5955 Type: DiffTypeDeleted, 5956 Name: "File", 5957 Old: "foo", 5958 New: "", 5959 }, 5960 }, 5961 }, 5962 }, 5963 }, 5964 }, 5965 { 5966 Name: "Dispatch payload edited", 5967 Old: &Task{ 5968 DispatchPayload: &DispatchPayloadConfig{ 5969 File: "foo", 5970 }, 5971 }, 5972 New: &Task{ 5973 DispatchPayload: &DispatchPayloadConfig{ 5974 File: "bar", 5975 }, 5976 }, 5977 Expected: &TaskDiff{ 5978 Type: DiffTypeEdited, 5979 Objects: []*ObjectDiff{ 5980 { 5981 Type: DiffTypeEdited, 5982 Name: "DispatchPayload", 5983 Fields: []*FieldDiff{ 5984 { 5985 Type: DiffTypeEdited, 5986 Name: "File", 5987 Old: "foo", 5988 New: "bar", 5989 }, 5990 }, 5991 }, 5992 }, 5993 }, 5994 }, 5995 { 5996 // Place holder for if more fields are added 5997 Name: "DispatchPayload edited with context", 5998 Contextual: true, 5999 Old: &Task{ 6000 DispatchPayload: &DispatchPayloadConfig{ 6001 File: "foo", 6002 }, 6003 }, 6004 New: &Task{ 6005 DispatchPayload: &DispatchPayloadConfig{ 6006 File: "bar", 6007 }, 6008 }, 6009 Expected: &TaskDiff{ 6010 Type: DiffTypeEdited, 6011 Objects: []*ObjectDiff{ 6012 { 6013 Type: DiffTypeEdited, 6014 Name: "DispatchPayload", 6015 Fields: []*FieldDiff{ 6016 { 6017 Type: DiffTypeEdited, 6018 Name: "File", 6019 Old: "foo", 6020 New: "bar", 6021 }, 6022 }, 6023 }, 6024 }, 6025 }, 6026 }, 6027 } 6028 6029 for i, c := range cases { 6030 t.Run(c.Name, func(t *testing.T) { 6031 actual, err := c.Old.Diff(c.New, c.Contextual) 6032 if c.Error && err == nil { 6033 t.Fatalf("case %d: expected errored", i+1) 6034 } else if err != nil { 6035 if !c.Error { 6036 t.Fatalf("case %d: errored %#v", i+1, err) 6037 } else { 6038 return 6039 } 6040 } 6041 6042 if !reflect.DeepEqual(actual, c.Expected) { 6043 t.Errorf("case %d: got:\n%#v\n want:\n%#v\n", 6044 i+1, actual, c.Expected) 6045 } 6046 }) 6047 } 6048 }