github.com/zhizhiboom/nomad@v0.8.5-0.20180907175415-f28fd3a1a056/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: "AutoRevert", 1983 Old: "true", 1984 New: "", 1985 }, 1986 { 1987 Type: DiffTypeDeleted, 1988 Name: "Canary", 1989 Old: "0", 1990 New: "", 1991 }, 1992 { 1993 Type: DiffTypeDeleted, 1994 Name: "HealthyDeadline", 1995 Old: "0", 1996 New: "", 1997 }, 1998 { 1999 Type: DiffTypeDeleted, 2000 Name: "MaxParallel", 2001 Old: "0", 2002 New: "", 2003 }, 2004 { 2005 Type: DiffTypeDeleted, 2006 Name: "MinHealthyTime", 2007 Old: "0", 2008 New: "", 2009 }, 2010 { 2011 Type: DiffTypeDeleted, 2012 Name: "ProgressDeadline", 2013 Old: "0", 2014 New: "", 2015 }, 2016 }, 2017 }, 2018 }, 2019 }, 2020 }, 2021 { 2022 // Update strategy added 2023 Old: &TaskGroup{}, 2024 New: &TaskGroup{ 2025 Update: &UpdateStrategy{ 2026 AutoRevert: true, 2027 }, 2028 }, 2029 Expected: &TaskGroupDiff{ 2030 Type: DiffTypeEdited, 2031 Objects: []*ObjectDiff{ 2032 { 2033 Type: DiffTypeAdded, 2034 Name: "Update", 2035 Fields: []*FieldDiff{ 2036 { 2037 Type: DiffTypeAdded, 2038 Name: "AutoRevert", 2039 Old: "", 2040 New: "true", 2041 }, 2042 { 2043 Type: DiffTypeAdded, 2044 Name: "Canary", 2045 Old: "", 2046 New: "0", 2047 }, 2048 { 2049 Type: DiffTypeAdded, 2050 Name: "HealthyDeadline", 2051 Old: "", 2052 New: "0", 2053 }, 2054 { 2055 Type: DiffTypeAdded, 2056 Name: "MaxParallel", 2057 Old: "", 2058 New: "0", 2059 }, 2060 { 2061 Type: DiffTypeAdded, 2062 Name: "MinHealthyTime", 2063 Old: "", 2064 New: "0", 2065 }, 2066 { 2067 Type: DiffTypeAdded, 2068 Name: "ProgressDeadline", 2069 Old: "", 2070 New: "0", 2071 }, 2072 }, 2073 }, 2074 }, 2075 }, 2076 }, 2077 { 2078 // Update strategy edited 2079 Old: &TaskGroup{ 2080 Update: &UpdateStrategy{ 2081 MaxParallel: 5, 2082 HealthCheck: "foo", 2083 MinHealthyTime: 1 * time.Second, 2084 HealthyDeadline: 30 * time.Second, 2085 ProgressDeadline: 29 * time.Second, 2086 AutoRevert: true, 2087 Canary: 2, 2088 }, 2089 }, 2090 New: &TaskGroup{ 2091 Update: &UpdateStrategy{ 2092 MaxParallel: 7, 2093 HealthCheck: "bar", 2094 MinHealthyTime: 2 * time.Second, 2095 HealthyDeadline: 31 * time.Second, 2096 ProgressDeadline: 32 * time.Second, 2097 AutoRevert: false, 2098 Canary: 1, 2099 }, 2100 }, 2101 Expected: &TaskGroupDiff{ 2102 Type: DiffTypeEdited, 2103 Objects: []*ObjectDiff{ 2104 { 2105 Type: DiffTypeEdited, 2106 Name: "Update", 2107 Fields: []*FieldDiff{ 2108 { 2109 Type: DiffTypeEdited, 2110 Name: "AutoRevert", 2111 Old: "true", 2112 New: "false", 2113 }, 2114 { 2115 Type: DiffTypeEdited, 2116 Name: "Canary", 2117 Old: "2", 2118 New: "1", 2119 }, 2120 { 2121 Type: DiffTypeEdited, 2122 Name: "HealthCheck", 2123 Old: "foo", 2124 New: "bar", 2125 }, 2126 { 2127 Type: DiffTypeEdited, 2128 Name: "HealthyDeadline", 2129 Old: "30000000000", 2130 New: "31000000000", 2131 }, 2132 { 2133 Type: DiffTypeEdited, 2134 Name: "MaxParallel", 2135 Old: "5", 2136 New: "7", 2137 }, 2138 { 2139 Type: DiffTypeEdited, 2140 Name: "MinHealthyTime", 2141 Old: "1000000000", 2142 New: "2000000000", 2143 }, 2144 { 2145 Type: DiffTypeEdited, 2146 Name: "ProgressDeadline", 2147 Old: "29000000000", 2148 New: "32000000000", 2149 }, 2150 }, 2151 }, 2152 }, 2153 }, 2154 }, 2155 { 2156 // Update strategy edited with context 2157 Contextual: true, 2158 Old: &TaskGroup{ 2159 Update: &UpdateStrategy{ 2160 MaxParallel: 5, 2161 HealthCheck: "foo", 2162 MinHealthyTime: 1 * time.Second, 2163 HealthyDeadline: 30 * time.Second, 2164 ProgressDeadline: 30 * time.Second, 2165 AutoRevert: true, 2166 Canary: 2, 2167 }, 2168 }, 2169 New: &TaskGroup{ 2170 Update: &UpdateStrategy{ 2171 MaxParallel: 7, 2172 HealthCheck: "foo", 2173 MinHealthyTime: 1 * time.Second, 2174 HealthyDeadline: 30 * time.Second, 2175 ProgressDeadline: 30 * time.Second, 2176 AutoRevert: true, 2177 Canary: 2, 2178 }, 2179 }, 2180 Expected: &TaskGroupDiff{ 2181 Type: DiffTypeEdited, 2182 Objects: []*ObjectDiff{ 2183 { 2184 Type: DiffTypeEdited, 2185 Name: "Update", 2186 Fields: []*FieldDiff{ 2187 { 2188 Type: DiffTypeNone, 2189 Name: "AutoRevert", 2190 Old: "true", 2191 New: "true", 2192 }, 2193 { 2194 Type: DiffTypeNone, 2195 Name: "Canary", 2196 Old: "2", 2197 New: "2", 2198 }, 2199 { 2200 Type: DiffTypeNone, 2201 Name: "HealthCheck", 2202 Old: "foo", 2203 New: "foo", 2204 }, 2205 { 2206 Type: DiffTypeNone, 2207 Name: "HealthyDeadline", 2208 Old: "30000000000", 2209 New: "30000000000", 2210 }, 2211 { 2212 Type: DiffTypeEdited, 2213 Name: "MaxParallel", 2214 Old: "5", 2215 New: "7", 2216 }, 2217 { 2218 Type: DiffTypeNone, 2219 Name: "MinHealthyTime", 2220 Old: "1000000000", 2221 New: "1000000000", 2222 }, 2223 { 2224 Type: DiffTypeNone, 2225 Name: "ProgressDeadline", 2226 Old: "30000000000", 2227 New: "30000000000", 2228 }, 2229 }, 2230 }, 2231 }, 2232 }, 2233 }, 2234 { 2235 // EphemeralDisk added 2236 Old: &TaskGroup{}, 2237 New: &TaskGroup{ 2238 EphemeralDisk: &EphemeralDisk{ 2239 Migrate: true, 2240 Sticky: true, 2241 SizeMB: 100, 2242 }, 2243 }, 2244 Expected: &TaskGroupDiff{ 2245 Type: DiffTypeEdited, 2246 Objects: []*ObjectDiff{ 2247 { 2248 Type: DiffTypeAdded, 2249 Name: "EphemeralDisk", 2250 Fields: []*FieldDiff{ 2251 { 2252 Type: DiffTypeAdded, 2253 Name: "Migrate", 2254 Old: "", 2255 New: "true", 2256 }, 2257 { 2258 Type: DiffTypeAdded, 2259 Name: "SizeMB", 2260 Old: "", 2261 New: "100", 2262 }, 2263 { 2264 Type: DiffTypeAdded, 2265 Name: "Sticky", 2266 Old: "", 2267 New: "true", 2268 }, 2269 }, 2270 }, 2271 }, 2272 }, 2273 }, 2274 { 2275 // EphemeralDisk deleted 2276 Old: &TaskGroup{ 2277 EphemeralDisk: &EphemeralDisk{ 2278 Migrate: true, 2279 Sticky: true, 2280 SizeMB: 100, 2281 }, 2282 }, 2283 New: &TaskGroup{}, 2284 Expected: &TaskGroupDiff{ 2285 Type: DiffTypeEdited, 2286 Objects: []*ObjectDiff{ 2287 { 2288 Type: DiffTypeDeleted, 2289 Name: "EphemeralDisk", 2290 Fields: []*FieldDiff{ 2291 { 2292 Type: DiffTypeDeleted, 2293 Name: "Migrate", 2294 Old: "true", 2295 New: "", 2296 }, 2297 { 2298 Type: DiffTypeDeleted, 2299 Name: "SizeMB", 2300 Old: "100", 2301 New: "", 2302 }, 2303 { 2304 Type: DiffTypeDeleted, 2305 Name: "Sticky", 2306 Old: "true", 2307 New: "", 2308 }, 2309 }, 2310 }, 2311 }, 2312 }, 2313 }, 2314 { 2315 // EphemeralDisk edited 2316 Old: &TaskGroup{ 2317 EphemeralDisk: &EphemeralDisk{ 2318 Migrate: true, 2319 Sticky: true, 2320 SizeMB: 150, 2321 }, 2322 }, 2323 New: &TaskGroup{ 2324 EphemeralDisk: &EphemeralDisk{ 2325 Migrate: false, 2326 Sticky: false, 2327 SizeMB: 90, 2328 }, 2329 }, 2330 Expected: &TaskGroupDiff{ 2331 Type: DiffTypeEdited, 2332 Objects: []*ObjectDiff{ 2333 { 2334 Type: DiffTypeEdited, 2335 Name: "EphemeralDisk", 2336 Fields: []*FieldDiff{ 2337 { 2338 Type: DiffTypeEdited, 2339 Name: "Migrate", 2340 Old: "true", 2341 New: "false", 2342 }, 2343 { 2344 Type: DiffTypeEdited, 2345 Name: "SizeMB", 2346 Old: "150", 2347 New: "90", 2348 }, 2349 2350 { 2351 Type: DiffTypeEdited, 2352 Name: "Sticky", 2353 Old: "true", 2354 New: "false", 2355 }, 2356 }, 2357 }, 2358 }, 2359 }, 2360 }, 2361 { 2362 // EphemeralDisk edited with context 2363 Contextual: true, 2364 Old: &TaskGroup{ 2365 EphemeralDisk: &EphemeralDisk{ 2366 Migrate: false, 2367 Sticky: false, 2368 SizeMB: 100, 2369 }, 2370 }, 2371 New: &TaskGroup{ 2372 EphemeralDisk: &EphemeralDisk{ 2373 Migrate: true, 2374 Sticky: true, 2375 SizeMB: 90, 2376 }, 2377 }, 2378 Expected: &TaskGroupDiff{ 2379 Type: DiffTypeEdited, 2380 Objects: []*ObjectDiff{ 2381 { 2382 Type: DiffTypeEdited, 2383 Name: "EphemeralDisk", 2384 Fields: []*FieldDiff{ 2385 { 2386 Type: DiffTypeEdited, 2387 Name: "Migrate", 2388 Old: "false", 2389 New: "true", 2390 }, 2391 { 2392 Type: DiffTypeEdited, 2393 Name: "SizeMB", 2394 Old: "100", 2395 New: "90", 2396 }, 2397 { 2398 Type: DiffTypeEdited, 2399 Name: "Sticky", 2400 Old: "false", 2401 New: "true", 2402 }, 2403 }, 2404 }, 2405 }, 2406 }, 2407 }, 2408 { 2409 // Tasks edited 2410 Old: &TaskGroup{ 2411 Tasks: []*Task{ 2412 { 2413 Name: "foo", 2414 Driver: "docker", 2415 }, 2416 { 2417 Name: "bar", 2418 Driver: "docker", 2419 }, 2420 { 2421 Name: "baz", 2422 ShutdownDelay: 1 * time.Second, 2423 }, 2424 }, 2425 }, 2426 New: &TaskGroup{ 2427 Tasks: []*Task{ 2428 { 2429 Name: "bar", 2430 Driver: "docker", 2431 }, 2432 { 2433 Name: "bam", 2434 Driver: "docker", 2435 }, 2436 { 2437 Name: "baz", 2438 ShutdownDelay: 2 * time.Second, 2439 }, 2440 }, 2441 }, 2442 Expected: &TaskGroupDiff{ 2443 Type: DiffTypeEdited, 2444 Tasks: []*TaskDiff{ 2445 { 2446 Type: DiffTypeAdded, 2447 Name: "bam", 2448 Fields: []*FieldDiff{ 2449 { 2450 Type: DiffTypeAdded, 2451 Name: "Driver", 2452 Old: "", 2453 New: "docker", 2454 }, 2455 { 2456 Type: DiffTypeAdded, 2457 Name: "KillTimeout", 2458 Old: "", 2459 New: "0", 2460 }, 2461 { 2462 Type: DiffTypeAdded, 2463 Name: "Leader", 2464 Old: "", 2465 New: "false", 2466 }, 2467 { 2468 Type: DiffTypeAdded, 2469 Name: "ShutdownDelay", 2470 Old: "", 2471 New: "0", 2472 }, 2473 }, 2474 }, 2475 { 2476 Type: DiffTypeNone, 2477 Name: "bar", 2478 }, 2479 { 2480 Type: DiffTypeEdited, 2481 Name: "baz", 2482 Fields: []*FieldDiff{ 2483 { 2484 Type: DiffTypeEdited, 2485 Name: "ShutdownDelay", 2486 Old: "1000000000", 2487 New: "2000000000", 2488 }, 2489 }, 2490 }, 2491 { 2492 Type: DiffTypeDeleted, 2493 Name: "foo", 2494 Fields: []*FieldDiff{ 2495 { 2496 Type: DiffTypeDeleted, 2497 Name: "Driver", 2498 Old: "docker", 2499 New: "", 2500 }, 2501 { 2502 Type: DiffTypeDeleted, 2503 Name: "KillTimeout", 2504 Old: "0", 2505 New: "", 2506 }, 2507 { 2508 Type: DiffTypeDeleted, 2509 Name: "Leader", 2510 Old: "false", 2511 New: "", 2512 }, 2513 { 2514 Type: DiffTypeDeleted, 2515 Name: "ShutdownDelay", 2516 Old: "0", 2517 New: "", 2518 }, 2519 }, 2520 }, 2521 }, 2522 }, 2523 }, 2524 } 2525 2526 for i, c := range cases { 2527 actual, err := c.Old.Diff(c.New, c.Contextual) 2528 if c.Error && err == nil { 2529 t.Fatalf("case %d: expected errored", i+1) 2530 } else if err != nil { 2531 if !c.Error { 2532 t.Fatalf("case %d: errored %#v", i+1, err) 2533 } else { 2534 continue 2535 } 2536 } 2537 2538 if !reflect.DeepEqual(actual, c.Expected) { 2539 t.Fatalf("case %d: got:\n%#v\n want:\n%#v\n", 2540 i+1, actual, c.Expected) 2541 } 2542 } 2543 } 2544 2545 func TestTaskDiff(t *testing.T) { 2546 cases := []struct { 2547 Name string 2548 Old, New *Task 2549 Expected *TaskDiff 2550 Error bool 2551 Contextual bool 2552 }{ 2553 { 2554 Name: "Empty", 2555 Old: nil, 2556 New: nil, 2557 Expected: &TaskDiff{ 2558 Type: DiffTypeNone, 2559 }, 2560 }, 2561 { 2562 Name: "Primitive only that has different names", 2563 Old: &Task{ 2564 Name: "foo", 2565 Meta: map[string]string{ 2566 "foo": "bar", 2567 }, 2568 }, 2569 New: &Task{ 2570 Name: "bar", 2571 Meta: map[string]string{ 2572 "foo": "bar", 2573 }, 2574 }, 2575 Error: true, 2576 }, 2577 { 2578 Name: "Primitive only that is the same", 2579 Old: &Task{ 2580 Name: "foo", 2581 Driver: "exec", 2582 User: "foo", 2583 Env: map[string]string{ 2584 "FOO": "bar", 2585 }, 2586 Meta: map[string]string{ 2587 "foo": "bar", 2588 }, 2589 KillTimeout: 1 * time.Second, 2590 Leader: true, 2591 }, 2592 New: &Task{ 2593 Name: "foo", 2594 Driver: "exec", 2595 User: "foo", 2596 Env: map[string]string{ 2597 "FOO": "bar", 2598 }, 2599 Meta: map[string]string{ 2600 "foo": "bar", 2601 }, 2602 KillTimeout: 1 * time.Second, 2603 Leader: true, 2604 }, 2605 Expected: &TaskDiff{ 2606 Type: DiffTypeNone, 2607 Name: "foo", 2608 }, 2609 }, 2610 { 2611 Name: "Primitive only that has diffs", 2612 Old: &Task{ 2613 Name: "foo", 2614 Driver: "exec", 2615 User: "foo", 2616 Env: map[string]string{ 2617 "FOO": "bar", 2618 }, 2619 Meta: map[string]string{ 2620 "foo": "bar", 2621 }, 2622 KillTimeout: 1 * time.Second, 2623 Leader: true, 2624 }, 2625 New: &Task{ 2626 Name: "foo", 2627 Driver: "docker", 2628 User: "bar", 2629 Env: map[string]string{ 2630 "FOO": "baz", 2631 }, 2632 Meta: map[string]string{ 2633 "foo": "baz", 2634 }, 2635 KillTimeout: 2 * time.Second, 2636 Leader: false, 2637 }, 2638 Expected: &TaskDiff{ 2639 Type: DiffTypeEdited, 2640 Name: "foo", 2641 Fields: []*FieldDiff{ 2642 { 2643 Type: DiffTypeEdited, 2644 Name: "Driver", 2645 Old: "exec", 2646 New: "docker", 2647 }, 2648 { 2649 Type: DiffTypeEdited, 2650 Name: "Env[FOO]", 2651 Old: "bar", 2652 New: "baz", 2653 }, 2654 { 2655 Type: DiffTypeEdited, 2656 Name: "KillTimeout", 2657 Old: "1000000000", 2658 New: "2000000000", 2659 }, 2660 { 2661 Type: DiffTypeEdited, 2662 Name: "Leader", 2663 Old: "true", 2664 New: "false", 2665 }, 2666 { 2667 Type: DiffTypeEdited, 2668 Name: "Meta[foo]", 2669 Old: "bar", 2670 New: "baz", 2671 }, 2672 { 2673 Type: DiffTypeEdited, 2674 Name: "User", 2675 Old: "foo", 2676 New: "bar", 2677 }, 2678 }, 2679 }, 2680 }, 2681 { 2682 Name: "Map diff", 2683 Old: &Task{ 2684 Meta: map[string]string{ 2685 "foo": "foo", 2686 "bar": "bar", 2687 }, 2688 Env: map[string]string{ 2689 "foo": "foo", 2690 "bar": "bar", 2691 }, 2692 }, 2693 New: &Task{ 2694 Meta: map[string]string{ 2695 "bar": "bar", 2696 "baz": "baz", 2697 }, 2698 Env: map[string]string{ 2699 "bar": "bar", 2700 "baz": "baz", 2701 }, 2702 }, 2703 Expected: &TaskDiff{ 2704 Type: DiffTypeEdited, 2705 Fields: []*FieldDiff{ 2706 { 2707 Type: DiffTypeAdded, 2708 Name: "Env[baz]", 2709 Old: "", 2710 New: "baz", 2711 }, 2712 { 2713 Type: DiffTypeDeleted, 2714 Name: "Env[foo]", 2715 Old: "foo", 2716 New: "", 2717 }, 2718 { 2719 Type: DiffTypeAdded, 2720 Name: "Meta[baz]", 2721 Old: "", 2722 New: "baz", 2723 }, 2724 { 2725 Type: DiffTypeDeleted, 2726 Name: "Meta[foo]", 2727 Old: "foo", 2728 New: "", 2729 }, 2730 }, 2731 }, 2732 }, 2733 { 2734 Name: "Constraints edited", 2735 Old: &Task{ 2736 Constraints: []*Constraint{ 2737 { 2738 LTarget: "foo", 2739 RTarget: "foo", 2740 Operand: "foo", 2741 str: "foo", 2742 }, 2743 { 2744 LTarget: "bar", 2745 RTarget: "bar", 2746 Operand: "bar", 2747 str: "bar", 2748 }, 2749 }, 2750 }, 2751 New: &Task{ 2752 Constraints: []*Constraint{ 2753 { 2754 LTarget: "foo", 2755 RTarget: "foo", 2756 Operand: "foo", 2757 str: "foo", 2758 }, 2759 { 2760 LTarget: "baz", 2761 RTarget: "baz", 2762 Operand: "baz", 2763 str: "baz", 2764 }, 2765 }, 2766 }, 2767 Expected: &TaskDiff{ 2768 Type: DiffTypeEdited, 2769 Objects: []*ObjectDiff{ 2770 { 2771 Type: DiffTypeAdded, 2772 Name: "Constraint", 2773 Fields: []*FieldDiff{ 2774 { 2775 Type: DiffTypeAdded, 2776 Name: "LTarget", 2777 Old: "", 2778 New: "baz", 2779 }, 2780 { 2781 Type: DiffTypeAdded, 2782 Name: "Operand", 2783 Old: "", 2784 New: "baz", 2785 }, 2786 { 2787 Type: DiffTypeAdded, 2788 Name: "RTarget", 2789 Old: "", 2790 New: "baz", 2791 }, 2792 }, 2793 }, 2794 { 2795 Type: DiffTypeDeleted, 2796 Name: "Constraint", 2797 Fields: []*FieldDiff{ 2798 { 2799 Type: DiffTypeDeleted, 2800 Name: "LTarget", 2801 Old: "bar", 2802 New: "", 2803 }, 2804 { 2805 Type: DiffTypeDeleted, 2806 Name: "Operand", 2807 Old: "bar", 2808 New: "", 2809 }, 2810 { 2811 Type: DiffTypeDeleted, 2812 Name: "RTarget", 2813 Old: "bar", 2814 New: "", 2815 }, 2816 }, 2817 }, 2818 }, 2819 }, 2820 }, 2821 { 2822 Name: "Affinities edited", 2823 Old: &Task{ 2824 Affinities: []*Affinity{ 2825 { 2826 LTarget: "foo", 2827 RTarget: "foo", 2828 Operand: "foo", 2829 Weight: 20, 2830 str: "foo", 2831 }, 2832 { 2833 LTarget: "bar", 2834 RTarget: "bar", 2835 Operand: "bar", 2836 Weight: 20, 2837 str: "bar", 2838 }, 2839 }, 2840 }, 2841 New: &Task{ 2842 Affinities: []*Affinity{ 2843 { 2844 LTarget: "foo", 2845 RTarget: "foo", 2846 Operand: "foo", 2847 Weight: 20, 2848 str: "foo", 2849 }, 2850 { 2851 LTarget: "baz", 2852 RTarget: "baz", 2853 Operand: "baz", 2854 Weight: 20, 2855 str: "baz", 2856 }, 2857 }, 2858 }, 2859 Expected: &TaskDiff{ 2860 Type: DiffTypeEdited, 2861 Objects: []*ObjectDiff{ 2862 { 2863 Type: DiffTypeAdded, 2864 Name: "Affinity", 2865 Fields: []*FieldDiff{ 2866 { 2867 Type: DiffTypeAdded, 2868 Name: "LTarget", 2869 Old: "", 2870 New: "baz", 2871 }, 2872 { 2873 Type: DiffTypeAdded, 2874 Name: "Operand", 2875 Old: "", 2876 New: "baz", 2877 }, 2878 { 2879 Type: DiffTypeAdded, 2880 Name: "RTarget", 2881 Old: "", 2882 New: "baz", 2883 }, 2884 { 2885 Type: DiffTypeAdded, 2886 Name: "Weight", 2887 Old: "", 2888 New: "20", 2889 }, 2890 }, 2891 }, 2892 { 2893 Type: DiffTypeDeleted, 2894 Name: "Affinity", 2895 Fields: []*FieldDiff{ 2896 { 2897 Type: DiffTypeDeleted, 2898 Name: "LTarget", 2899 Old: "bar", 2900 New: "", 2901 }, 2902 { 2903 Type: DiffTypeDeleted, 2904 Name: "Operand", 2905 Old: "bar", 2906 New: "", 2907 }, 2908 { 2909 Type: DiffTypeDeleted, 2910 Name: "RTarget", 2911 Old: "bar", 2912 New: "", 2913 }, 2914 { 2915 Type: DiffTypeDeleted, 2916 Name: "Weight", 2917 Old: "20", 2918 New: "", 2919 }, 2920 }, 2921 }, 2922 }, 2923 }, 2924 }, 2925 { 2926 Name: "LogConfig added", 2927 Old: &Task{}, 2928 New: &Task{ 2929 LogConfig: &LogConfig{ 2930 MaxFiles: 1, 2931 MaxFileSizeMB: 10, 2932 }, 2933 }, 2934 Expected: &TaskDiff{ 2935 Type: DiffTypeEdited, 2936 Objects: []*ObjectDiff{ 2937 { 2938 Type: DiffTypeAdded, 2939 Name: "LogConfig", 2940 Fields: []*FieldDiff{ 2941 { 2942 Type: DiffTypeAdded, 2943 Name: "MaxFileSizeMB", 2944 Old: "", 2945 New: "10", 2946 }, 2947 { 2948 Type: DiffTypeAdded, 2949 Name: "MaxFiles", 2950 Old: "", 2951 New: "1", 2952 }, 2953 }, 2954 }, 2955 }, 2956 }, 2957 }, 2958 { 2959 Name: "LogConfig deleted", 2960 Old: &Task{ 2961 LogConfig: &LogConfig{ 2962 MaxFiles: 1, 2963 MaxFileSizeMB: 10, 2964 }, 2965 }, 2966 New: &Task{}, 2967 Expected: &TaskDiff{ 2968 Type: DiffTypeEdited, 2969 Objects: []*ObjectDiff{ 2970 { 2971 Type: DiffTypeDeleted, 2972 Name: "LogConfig", 2973 Fields: []*FieldDiff{ 2974 { 2975 Type: DiffTypeDeleted, 2976 Name: "MaxFileSizeMB", 2977 Old: "10", 2978 New: "", 2979 }, 2980 { 2981 Type: DiffTypeDeleted, 2982 Name: "MaxFiles", 2983 Old: "1", 2984 New: "", 2985 }, 2986 }, 2987 }, 2988 }, 2989 }, 2990 }, 2991 { 2992 Name: "LogConfig edited", 2993 Old: &Task{ 2994 LogConfig: &LogConfig{ 2995 MaxFiles: 1, 2996 MaxFileSizeMB: 10, 2997 }, 2998 }, 2999 New: &Task{ 3000 LogConfig: &LogConfig{ 3001 MaxFiles: 2, 3002 MaxFileSizeMB: 20, 3003 }, 3004 }, 3005 Expected: &TaskDiff{ 3006 Type: DiffTypeEdited, 3007 Objects: []*ObjectDiff{ 3008 { 3009 Type: DiffTypeEdited, 3010 Name: "LogConfig", 3011 Fields: []*FieldDiff{ 3012 { 3013 Type: DiffTypeEdited, 3014 Name: "MaxFileSizeMB", 3015 Old: "10", 3016 New: "20", 3017 }, 3018 { 3019 Type: DiffTypeEdited, 3020 Name: "MaxFiles", 3021 Old: "1", 3022 New: "2", 3023 }, 3024 }, 3025 }, 3026 }, 3027 }, 3028 }, 3029 { 3030 Name: "LogConfig edited with context", 3031 Contextual: true, 3032 Old: &Task{ 3033 LogConfig: &LogConfig{ 3034 MaxFiles: 1, 3035 MaxFileSizeMB: 10, 3036 }, 3037 }, 3038 New: &Task{ 3039 LogConfig: &LogConfig{ 3040 MaxFiles: 1, 3041 MaxFileSizeMB: 20, 3042 }, 3043 }, 3044 Expected: &TaskDiff{ 3045 Type: DiffTypeEdited, 3046 Objects: []*ObjectDiff{ 3047 { 3048 Type: DiffTypeEdited, 3049 Name: "LogConfig", 3050 Fields: []*FieldDiff{ 3051 { 3052 Type: DiffTypeEdited, 3053 Name: "MaxFileSizeMB", 3054 Old: "10", 3055 New: "20", 3056 }, 3057 { 3058 Type: DiffTypeNone, 3059 Name: "MaxFiles", 3060 Old: "1", 3061 New: "1", 3062 }, 3063 }, 3064 }, 3065 }, 3066 }, 3067 }, 3068 { 3069 Name: "Artifacts edited", 3070 Old: &Task{ 3071 Artifacts: []*TaskArtifact{ 3072 { 3073 GetterSource: "foo", 3074 GetterOptions: map[string]string{ 3075 "foo": "bar", 3076 }, 3077 RelativeDest: "foo", 3078 }, 3079 { 3080 GetterSource: "bar", 3081 GetterOptions: map[string]string{ 3082 "bar": "baz", 3083 }, 3084 GetterMode: "dir", 3085 RelativeDest: "bar", 3086 }, 3087 }, 3088 }, 3089 New: &Task{ 3090 Artifacts: []*TaskArtifact{ 3091 { 3092 GetterSource: "foo", 3093 GetterOptions: map[string]string{ 3094 "foo": "bar", 3095 }, 3096 RelativeDest: "foo", 3097 }, 3098 { 3099 GetterSource: "bam", 3100 GetterOptions: map[string]string{ 3101 "bam": "baz", 3102 }, 3103 GetterMode: "file", 3104 RelativeDest: "bam", 3105 }, 3106 }, 3107 }, 3108 Expected: &TaskDiff{ 3109 Type: DiffTypeEdited, 3110 Objects: []*ObjectDiff{ 3111 { 3112 Type: DiffTypeAdded, 3113 Name: "Artifact", 3114 Fields: []*FieldDiff{ 3115 { 3116 Type: DiffTypeAdded, 3117 Name: "GetterMode", 3118 Old: "", 3119 New: "file", 3120 }, 3121 { 3122 Type: DiffTypeAdded, 3123 Name: "GetterOptions[bam]", 3124 Old: "", 3125 New: "baz", 3126 }, 3127 { 3128 Type: DiffTypeAdded, 3129 Name: "GetterSource", 3130 Old: "", 3131 New: "bam", 3132 }, 3133 { 3134 Type: DiffTypeAdded, 3135 Name: "RelativeDest", 3136 Old: "", 3137 New: "bam", 3138 }, 3139 }, 3140 }, 3141 { 3142 Type: DiffTypeDeleted, 3143 Name: "Artifact", 3144 Fields: []*FieldDiff{ 3145 { 3146 Type: DiffTypeDeleted, 3147 Name: "GetterMode", 3148 Old: "dir", 3149 New: "", 3150 }, 3151 { 3152 Type: DiffTypeDeleted, 3153 Name: "GetterOptions[bar]", 3154 Old: "baz", 3155 New: "", 3156 }, 3157 { 3158 Type: DiffTypeDeleted, 3159 Name: "GetterSource", 3160 Old: "bar", 3161 New: "", 3162 }, 3163 { 3164 Type: DiffTypeDeleted, 3165 Name: "RelativeDest", 3166 Old: "bar", 3167 New: "", 3168 }, 3169 }, 3170 }, 3171 }, 3172 }, 3173 }, 3174 { 3175 Name: "Resources edited (no networks)", 3176 Old: &Task{ 3177 Resources: &Resources{ 3178 CPU: 100, 3179 MemoryMB: 100, 3180 DiskMB: 100, 3181 IOPS: 100, 3182 }, 3183 }, 3184 New: &Task{ 3185 Resources: &Resources{ 3186 CPU: 200, 3187 MemoryMB: 200, 3188 DiskMB: 200, 3189 IOPS: 200, 3190 }, 3191 }, 3192 Expected: &TaskDiff{ 3193 Type: DiffTypeEdited, 3194 Objects: []*ObjectDiff{ 3195 { 3196 Type: DiffTypeEdited, 3197 Name: "Resources", 3198 Fields: []*FieldDiff{ 3199 { 3200 Type: DiffTypeEdited, 3201 Name: "CPU", 3202 Old: "100", 3203 New: "200", 3204 }, 3205 { 3206 Type: DiffTypeEdited, 3207 Name: "DiskMB", 3208 Old: "100", 3209 New: "200", 3210 }, 3211 { 3212 Type: DiffTypeEdited, 3213 Name: "IOPS", 3214 Old: "100", 3215 New: "200", 3216 }, 3217 { 3218 Type: DiffTypeEdited, 3219 Name: "MemoryMB", 3220 Old: "100", 3221 New: "200", 3222 }, 3223 }, 3224 }, 3225 }, 3226 }, 3227 }, 3228 { 3229 Name: "Resources edited (no networks) with context", 3230 Contextual: true, 3231 Old: &Task{ 3232 Resources: &Resources{ 3233 CPU: 100, 3234 MemoryMB: 100, 3235 DiskMB: 100, 3236 IOPS: 100, 3237 }, 3238 }, 3239 New: &Task{ 3240 Resources: &Resources{ 3241 CPU: 200, 3242 MemoryMB: 100, 3243 DiskMB: 200, 3244 IOPS: 100, 3245 }, 3246 }, 3247 Expected: &TaskDiff{ 3248 Type: DiffTypeEdited, 3249 Objects: []*ObjectDiff{ 3250 { 3251 Type: DiffTypeEdited, 3252 Name: "Resources", 3253 Fields: []*FieldDiff{ 3254 { 3255 Type: DiffTypeEdited, 3256 Name: "CPU", 3257 Old: "100", 3258 New: "200", 3259 }, 3260 { 3261 Type: DiffTypeEdited, 3262 Name: "DiskMB", 3263 Old: "100", 3264 New: "200", 3265 }, 3266 { 3267 Type: DiffTypeNone, 3268 Name: "IOPS", 3269 Old: "100", 3270 New: "100", 3271 }, 3272 { 3273 Type: DiffTypeNone, 3274 Name: "MemoryMB", 3275 Old: "100", 3276 New: "100", 3277 }, 3278 }, 3279 }, 3280 }, 3281 }, 3282 }, 3283 { 3284 Name: "Network Resources edited", 3285 Old: &Task{ 3286 Resources: &Resources{ 3287 Networks: []*NetworkResource{ 3288 { 3289 Device: "foo", 3290 CIDR: "foo", 3291 IP: "foo", 3292 MBits: 100, 3293 ReservedPorts: []Port{ 3294 { 3295 Label: "foo", 3296 Value: 80, 3297 }, 3298 }, 3299 DynamicPorts: []Port{ 3300 { 3301 Label: "bar", 3302 }, 3303 }, 3304 }, 3305 }, 3306 }, 3307 }, 3308 New: &Task{ 3309 Resources: &Resources{ 3310 Networks: []*NetworkResource{ 3311 { 3312 Device: "bar", 3313 CIDR: "bar", 3314 IP: "bar", 3315 MBits: 200, 3316 ReservedPorts: []Port{ 3317 { 3318 Label: "foo", 3319 Value: 81, 3320 }, 3321 }, 3322 DynamicPorts: []Port{ 3323 { 3324 Label: "baz", 3325 }, 3326 }, 3327 }, 3328 }, 3329 }, 3330 }, 3331 Expected: &TaskDiff{ 3332 Type: DiffTypeEdited, 3333 Objects: []*ObjectDiff{ 3334 { 3335 Type: DiffTypeEdited, 3336 Name: "Resources", 3337 Objects: []*ObjectDiff{ 3338 { 3339 Type: DiffTypeAdded, 3340 Name: "Network", 3341 Fields: []*FieldDiff{ 3342 { 3343 Type: DiffTypeAdded, 3344 Name: "MBits", 3345 Old: "", 3346 New: "200", 3347 }, 3348 }, 3349 Objects: []*ObjectDiff{ 3350 { 3351 Type: DiffTypeAdded, 3352 Name: "Static Port", 3353 Fields: []*FieldDiff{ 3354 { 3355 Type: DiffTypeAdded, 3356 Name: "Label", 3357 Old: "", 3358 New: "foo", 3359 }, 3360 { 3361 Type: DiffTypeAdded, 3362 Name: "Value", 3363 Old: "", 3364 New: "81", 3365 }, 3366 }, 3367 }, 3368 { 3369 Type: DiffTypeAdded, 3370 Name: "Dynamic Port", 3371 Fields: []*FieldDiff{ 3372 { 3373 Type: DiffTypeAdded, 3374 Name: "Label", 3375 Old: "", 3376 New: "baz", 3377 }, 3378 }, 3379 }, 3380 }, 3381 }, 3382 { 3383 Type: DiffTypeDeleted, 3384 Name: "Network", 3385 Fields: []*FieldDiff{ 3386 { 3387 Type: DiffTypeDeleted, 3388 Name: "MBits", 3389 Old: "100", 3390 New: "", 3391 }, 3392 }, 3393 Objects: []*ObjectDiff{ 3394 { 3395 Type: DiffTypeDeleted, 3396 Name: "Static Port", 3397 Fields: []*FieldDiff{ 3398 { 3399 Type: DiffTypeDeleted, 3400 Name: "Label", 3401 Old: "foo", 3402 New: "", 3403 }, 3404 { 3405 Type: DiffTypeDeleted, 3406 Name: "Value", 3407 Old: "80", 3408 New: "", 3409 }, 3410 }, 3411 }, 3412 { 3413 Type: DiffTypeDeleted, 3414 Name: "Dynamic Port", 3415 Fields: []*FieldDiff{ 3416 { 3417 Type: DiffTypeDeleted, 3418 Name: "Label", 3419 Old: "bar", 3420 New: "", 3421 }, 3422 }, 3423 }, 3424 }, 3425 }, 3426 }, 3427 }, 3428 }, 3429 }, 3430 }, 3431 { 3432 Name: "Config same", 3433 Old: &Task{ 3434 Config: map[string]interface{}{ 3435 "foo": 1, 3436 "bar": "bar", 3437 "bam": []string{"a", "b"}, 3438 "baz": map[string]int{ 3439 "a": 1, 3440 "b": 2, 3441 }, 3442 "boom": &Port{ 3443 Label: "boom_port", 3444 }, 3445 }, 3446 }, 3447 New: &Task{ 3448 Config: map[string]interface{}{ 3449 "foo": 1, 3450 "bar": "bar", 3451 "bam": []string{"a", "b"}, 3452 "baz": map[string]int{ 3453 "a": 1, 3454 "b": 2, 3455 }, 3456 "boom": &Port{ 3457 Label: "boom_port", 3458 }, 3459 }, 3460 }, 3461 Expected: &TaskDiff{ 3462 Type: DiffTypeNone, 3463 }, 3464 }, 3465 { 3466 Name: "Config edited", 3467 Old: &Task{ 3468 Config: map[string]interface{}{ 3469 "foo": 1, 3470 "bar": "baz", 3471 "bam": []string{"a", "b"}, 3472 "baz": map[string]int{ 3473 "a": 1, 3474 "b": 2, 3475 }, 3476 "boom": &Port{ 3477 Label: "boom_port", 3478 }, 3479 }, 3480 }, 3481 New: &Task{ 3482 Config: map[string]interface{}{ 3483 "foo": 2, 3484 "bar": "baz", 3485 "bam": []string{"a", "c", "d"}, 3486 "baz": map[string]int{ 3487 "b": 3, 3488 "c": 4, 3489 }, 3490 "boom": &Port{ 3491 Label: "boom_port2", 3492 }, 3493 }, 3494 }, 3495 Expected: &TaskDiff{ 3496 Type: DiffTypeEdited, 3497 Objects: []*ObjectDiff{ 3498 { 3499 Type: DiffTypeEdited, 3500 Name: "Config", 3501 Fields: []*FieldDiff{ 3502 { 3503 Type: DiffTypeEdited, 3504 Name: "bam[1]", 3505 Old: "b", 3506 New: "c", 3507 }, 3508 { 3509 Type: DiffTypeAdded, 3510 Name: "bam[2]", 3511 Old: "", 3512 New: "d", 3513 }, 3514 { 3515 Type: DiffTypeDeleted, 3516 Name: "baz[a]", 3517 Old: "1", 3518 New: "", 3519 }, 3520 { 3521 Type: DiffTypeEdited, 3522 Name: "baz[b]", 3523 Old: "2", 3524 New: "3", 3525 }, 3526 { 3527 Type: DiffTypeAdded, 3528 Name: "baz[c]", 3529 Old: "", 3530 New: "4", 3531 }, 3532 { 3533 Type: DiffTypeEdited, 3534 Name: "boom.Label", 3535 Old: "boom_port", 3536 New: "boom_port2", 3537 }, 3538 { 3539 Type: DiffTypeEdited, 3540 Name: "foo", 3541 Old: "1", 3542 New: "2", 3543 }, 3544 }, 3545 }, 3546 }, 3547 }, 3548 }, 3549 { 3550 Name: "Config edited with context", 3551 Contextual: true, 3552 Old: &Task{ 3553 Config: map[string]interface{}{ 3554 "foo": 1, 3555 "bar": "baz", 3556 "bam": []string{"a", "b"}, 3557 "baz": map[string]int{ 3558 "a": 1, 3559 "b": 2, 3560 }, 3561 "boom": &Port{ 3562 Label: "boom_port", 3563 }, 3564 }, 3565 }, 3566 New: &Task{ 3567 Config: map[string]interface{}{ 3568 "foo": 2, 3569 "bar": "baz", 3570 "bam": []string{"a", "c", "d"}, 3571 "baz": map[string]int{ 3572 "a": 1, 3573 "b": 2, 3574 }, 3575 "boom": &Port{ 3576 Label: "boom_port", 3577 }, 3578 }, 3579 }, 3580 Expected: &TaskDiff{ 3581 Type: DiffTypeEdited, 3582 Objects: []*ObjectDiff{ 3583 { 3584 Type: DiffTypeEdited, 3585 Name: "Config", 3586 Fields: []*FieldDiff{ 3587 { 3588 Type: DiffTypeNone, 3589 Name: "bam[0]", 3590 Old: "a", 3591 New: "a", 3592 }, 3593 { 3594 Type: DiffTypeEdited, 3595 Name: "bam[1]", 3596 Old: "b", 3597 New: "c", 3598 }, 3599 { 3600 Type: DiffTypeAdded, 3601 Name: "bam[2]", 3602 Old: "", 3603 New: "d", 3604 }, 3605 { 3606 Type: DiffTypeNone, 3607 Name: "bar", 3608 Old: "baz", 3609 New: "baz", 3610 }, 3611 { 3612 Type: DiffTypeNone, 3613 Name: "baz[a]", 3614 Old: "1", 3615 New: "1", 3616 }, 3617 { 3618 Type: DiffTypeNone, 3619 Name: "baz[b]", 3620 Old: "2", 3621 New: "2", 3622 }, 3623 { 3624 Type: DiffTypeNone, 3625 Name: "boom.Label", 3626 Old: "boom_port", 3627 New: "boom_port", 3628 }, 3629 { 3630 Type: DiffTypeNone, 3631 Name: "boom.Value", 3632 Old: "0", 3633 New: "0", 3634 }, 3635 { 3636 Type: DiffTypeEdited, 3637 Name: "foo", 3638 Old: "1", 3639 New: "2", 3640 }, 3641 }, 3642 }, 3643 }, 3644 }, 3645 }, 3646 { 3647 Name: "Services edited (no checks)", 3648 Old: &Task{ 3649 Services: []*Service{ 3650 { 3651 Name: "foo", 3652 PortLabel: "foo", 3653 }, 3654 { 3655 Name: "bar", 3656 PortLabel: "bar", 3657 }, 3658 { 3659 Name: "baz", 3660 PortLabel: "baz", 3661 }, 3662 }, 3663 }, 3664 New: &Task{ 3665 Services: []*Service{ 3666 { 3667 Name: "bar", 3668 PortLabel: "bar", 3669 }, 3670 { 3671 Name: "baz", 3672 PortLabel: "baz2", 3673 }, 3674 { 3675 Name: "bam", 3676 PortLabel: "bam", 3677 }, 3678 }, 3679 }, 3680 Expected: &TaskDiff{ 3681 Type: DiffTypeEdited, 3682 Objects: []*ObjectDiff{ 3683 { 3684 Type: DiffTypeEdited, 3685 Name: "Service", 3686 Fields: []*FieldDiff{ 3687 { 3688 Type: DiffTypeEdited, 3689 Name: "PortLabel", 3690 Old: "baz", 3691 New: "baz2", 3692 }, 3693 }, 3694 }, 3695 { 3696 Type: DiffTypeAdded, 3697 Name: "Service", 3698 Fields: []*FieldDiff{ 3699 { 3700 Type: DiffTypeAdded, 3701 Name: "Name", 3702 Old: "", 3703 New: "bam", 3704 }, 3705 { 3706 Type: DiffTypeAdded, 3707 Name: "PortLabel", 3708 Old: "", 3709 New: "bam", 3710 }, 3711 }, 3712 }, 3713 { 3714 Type: DiffTypeDeleted, 3715 Name: "Service", 3716 Fields: []*FieldDiff{ 3717 { 3718 Type: DiffTypeDeleted, 3719 Name: "Name", 3720 Old: "foo", 3721 New: "", 3722 }, 3723 { 3724 Type: DiffTypeDeleted, 3725 Name: "PortLabel", 3726 Old: "foo", 3727 New: "", 3728 }, 3729 }, 3730 }, 3731 }, 3732 }, 3733 }, 3734 { 3735 Name: "Services edited (no checks) with context", 3736 Contextual: true, 3737 Old: &Task{ 3738 Services: []*Service{ 3739 { 3740 Name: "foo", 3741 PortLabel: "foo", 3742 }, 3743 }, 3744 }, 3745 New: &Task{ 3746 Services: []*Service{ 3747 { 3748 Name: "foo", 3749 PortLabel: "bar", 3750 AddressMode: "driver", 3751 }, 3752 }, 3753 }, 3754 Expected: &TaskDiff{ 3755 Type: DiffTypeEdited, 3756 Objects: []*ObjectDiff{ 3757 { 3758 Type: DiffTypeEdited, 3759 Name: "Service", 3760 Fields: []*FieldDiff{ 3761 { 3762 Type: DiffTypeAdded, 3763 Name: "AddressMode", 3764 New: "driver", 3765 }, 3766 { 3767 Type: DiffTypeNone, 3768 Name: "Name", 3769 Old: "foo", 3770 New: "foo", 3771 }, 3772 { 3773 Type: DiffTypeEdited, 3774 Name: "PortLabel", 3775 Old: "foo", 3776 New: "bar", 3777 }, 3778 }, 3779 }, 3780 }, 3781 }, 3782 }, 3783 { 3784 Name: "Services tags edited (no checks) with context", 3785 Contextual: true, 3786 Old: &Task{ 3787 Services: []*Service{ 3788 { 3789 Tags: []string{"foo", "bar"}, 3790 CanaryTags: []string{"foo", "bar"}, 3791 }, 3792 }, 3793 }, 3794 New: &Task{ 3795 Services: []*Service{ 3796 { 3797 Tags: []string{"bar", "bam"}, 3798 CanaryTags: []string{"bar", "bam"}, 3799 }, 3800 }, 3801 }, 3802 Expected: &TaskDiff{ 3803 Type: DiffTypeEdited, 3804 Objects: []*ObjectDiff{ 3805 { 3806 Type: DiffTypeEdited, 3807 Name: "Service", 3808 Objects: []*ObjectDiff{ 3809 { 3810 Type: DiffTypeEdited, 3811 Name: "CanaryTags", 3812 Fields: []*FieldDiff{ 3813 { 3814 Type: DiffTypeAdded, 3815 Name: "CanaryTags", 3816 Old: "", 3817 New: "bam", 3818 }, 3819 { 3820 Type: DiffTypeNone, 3821 Name: "CanaryTags", 3822 Old: "bar", 3823 New: "bar", 3824 }, 3825 { 3826 Type: DiffTypeDeleted, 3827 Name: "CanaryTags", 3828 Old: "foo", 3829 New: "", 3830 }, 3831 }, 3832 }, 3833 { 3834 Type: DiffTypeEdited, 3835 Name: "Tags", 3836 Fields: []*FieldDiff{ 3837 { 3838 Type: DiffTypeAdded, 3839 Name: "Tags", 3840 Old: "", 3841 New: "bam", 3842 }, 3843 { 3844 Type: DiffTypeNone, 3845 Name: "Tags", 3846 Old: "bar", 3847 New: "bar", 3848 }, 3849 { 3850 Type: DiffTypeDeleted, 3851 Name: "Tags", 3852 Old: "foo", 3853 New: "", 3854 }, 3855 }, 3856 }, 3857 }, 3858 Fields: []*FieldDiff{ 3859 { 3860 Type: DiffTypeNone, 3861 Name: "AddressMode", 3862 }, 3863 { 3864 Type: DiffTypeNone, 3865 Name: "Name", 3866 }, 3867 { 3868 Type: DiffTypeNone, 3869 Name: "PortLabel", 3870 }, 3871 }, 3872 }, 3873 }, 3874 }, 3875 }, 3876 { 3877 Name: "Service Checks edited", 3878 Old: &Task{ 3879 Services: []*Service{ 3880 { 3881 Name: "foo", 3882 Checks: []*ServiceCheck{ 3883 { 3884 Name: "foo", 3885 Type: "http", 3886 Command: "foo", 3887 Args: []string{"foo"}, 3888 Path: "foo", 3889 Protocol: "http", 3890 Interval: 1 * time.Second, 3891 Timeout: 1 * time.Second, 3892 Header: map[string][]string{ 3893 "Foo": {"bar"}, 3894 }, 3895 }, 3896 { 3897 Name: "bar", 3898 Type: "http", 3899 Command: "foo", 3900 Args: []string{"foo"}, 3901 Path: "foo", 3902 Protocol: "http", 3903 Interval: 1 * time.Second, 3904 Timeout: 1 * time.Second, 3905 }, 3906 { 3907 Name: "baz", 3908 Type: "http", 3909 Command: "foo", 3910 Args: []string{"foo"}, 3911 Path: "foo", 3912 Protocol: "http", 3913 Interval: 1 * time.Second, 3914 Timeout: 1 * time.Second, 3915 }, 3916 }, 3917 }, 3918 }, 3919 }, 3920 New: &Task{ 3921 Services: []*Service{ 3922 { 3923 Name: "foo", 3924 Checks: []*ServiceCheck{ 3925 { 3926 Name: "bar", 3927 Type: "http", 3928 Command: "foo", 3929 Args: []string{"foo"}, 3930 Path: "foo", 3931 Protocol: "http", 3932 Interval: 1 * time.Second, 3933 Timeout: 1 * time.Second, 3934 }, 3935 { 3936 Name: "baz", 3937 Type: "tcp", 3938 Command: "foo", 3939 Args: []string{"foo"}, 3940 Path: "foo", 3941 Protocol: "http", 3942 Interval: 1 * time.Second, 3943 Timeout: 1 * time.Second, 3944 Header: map[string][]string{ 3945 "Eggs": {"spam"}, 3946 }, 3947 }, 3948 { 3949 Name: "bam", 3950 Type: "http", 3951 Command: "foo", 3952 Args: []string{"foo"}, 3953 Path: "foo", 3954 Protocol: "http", 3955 Interval: 1 * time.Second, 3956 Timeout: 1 * time.Second, 3957 }, 3958 }, 3959 }, 3960 }, 3961 }, 3962 Expected: &TaskDiff{ 3963 Type: DiffTypeEdited, 3964 Objects: []*ObjectDiff{ 3965 { 3966 Type: DiffTypeEdited, 3967 Name: "Service", 3968 Objects: []*ObjectDiff{ 3969 { 3970 Type: DiffTypeEdited, 3971 Name: "Check", 3972 Fields: []*FieldDiff{ 3973 { 3974 Type: DiffTypeEdited, 3975 Name: "Type", 3976 Old: "http", 3977 New: "tcp", 3978 }, 3979 }, 3980 Objects: []*ObjectDiff{ 3981 { 3982 Type: DiffTypeAdded, 3983 Name: "Header", 3984 Fields: []*FieldDiff{ 3985 { 3986 Type: DiffTypeAdded, 3987 Name: "Eggs[0]", 3988 Old: "", 3989 New: "spam", 3990 }, 3991 }, 3992 }, 3993 }, 3994 }, 3995 { 3996 Type: DiffTypeAdded, 3997 Name: "Check", 3998 Fields: []*FieldDiff{ 3999 { 4000 Type: DiffTypeAdded, 4001 Name: "Command", 4002 Old: "", 4003 New: "foo", 4004 }, 4005 { 4006 Type: DiffTypeAdded, 4007 Name: "GRPCUseTLS", 4008 Old: "", 4009 New: "false", 4010 }, 4011 { 4012 Type: DiffTypeAdded, 4013 Name: "Interval", 4014 Old: "", 4015 New: "1000000000", 4016 }, 4017 { 4018 Type: DiffTypeAdded, 4019 Name: "Name", 4020 Old: "", 4021 New: "bam", 4022 }, 4023 { 4024 Type: DiffTypeAdded, 4025 Name: "Path", 4026 Old: "", 4027 New: "foo", 4028 }, 4029 { 4030 Type: DiffTypeAdded, 4031 Name: "Protocol", 4032 Old: "", 4033 New: "http", 4034 }, 4035 { 4036 Type: DiffTypeAdded, 4037 Name: "TLSSkipVerify", 4038 Old: "", 4039 New: "false", 4040 }, 4041 { 4042 Type: DiffTypeAdded, 4043 Name: "Timeout", 4044 Old: "", 4045 New: "1000000000", 4046 }, 4047 { 4048 Type: DiffTypeAdded, 4049 Name: "Type", 4050 Old: "", 4051 New: "http", 4052 }, 4053 }, 4054 }, 4055 { 4056 Type: DiffTypeDeleted, 4057 Name: "Check", 4058 Fields: []*FieldDiff{ 4059 { 4060 Type: DiffTypeDeleted, 4061 Name: "Command", 4062 Old: "foo", 4063 New: "", 4064 }, 4065 { 4066 Type: DiffTypeDeleted, 4067 Name: "GRPCUseTLS", 4068 Old: "false", 4069 New: "", 4070 }, 4071 { 4072 Type: DiffTypeDeleted, 4073 Name: "Interval", 4074 Old: "1000000000", 4075 New: "", 4076 }, 4077 { 4078 Type: DiffTypeDeleted, 4079 Name: "Name", 4080 Old: "foo", 4081 New: "", 4082 }, 4083 { 4084 Type: DiffTypeDeleted, 4085 Name: "Path", 4086 Old: "foo", 4087 New: "", 4088 }, 4089 { 4090 Type: DiffTypeDeleted, 4091 Name: "Protocol", 4092 Old: "http", 4093 New: "", 4094 }, 4095 { 4096 Type: DiffTypeDeleted, 4097 Name: "TLSSkipVerify", 4098 Old: "false", 4099 New: "", 4100 }, 4101 { 4102 Type: DiffTypeDeleted, 4103 Name: "Timeout", 4104 Old: "1000000000", 4105 New: "", 4106 }, 4107 { 4108 Type: DiffTypeDeleted, 4109 Name: "Type", 4110 Old: "http", 4111 New: "", 4112 }, 4113 }, 4114 Objects: []*ObjectDiff{ 4115 { 4116 Type: DiffTypeDeleted, 4117 Name: "Header", 4118 Fields: []*FieldDiff{ 4119 { 4120 Type: DiffTypeDeleted, 4121 Name: "Foo[0]", 4122 Old: "bar", 4123 }, 4124 }, 4125 }, 4126 }, 4127 }, 4128 }, 4129 }, 4130 }, 4131 }, 4132 }, 4133 { 4134 Name: "Service Checks edited with context", 4135 Contextual: true, 4136 Old: &Task{ 4137 Services: []*Service{ 4138 { 4139 Name: "foo", 4140 Checks: []*ServiceCheck{ 4141 { 4142 Name: "foo", 4143 Type: "http", 4144 Command: "foo", 4145 Args: []string{"foo"}, 4146 Path: "foo", 4147 Protocol: "http", 4148 Interval: 1 * time.Second, 4149 Timeout: 1 * time.Second, 4150 InitialStatus: "critical", 4151 Header: map[string][]string{ 4152 "Foo": {"bar"}, 4153 }, 4154 }, 4155 }, 4156 }, 4157 }, 4158 }, 4159 New: &Task{ 4160 Services: []*Service{ 4161 { 4162 Name: "foo", 4163 Checks: []*ServiceCheck{ 4164 { 4165 Name: "foo", 4166 Type: "tcp", 4167 Command: "foo", 4168 Args: []string{"foo"}, 4169 Path: "foo", 4170 Protocol: "http", 4171 Interval: 1 * time.Second, 4172 Timeout: 1 * time.Second, 4173 InitialStatus: "passing", 4174 Method: "POST", 4175 Header: map[string][]string{ 4176 "Foo": {"bar", "baz"}, 4177 "Eggs": {"spam"}, 4178 }, 4179 }, 4180 }, 4181 }, 4182 }, 4183 }, 4184 Expected: &TaskDiff{ 4185 Type: DiffTypeEdited, 4186 Objects: []*ObjectDiff{ 4187 { 4188 Type: DiffTypeEdited, 4189 Name: "Service", 4190 Fields: []*FieldDiff{ 4191 { 4192 Type: DiffTypeNone, 4193 Name: "AddressMode", 4194 Old: "", 4195 New: "", 4196 }, 4197 { 4198 Type: DiffTypeNone, 4199 Name: "Name", 4200 Old: "foo", 4201 New: "foo", 4202 }, 4203 { 4204 Type: DiffTypeNone, 4205 Name: "PortLabel", 4206 Old: "", 4207 New: "", 4208 }, 4209 }, 4210 Objects: []*ObjectDiff{ 4211 { 4212 Type: DiffTypeEdited, 4213 Name: "Check", 4214 Fields: []*FieldDiff{ 4215 { 4216 Type: DiffTypeNone, 4217 Name: "AddressMode", 4218 Old: "", 4219 New: "", 4220 }, 4221 { 4222 Type: DiffTypeNone, 4223 Name: "Command", 4224 Old: "foo", 4225 New: "foo", 4226 }, 4227 { 4228 Type: DiffTypeNone, 4229 Name: "GRPCService", 4230 Old: "", 4231 New: "", 4232 }, 4233 { 4234 Type: DiffTypeNone, 4235 Name: "GRPCUseTLS", 4236 Old: "false", 4237 New: "false", 4238 }, 4239 { 4240 Type: DiffTypeEdited, 4241 Name: "InitialStatus", 4242 Old: "critical", 4243 New: "passing", 4244 }, 4245 { 4246 Type: DiffTypeNone, 4247 Name: "Interval", 4248 Old: "1000000000", 4249 New: "1000000000", 4250 }, 4251 { 4252 Type: DiffTypeAdded, 4253 Name: "Method", 4254 Old: "", 4255 New: "POST", 4256 }, 4257 { 4258 Type: DiffTypeNone, 4259 Name: "Name", 4260 Old: "foo", 4261 New: "foo", 4262 }, 4263 { 4264 Type: DiffTypeNone, 4265 Name: "Path", 4266 Old: "foo", 4267 New: "foo", 4268 }, 4269 { 4270 Type: DiffTypeNone, 4271 Name: "PortLabel", 4272 Old: "", 4273 New: "", 4274 }, 4275 { 4276 Type: DiffTypeNone, 4277 Name: "Protocol", 4278 Old: "http", 4279 New: "http", 4280 }, 4281 { 4282 Type: DiffTypeNone, 4283 Name: "TLSSkipVerify", 4284 Old: "false", 4285 New: "false", 4286 }, 4287 { 4288 Type: DiffTypeNone, 4289 Name: "Timeout", 4290 Old: "1000000000", 4291 New: "1000000000", 4292 }, 4293 { 4294 Type: DiffTypeEdited, 4295 Name: "Type", 4296 Old: "http", 4297 New: "tcp", 4298 }, 4299 }, 4300 Objects: []*ObjectDiff{ 4301 { 4302 Type: DiffTypeEdited, 4303 Name: "Header", 4304 Fields: []*FieldDiff{ 4305 { 4306 Type: DiffTypeAdded, 4307 Name: "Eggs[0]", 4308 Old: "", 4309 New: "spam", 4310 }, 4311 { 4312 Type: DiffTypeNone, 4313 Name: "Foo[0]", 4314 Old: "bar", 4315 New: "bar", 4316 }, 4317 { 4318 Type: DiffTypeAdded, 4319 Name: "Foo[1]", 4320 Old: "", 4321 New: "baz", 4322 }, 4323 }, 4324 }, 4325 }, 4326 }, 4327 }, 4328 }, 4329 }, 4330 }, 4331 }, 4332 { 4333 Name: "CheckRestart edited", 4334 Old: &Task{ 4335 Services: []*Service{ 4336 { 4337 Name: "foo", 4338 Checks: []*ServiceCheck{ 4339 { 4340 Name: "foo", 4341 Type: "http", 4342 Command: "foo", 4343 Args: []string{"foo"}, 4344 Path: "foo", 4345 Protocol: "http", 4346 Interval: 1 * time.Second, 4347 Timeout: 1 * time.Second, 4348 }, 4349 { 4350 Name: "bar", 4351 Type: "http", 4352 Command: "foo", 4353 Args: []string{"foo"}, 4354 Path: "foo", 4355 Protocol: "http", 4356 Interval: 1 * time.Second, 4357 Timeout: 1 * time.Second, 4358 CheckRestart: &CheckRestart{ 4359 Limit: 2, 4360 Grace: 2 * time.Second, 4361 }, 4362 }, 4363 { 4364 Name: "baz", 4365 Type: "http", 4366 Command: "foo", 4367 Args: []string{"foo"}, 4368 Path: "foo", 4369 Protocol: "http", 4370 Interval: 1 * time.Second, 4371 Timeout: 1 * time.Second, 4372 CheckRestart: &CheckRestart{ 4373 Limit: 3, 4374 Grace: 3 * time.Second, 4375 }, 4376 }, 4377 }, 4378 }, 4379 }, 4380 }, 4381 New: &Task{ 4382 Services: []*Service{ 4383 { 4384 Name: "foo", 4385 Checks: []*ServiceCheck{ 4386 { 4387 Name: "foo", 4388 Type: "http", 4389 Command: "foo", 4390 Args: []string{"foo"}, 4391 Path: "foo", 4392 Protocol: "http", 4393 Interval: 1 * time.Second, 4394 Timeout: 1 * time.Second, 4395 CheckRestart: &CheckRestart{ 4396 Limit: 1, 4397 Grace: 1 * time.Second, 4398 }, 4399 }, 4400 { 4401 Name: "bar", 4402 Type: "http", 4403 Command: "foo", 4404 Args: []string{"foo"}, 4405 Path: "foo", 4406 Protocol: "http", 4407 Interval: 1 * time.Second, 4408 Timeout: 1 * time.Second, 4409 }, 4410 { 4411 Name: "baz", 4412 Type: "http", 4413 Command: "foo", 4414 Args: []string{"foo"}, 4415 Path: "foo", 4416 Protocol: "http", 4417 Interval: 1 * time.Second, 4418 Timeout: 1 * time.Second, 4419 CheckRestart: &CheckRestart{ 4420 Limit: 4, 4421 Grace: 4 * time.Second, 4422 }, 4423 }, 4424 }, 4425 }, 4426 }, 4427 }, 4428 Expected: &TaskDiff{ 4429 Type: DiffTypeEdited, 4430 Objects: []*ObjectDiff{ 4431 { 4432 Type: DiffTypeEdited, 4433 Name: "Service", 4434 Objects: []*ObjectDiff{ 4435 { 4436 Type: DiffTypeEdited, 4437 Name: "Check", 4438 Objects: []*ObjectDiff{ 4439 { 4440 Type: DiffTypeEdited, 4441 Name: "CheckRestart", 4442 Fields: []*FieldDiff{ 4443 { 4444 Type: DiffTypeEdited, 4445 Name: "Grace", 4446 Old: "3000000000", 4447 New: "4000000000", 4448 }, 4449 { 4450 Type: DiffTypeEdited, 4451 Name: "Limit", 4452 Old: "3", 4453 New: "4", 4454 }, 4455 }, 4456 }, 4457 }, 4458 }, 4459 { 4460 Type: DiffTypeEdited, 4461 Name: "Check", 4462 Objects: []*ObjectDiff{ 4463 { 4464 Type: DiffTypeAdded, 4465 Name: "CheckRestart", 4466 Fields: []*FieldDiff{ 4467 { 4468 Type: DiffTypeAdded, 4469 Name: "Grace", 4470 New: "1000000000", 4471 }, 4472 { 4473 Type: DiffTypeAdded, 4474 Name: "IgnoreWarnings", 4475 New: "false", 4476 }, 4477 { 4478 Type: DiffTypeAdded, 4479 Name: "Limit", 4480 New: "1", 4481 }, 4482 }, 4483 }, 4484 }, 4485 }, 4486 { 4487 Type: DiffTypeEdited, 4488 Name: "Check", 4489 Objects: []*ObjectDiff{ 4490 { 4491 Type: DiffTypeDeleted, 4492 Name: "CheckRestart", 4493 Fields: []*FieldDiff{ 4494 { 4495 Type: DiffTypeDeleted, 4496 Name: "Grace", 4497 Old: "2000000000", 4498 }, 4499 { 4500 Type: DiffTypeDeleted, 4501 Name: "IgnoreWarnings", 4502 Old: "false", 4503 }, 4504 { 4505 Type: DiffTypeDeleted, 4506 Name: "Limit", 4507 Old: "2", 4508 }, 4509 }, 4510 }, 4511 }, 4512 }, 4513 }, 4514 }, 4515 }, 4516 }, 4517 }, 4518 { 4519 Name: "Vault added", 4520 Old: &Task{}, 4521 New: &Task{ 4522 Vault: &Vault{ 4523 Policies: []string{"foo", "bar"}, 4524 Env: true, 4525 ChangeMode: "signal", 4526 ChangeSignal: "SIGUSR1", 4527 }, 4528 }, 4529 Expected: &TaskDiff{ 4530 Type: DiffTypeEdited, 4531 Objects: []*ObjectDiff{ 4532 { 4533 Type: DiffTypeAdded, 4534 Name: "Vault", 4535 Fields: []*FieldDiff{ 4536 { 4537 Type: DiffTypeAdded, 4538 Name: "ChangeMode", 4539 Old: "", 4540 New: "signal", 4541 }, 4542 { 4543 Type: DiffTypeAdded, 4544 Name: "ChangeSignal", 4545 Old: "", 4546 New: "SIGUSR1", 4547 }, 4548 { 4549 Type: DiffTypeAdded, 4550 Name: "Env", 4551 Old: "", 4552 New: "true", 4553 }, 4554 }, 4555 Objects: []*ObjectDiff{ 4556 { 4557 Type: DiffTypeAdded, 4558 Name: "Policies", 4559 Fields: []*FieldDiff{ 4560 { 4561 Type: DiffTypeAdded, 4562 Name: "Policies", 4563 Old: "", 4564 New: "bar", 4565 }, 4566 { 4567 Type: DiffTypeAdded, 4568 Name: "Policies", 4569 Old: "", 4570 New: "foo", 4571 }, 4572 }, 4573 }, 4574 }, 4575 }, 4576 }, 4577 }, 4578 }, 4579 { 4580 Name: "Vault deleted", 4581 Old: &Task{ 4582 Vault: &Vault{ 4583 Policies: []string{"foo", "bar"}, 4584 Env: true, 4585 ChangeMode: "signal", 4586 ChangeSignal: "SIGUSR1", 4587 }, 4588 }, 4589 New: &Task{}, 4590 Expected: &TaskDiff{ 4591 Type: DiffTypeEdited, 4592 Objects: []*ObjectDiff{ 4593 { 4594 Type: DiffTypeDeleted, 4595 Name: "Vault", 4596 Fields: []*FieldDiff{ 4597 { 4598 Type: DiffTypeDeleted, 4599 Name: "ChangeMode", 4600 Old: "signal", 4601 New: "", 4602 }, 4603 { 4604 Type: DiffTypeDeleted, 4605 Name: "ChangeSignal", 4606 Old: "SIGUSR1", 4607 New: "", 4608 }, 4609 { 4610 Type: DiffTypeDeleted, 4611 Name: "Env", 4612 Old: "true", 4613 New: "", 4614 }, 4615 }, 4616 Objects: []*ObjectDiff{ 4617 { 4618 Type: DiffTypeDeleted, 4619 Name: "Policies", 4620 Fields: []*FieldDiff{ 4621 { 4622 Type: DiffTypeDeleted, 4623 Name: "Policies", 4624 Old: "bar", 4625 New: "", 4626 }, 4627 { 4628 Type: DiffTypeDeleted, 4629 Name: "Policies", 4630 Old: "foo", 4631 New: "", 4632 }, 4633 }, 4634 }, 4635 }, 4636 }, 4637 }, 4638 }, 4639 }, 4640 { 4641 Name: "Vault edited", 4642 Old: &Task{ 4643 Vault: &Vault{ 4644 Policies: []string{"foo", "bar"}, 4645 Env: true, 4646 ChangeMode: "signal", 4647 ChangeSignal: "SIGUSR1", 4648 }, 4649 }, 4650 New: &Task{ 4651 Vault: &Vault{ 4652 Policies: []string{"bar", "baz"}, 4653 Env: false, 4654 ChangeMode: "restart", 4655 ChangeSignal: "foo", 4656 }, 4657 }, 4658 Expected: &TaskDiff{ 4659 Type: DiffTypeEdited, 4660 Objects: []*ObjectDiff{ 4661 { 4662 Type: DiffTypeEdited, 4663 Name: "Vault", 4664 Fields: []*FieldDiff{ 4665 { 4666 Type: DiffTypeEdited, 4667 Name: "ChangeMode", 4668 Old: "signal", 4669 New: "restart", 4670 }, 4671 { 4672 Type: DiffTypeEdited, 4673 Name: "ChangeSignal", 4674 Old: "SIGUSR1", 4675 New: "foo", 4676 }, 4677 { 4678 Type: DiffTypeEdited, 4679 Name: "Env", 4680 Old: "true", 4681 New: "false", 4682 }, 4683 }, 4684 Objects: []*ObjectDiff{ 4685 { 4686 Type: DiffTypeEdited, 4687 Name: "Policies", 4688 Fields: []*FieldDiff{ 4689 { 4690 Type: DiffTypeAdded, 4691 Name: "Policies", 4692 Old: "", 4693 New: "baz", 4694 }, 4695 { 4696 Type: DiffTypeDeleted, 4697 Name: "Policies", 4698 Old: "foo", 4699 New: "", 4700 }, 4701 }, 4702 }, 4703 }, 4704 }, 4705 }, 4706 }, 4707 }, 4708 { 4709 Name: "Vault edited with context", 4710 Contextual: true, 4711 Old: &Task{ 4712 Vault: &Vault{ 4713 Policies: []string{"foo", "bar"}, 4714 Env: true, 4715 ChangeMode: "signal", 4716 ChangeSignal: "SIGUSR1", 4717 }, 4718 }, 4719 New: &Task{ 4720 Vault: &Vault{ 4721 Policies: []string{"bar", "baz"}, 4722 Env: true, 4723 ChangeMode: "signal", 4724 ChangeSignal: "SIGUSR1", 4725 }, 4726 }, 4727 Expected: &TaskDiff{ 4728 Type: DiffTypeEdited, 4729 Objects: []*ObjectDiff{ 4730 { 4731 Type: DiffTypeEdited, 4732 Name: "Vault", 4733 Fields: []*FieldDiff{ 4734 { 4735 Type: DiffTypeNone, 4736 Name: "ChangeMode", 4737 Old: "signal", 4738 New: "signal", 4739 }, 4740 { 4741 Type: DiffTypeNone, 4742 Name: "ChangeSignal", 4743 Old: "SIGUSR1", 4744 New: "SIGUSR1", 4745 }, 4746 { 4747 Type: DiffTypeNone, 4748 Name: "Env", 4749 Old: "true", 4750 New: "true", 4751 }, 4752 }, 4753 Objects: []*ObjectDiff{ 4754 { 4755 Type: DiffTypeEdited, 4756 Name: "Policies", 4757 Fields: []*FieldDiff{ 4758 { 4759 Type: DiffTypeAdded, 4760 Name: "Policies", 4761 Old: "", 4762 New: "baz", 4763 }, 4764 { 4765 Type: DiffTypeNone, 4766 Name: "Policies", 4767 Old: "bar", 4768 New: "bar", 4769 }, 4770 { 4771 Type: DiffTypeDeleted, 4772 Name: "Policies", 4773 Old: "foo", 4774 New: "", 4775 }, 4776 }, 4777 }, 4778 }, 4779 }, 4780 }, 4781 }, 4782 }, 4783 { 4784 Name: "Template edited", 4785 Old: &Task{ 4786 Templates: []*Template{ 4787 { 4788 SourcePath: "foo", 4789 DestPath: "bar", 4790 EmbeddedTmpl: "baz", 4791 ChangeMode: "bam", 4792 ChangeSignal: "SIGHUP", 4793 Splay: 1, 4794 Perms: "0644", 4795 VaultGrace: 3 * time.Second, 4796 }, 4797 { 4798 SourcePath: "foo2", 4799 DestPath: "bar2", 4800 EmbeddedTmpl: "baz2", 4801 ChangeMode: "bam2", 4802 ChangeSignal: "SIGHUP2", 4803 Splay: 2, 4804 Perms: "0666", 4805 Envvars: true, 4806 VaultGrace: 5 * time.Second, 4807 }, 4808 }, 4809 }, 4810 New: &Task{ 4811 Templates: []*Template{ 4812 { 4813 SourcePath: "foo", 4814 DestPath: "bar", 4815 EmbeddedTmpl: "baz", 4816 ChangeMode: "bam", 4817 ChangeSignal: "SIGHUP", 4818 Splay: 1, 4819 Perms: "0644", 4820 VaultGrace: 3 * time.Second, 4821 }, 4822 { 4823 SourcePath: "foo3", 4824 DestPath: "bar3", 4825 EmbeddedTmpl: "baz3", 4826 ChangeMode: "bam3", 4827 ChangeSignal: "SIGHUP3", 4828 Splay: 3, 4829 Perms: "0776", 4830 VaultGrace: 10 * time.Second, 4831 }, 4832 }, 4833 }, 4834 Expected: &TaskDiff{ 4835 Type: DiffTypeEdited, 4836 Objects: []*ObjectDiff{ 4837 { 4838 Type: DiffTypeAdded, 4839 Name: "Template", 4840 Fields: []*FieldDiff{ 4841 { 4842 Type: DiffTypeAdded, 4843 Name: "ChangeMode", 4844 Old: "", 4845 New: "bam3", 4846 }, 4847 { 4848 Type: DiffTypeAdded, 4849 Name: "ChangeSignal", 4850 Old: "", 4851 New: "SIGHUP3", 4852 }, 4853 { 4854 Type: DiffTypeAdded, 4855 Name: "DestPath", 4856 Old: "", 4857 New: "bar3", 4858 }, 4859 { 4860 Type: DiffTypeAdded, 4861 Name: "EmbeddedTmpl", 4862 Old: "", 4863 New: "baz3", 4864 }, 4865 { 4866 Type: DiffTypeAdded, 4867 Name: "Envvars", 4868 Old: "", 4869 New: "false", 4870 }, 4871 { 4872 Type: DiffTypeAdded, 4873 Name: "Perms", 4874 Old: "", 4875 New: "0776", 4876 }, 4877 { 4878 Type: DiffTypeAdded, 4879 Name: "SourcePath", 4880 Old: "", 4881 New: "foo3", 4882 }, 4883 { 4884 Type: DiffTypeAdded, 4885 Name: "Splay", 4886 Old: "", 4887 New: "3", 4888 }, 4889 { 4890 Type: DiffTypeAdded, 4891 Name: "VaultGrace", 4892 Old: "", 4893 New: "10000000000", 4894 }, 4895 }, 4896 }, 4897 { 4898 Type: DiffTypeDeleted, 4899 Name: "Template", 4900 Fields: []*FieldDiff{ 4901 { 4902 Type: DiffTypeDeleted, 4903 Name: "ChangeMode", 4904 Old: "bam2", 4905 New: "", 4906 }, 4907 { 4908 Type: DiffTypeDeleted, 4909 Name: "ChangeSignal", 4910 Old: "SIGHUP2", 4911 New: "", 4912 }, 4913 { 4914 Type: DiffTypeDeleted, 4915 Name: "DestPath", 4916 Old: "bar2", 4917 New: "", 4918 }, 4919 { 4920 Type: DiffTypeDeleted, 4921 Name: "EmbeddedTmpl", 4922 Old: "baz2", 4923 New: "", 4924 }, 4925 { 4926 Type: DiffTypeDeleted, 4927 Name: "Envvars", 4928 Old: "true", 4929 New: "", 4930 }, 4931 { 4932 Type: DiffTypeDeleted, 4933 Name: "Perms", 4934 Old: "0666", 4935 New: "", 4936 }, 4937 { 4938 Type: DiffTypeDeleted, 4939 Name: "SourcePath", 4940 Old: "foo2", 4941 New: "", 4942 }, 4943 { 4944 Type: DiffTypeDeleted, 4945 Name: "Splay", 4946 Old: "2", 4947 New: "", 4948 }, 4949 { 4950 Type: DiffTypeDeleted, 4951 Name: "VaultGrace", 4952 Old: "5000000000", 4953 New: "", 4954 }, 4955 }, 4956 }, 4957 }, 4958 }, 4959 }, 4960 { 4961 Name: "DispatchPayload added", 4962 Old: &Task{}, 4963 New: &Task{ 4964 DispatchPayload: &DispatchPayloadConfig{ 4965 File: "foo", 4966 }, 4967 }, 4968 Expected: &TaskDiff{ 4969 Type: DiffTypeEdited, 4970 Objects: []*ObjectDiff{ 4971 { 4972 Type: DiffTypeAdded, 4973 Name: "DispatchPayload", 4974 Fields: []*FieldDiff{ 4975 { 4976 Type: DiffTypeAdded, 4977 Name: "File", 4978 Old: "", 4979 New: "foo", 4980 }, 4981 }, 4982 }, 4983 }, 4984 }, 4985 }, 4986 { 4987 Name: "DispatchPayload deleted", 4988 Old: &Task{ 4989 DispatchPayload: &DispatchPayloadConfig{ 4990 File: "foo", 4991 }, 4992 }, 4993 New: &Task{}, 4994 Expected: &TaskDiff{ 4995 Type: DiffTypeEdited, 4996 Objects: []*ObjectDiff{ 4997 { 4998 Type: DiffTypeDeleted, 4999 Name: "DispatchPayload", 5000 Fields: []*FieldDiff{ 5001 { 5002 Type: DiffTypeDeleted, 5003 Name: "File", 5004 Old: "foo", 5005 New: "", 5006 }, 5007 }, 5008 }, 5009 }, 5010 }, 5011 }, 5012 { 5013 Name: "Dispatch payload edited", 5014 Old: &Task{ 5015 DispatchPayload: &DispatchPayloadConfig{ 5016 File: "foo", 5017 }, 5018 }, 5019 New: &Task{ 5020 DispatchPayload: &DispatchPayloadConfig{ 5021 File: "bar", 5022 }, 5023 }, 5024 Expected: &TaskDiff{ 5025 Type: DiffTypeEdited, 5026 Objects: []*ObjectDiff{ 5027 { 5028 Type: DiffTypeEdited, 5029 Name: "DispatchPayload", 5030 Fields: []*FieldDiff{ 5031 { 5032 Type: DiffTypeEdited, 5033 Name: "File", 5034 Old: "foo", 5035 New: "bar", 5036 }, 5037 }, 5038 }, 5039 }, 5040 }, 5041 }, 5042 { 5043 // Place holder for if more fields are added 5044 Name: "DispatchPayload edited with context", 5045 Contextual: true, 5046 Old: &Task{ 5047 DispatchPayload: &DispatchPayloadConfig{ 5048 File: "foo", 5049 }, 5050 }, 5051 New: &Task{ 5052 DispatchPayload: &DispatchPayloadConfig{ 5053 File: "bar", 5054 }, 5055 }, 5056 Expected: &TaskDiff{ 5057 Type: DiffTypeEdited, 5058 Objects: []*ObjectDiff{ 5059 { 5060 Type: DiffTypeEdited, 5061 Name: "DispatchPayload", 5062 Fields: []*FieldDiff{ 5063 { 5064 Type: DiffTypeEdited, 5065 Name: "File", 5066 Old: "foo", 5067 New: "bar", 5068 }, 5069 }, 5070 }, 5071 }, 5072 }, 5073 }, 5074 } 5075 5076 for i, c := range cases { 5077 t.Run(c.Name, func(t *testing.T) { 5078 actual, err := c.Old.Diff(c.New, c.Contextual) 5079 if c.Error && err == nil { 5080 t.Fatalf("case %d: expected errored", i+1) 5081 } else if err != nil { 5082 if !c.Error { 5083 t.Fatalf("case %d: errored %#v", i+1, err) 5084 } else { 5085 return 5086 } 5087 } 5088 5089 if !reflect.DeepEqual(actual, c.Expected) { 5090 t.Errorf("case %d: got:\n%#v\n want:\n%#v\n", 5091 i+1, actual, c.Expected) 5092 } 5093 }) 5094 } 5095 }