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