github.com/smithx10/nomad@v0.9.1-rc1/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 }, 3182 }, 3183 New: &Task{ 3184 Resources: &Resources{ 3185 CPU: 200, 3186 MemoryMB: 200, 3187 DiskMB: 200, 3188 }, 3189 }, 3190 Expected: &TaskDiff{ 3191 Type: DiffTypeEdited, 3192 Objects: []*ObjectDiff{ 3193 { 3194 Type: DiffTypeEdited, 3195 Name: "Resources", 3196 Fields: []*FieldDiff{ 3197 { 3198 Type: DiffTypeEdited, 3199 Name: "CPU", 3200 Old: "100", 3201 New: "200", 3202 }, 3203 { 3204 Type: DiffTypeEdited, 3205 Name: "DiskMB", 3206 Old: "100", 3207 New: "200", 3208 }, 3209 { 3210 Type: DiffTypeEdited, 3211 Name: "MemoryMB", 3212 Old: "100", 3213 New: "200", 3214 }, 3215 }, 3216 }, 3217 }, 3218 }, 3219 }, 3220 { 3221 Name: "Resources edited (no networks) with context", 3222 Contextual: true, 3223 Old: &Task{ 3224 Resources: &Resources{ 3225 CPU: 100, 3226 MemoryMB: 100, 3227 DiskMB: 100, 3228 }, 3229 }, 3230 New: &Task{ 3231 Resources: &Resources{ 3232 CPU: 200, 3233 MemoryMB: 100, 3234 DiskMB: 200, 3235 }, 3236 }, 3237 Expected: &TaskDiff{ 3238 Type: DiffTypeEdited, 3239 Objects: []*ObjectDiff{ 3240 { 3241 Type: DiffTypeEdited, 3242 Name: "Resources", 3243 Fields: []*FieldDiff{ 3244 { 3245 Type: DiffTypeEdited, 3246 Name: "CPU", 3247 Old: "100", 3248 New: "200", 3249 }, 3250 { 3251 Type: DiffTypeEdited, 3252 Name: "DiskMB", 3253 Old: "100", 3254 New: "200", 3255 }, 3256 { 3257 Type: DiffTypeNone, 3258 Name: "IOPS", 3259 Old: "0", 3260 New: "0", 3261 }, 3262 { 3263 Type: DiffTypeNone, 3264 Name: "MemoryMB", 3265 Old: "100", 3266 New: "100", 3267 }, 3268 }, 3269 }, 3270 }, 3271 }, 3272 }, 3273 { 3274 Name: "Network Resources edited", 3275 Old: &Task{ 3276 Resources: &Resources{ 3277 Networks: []*NetworkResource{ 3278 { 3279 Device: "foo", 3280 CIDR: "foo", 3281 IP: "foo", 3282 MBits: 100, 3283 ReservedPorts: []Port{ 3284 { 3285 Label: "foo", 3286 Value: 80, 3287 }, 3288 }, 3289 DynamicPorts: []Port{ 3290 { 3291 Label: "bar", 3292 }, 3293 }, 3294 }, 3295 }, 3296 }, 3297 }, 3298 New: &Task{ 3299 Resources: &Resources{ 3300 Networks: []*NetworkResource{ 3301 { 3302 Device: "bar", 3303 CIDR: "bar", 3304 IP: "bar", 3305 MBits: 200, 3306 ReservedPorts: []Port{ 3307 { 3308 Label: "foo", 3309 Value: 81, 3310 }, 3311 }, 3312 DynamicPorts: []Port{ 3313 { 3314 Label: "baz", 3315 }, 3316 }, 3317 }, 3318 }, 3319 }, 3320 }, 3321 Expected: &TaskDiff{ 3322 Type: DiffTypeEdited, 3323 Objects: []*ObjectDiff{ 3324 { 3325 Type: DiffTypeEdited, 3326 Name: "Resources", 3327 Objects: []*ObjectDiff{ 3328 { 3329 Type: DiffTypeAdded, 3330 Name: "Network", 3331 Fields: []*FieldDiff{ 3332 { 3333 Type: DiffTypeAdded, 3334 Name: "MBits", 3335 Old: "", 3336 New: "200", 3337 }, 3338 }, 3339 Objects: []*ObjectDiff{ 3340 { 3341 Type: DiffTypeAdded, 3342 Name: "Static Port", 3343 Fields: []*FieldDiff{ 3344 { 3345 Type: DiffTypeAdded, 3346 Name: "Label", 3347 Old: "", 3348 New: "foo", 3349 }, 3350 { 3351 Type: DiffTypeAdded, 3352 Name: "Value", 3353 Old: "", 3354 New: "81", 3355 }, 3356 }, 3357 }, 3358 { 3359 Type: DiffTypeAdded, 3360 Name: "Dynamic Port", 3361 Fields: []*FieldDiff{ 3362 { 3363 Type: DiffTypeAdded, 3364 Name: "Label", 3365 Old: "", 3366 New: "baz", 3367 }, 3368 }, 3369 }, 3370 }, 3371 }, 3372 { 3373 Type: DiffTypeDeleted, 3374 Name: "Network", 3375 Fields: []*FieldDiff{ 3376 { 3377 Type: DiffTypeDeleted, 3378 Name: "MBits", 3379 Old: "100", 3380 New: "", 3381 }, 3382 }, 3383 Objects: []*ObjectDiff{ 3384 { 3385 Type: DiffTypeDeleted, 3386 Name: "Static Port", 3387 Fields: []*FieldDiff{ 3388 { 3389 Type: DiffTypeDeleted, 3390 Name: "Label", 3391 Old: "foo", 3392 New: "", 3393 }, 3394 { 3395 Type: DiffTypeDeleted, 3396 Name: "Value", 3397 Old: "80", 3398 New: "", 3399 }, 3400 }, 3401 }, 3402 { 3403 Type: DiffTypeDeleted, 3404 Name: "Dynamic Port", 3405 Fields: []*FieldDiff{ 3406 { 3407 Type: DiffTypeDeleted, 3408 Name: "Label", 3409 Old: "bar", 3410 New: "", 3411 }, 3412 }, 3413 }, 3414 }, 3415 }, 3416 }, 3417 }, 3418 }, 3419 }, 3420 }, 3421 { 3422 Name: "Device Resources edited", 3423 Old: &Task{ 3424 Resources: &Resources{ 3425 Devices: []*RequestedDevice{ 3426 { 3427 Name: "foo", 3428 Count: 2, 3429 }, 3430 { 3431 Name: "bar", 3432 Count: 2, 3433 }, 3434 { 3435 Name: "baz", 3436 Count: 2, 3437 }, 3438 }, 3439 }, 3440 }, 3441 New: &Task{ 3442 Resources: &Resources{ 3443 Devices: []*RequestedDevice{ 3444 { 3445 Name: "foo", 3446 Count: 2, 3447 }, 3448 { 3449 Name: "bar", 3450 Count: 3, 3451 }, 3452 { 3453 Name: "bam", 3454 Count: 2, 3455 }, 3456 }, 3457 }, 3458 }, 3459 Expected: &TaskDiff{ 3460 Type: DiffTypeEdited, 3461 Objects: []*ObjectDiff{ 3462 { 3463 Type: DiffTypeEdited, 3464 Name: "Resources", 3465 Objects: []*ObjectDiff{ 3466 { 3467 Type: DiffTypeEdited, 3468 Name: "Device", 3469 Fields: []*FieldDiff{ 3470 { 3471 Type: DiffTypeEdited, 3472 Name: "Count", 3473 Old: "2", 3474 New: "3", 3475 }, 3476 }, 3477 }, 3478 { 3479 Type: DiffTypeAdded, 3480 Name: "Device", 3481 Fields: []*FieldDiff{ 3482 { 3483 Type: DiffTypeAdded, 3484 Name: "Count", 3485 Old: "", 3486 New: "2", 3487 }, 3488 { 3489 Type: DiffTypeAdded, 3490 Name: "Name", 3491 Old: "", 3492 New: "bam", 3493 }, 3494 }, 3495 }, 3496 { 3497 Type: DiffTypeDeleted, 3498 Name: "Device", 3499 Fields: []*FieldDiff{ 3500 { 3501 Type: DiffTypeDeleted, 3502 Name: "Count", 3503 Old: "2", 3504 New: "", 3505 }, 3506 { 3507 Type: DiffTypeDeleted, 3508 Name: "Name", 3509 Old: "baz", 3510 New: "", 3511 }, 3512 }, 3513 }, 3514 }, 3515 }, 3516 }, 3517 }, 3518 }, 3519 { 3520 Name: "Device Resources edited with context", 3521 Contextual: true, 3522 Old: &Task{ 3523 Resources: &Resources{ 3524 CPU: 100, 3525 MemoryMB: 100, 3526 DiskMB: 100, 3527 Devices: []*RequestedDevice{ 3528 { 3529 Name: "foo", 3530 Count: 2, 3531 }, 3532 { 3533 Name: "bar", 3534 Count: 2, 3535 }, 3536 { 3537 Name: "baz", 3538 Count: 2, 3539 }, 3540 }, 3541 }, 3542 }, 3543 New: &Task{ 3544 Resources: &Resources{ 3545 CPU: 100, 3546 MemoryMB: 100, 3547 DiskMB: 100, 3548 Devices: []*RequestedDevice{ 3549 { 3550 Name: "foo", 3551 Count: 2, 3552 }, 3553 { 3554 Name: "bar", 3555 Count: 3, 3556 }, 3557 { 3558 Name: "bam", 3559 Count: 2, 3560 }, 3561 }, 3562 }, 3563 }, 3564 Expected: &TaskDiff{ 3565 Type: DiffTypeEdited, 3566 Objects: []*ObjectDiff{ 3567 { 3568 Type: DiffTypeEdited, 3569 Name: "Resources", 3570 Fields: []*FieldDiff{ 3571 { 3572 Type: DiffTypeNone, 3573 Name: "CPU", 3574 Old: "100", 3575 New: "100", 3576 }, 3577 { 3578 Type: DiffTypeNone, 3579 Name: "DiskMB", 3580 Old: "100", 3581 New: "100", 3582 }, 3583 { 3584 Type: DiffTypeNone, 3585 Name: "IOPS", 3586 Old: "0", 3587 New: "0", 3588 }, 3589 { 3590 Type: DiffTypeNone, 3591 Name: "MemoryMB", 3592 Old: "100", 3593 New: "100", 3594 }, 3595 }, 3596 Objects: []*ObjectDiff{ 3597 { 3598 Type: DiffTypeEdited, 3599 Name: "Device", 3600 Fields: []*FieldDiff{ 3601 { 3602 Type: DiffTypeEdited, 3603 Name: "Count", 3604 Old: "2", 3605 New: "3", 3606 }, 3607 { 3608 Type: DiffTypeNone, 3609 Name: "Name", 3610 Old: "bar", 3611 New: "bar", 3612 }, 3613 }, 3614 }, 3615 { 3616 Type: DiffTypeAdded, 3617 Name: "Device", 3618 Fields: []*FieldDiff{ 3619 { 3620 Type: DiffTypeAdded, 3621 Name: "Count", 3622 Old: "", 3623 New: "2", 3624 }, 3625 { 3626 Type: DiffTypeAdded, 3627 Name: "Name", 3628 Old: "", 3629 New: "bam", 3630 }, 3631 }, 3632 }, 3633 { 3634 Type: DiffTypeDeleted, 3635 Name: "Device", 3636 Fields: []*FieldDiff{ 3637 { 3638 Type: DiffTypeDeleted, 3639 Name: "Count", 3640 Old: "2", 3641 New: "", 3642 }, 3643 { 3644 Type: DiffTypeDeleted, 3645 Name: "Name", 3646 Old: "baz", 3647 New: "", 3648 }, 3649 }, 3650 }, 3651 }, 3652 }, 3653 }, 3654 }, 3655 }, 3656 { 3657 Name: "Config same", 3658 Old: &Task{ 3659 Config: map[string]interface{}{ 3660 "foo": 1, 3661 "bar": "bar", 3662 "bam": []string{"a", "b"}, 3663 "baz": map[string]int{ 3664 "a": 1, 3665 "b": 2, 3666 }, 3667 "boom": &Port{ 3668 Label: "boom_port", 3669 }, 3670 }, 3671 }, 3672 New: &Task{ 3673 Config: map[string]interface{}{ 3674 "foo": 1, 3675 "bar": "bar", 3676 "bam": []string{"a", "b"}, 3677 "baz": map[string]int{ 3678 "a": 1, 3679 "b": 2, 3680 }, 3681 "boom": &Port{ 3682 Label: "boom_port", 3683 }, 3684 }, 3685 }, 3686 Expected: &TaskDiff{ 3687 Type: DiffTypeNone, 3688 }, 3689 }, 3690 { 3691 Name: "Config edited", 3692 Old: &Task{ 3693 Config: map[string]interface{}{ 3694 "foo": 1, 3695 "bar": "baz", 3696 "bam": []string{"a", "b"}, 3697 "baz": map[string]int{ 3698 "a": 1, 3699 "b": 2, 3700 }, 3701 "boom": &Port{ 3702 Label: "boom_port", 3703 }, 3704 }, 3705 }, 3706 New: &Task{ 3707 Config: map[string]interface{}{ 3708 "foo": 2, 3709 "bar": "baz", 3710 "bam": []string{"a", "c", "d"}, 3711 "baz": map[string]int{ 3712 "b": 3, 3713 "c": 4, 3714 }, 3715 "boom": &Port{ 3716 Label: "boom_port2", 3717 }, 3718 }, 3719 }, 3720 Expected: &TaskDiff{ 3721 Type: DiffTypeEdited, 3722 Objects: []*ObjectDiff{ 3723 { 3724 Type: DiffTypeEdited, 3725 Name: "Config", 3726 Fields: []*FieldDiff{ 3727 { 3728 Type: DiffTypeEdited, 3729 Name: "bam[1]", 3730 Old: "b", 3731 New: "c", 3732 }, 3733 { 3734 Type: DiffTypeAdded, 3735 Name: "bam[2]", 3736 Old: "", 3737 New: "d", 3738 }, 3739 { 3740 Type: DiffTypeDeleted, 3741 Name: "baz[a]", 3742 Old: "1", 3743 New: "", 3744 }, 3745 { 3746 Type: DiffTypeEdited, 3747 Name: "baz[b]", 3748 Old: "2", 3749 New: "3", 3750 }, 3751 { 3752 Type: DiffTypeAdded, 3753 Name: "baz[c]", 3754 Old: "", 3755 New: "4", 3756 }, 3757 { 3758 Type: DiffTypeEdited, 3759 Name: "boom.Label", 3760 Old: "boom_port", 3761 New: "boom_port2", 3762 }, 3763 { 3764 Type: DiffTypeEdited, 3765 Name: "foo", 3766 Old: "1", 3767 New: "2", 3768 }, 3769 }, 3770 }, 3771 }, 3772 }, 3773 }, 3774 { 3775 Name: "Config edited with context", 3776 Contextual: true, 3777 Old: &Task{ 3778 Config: map[string]interface{}{ 3779 "foo": 1, 3780 "bar": "baz", 3781 "bam": []string{"a", "b"}, 3782 "baz": map[string]int{ 3783 "a": 1, 3784 "b": 2, 3785 }, 3786 "boom": &Port{ 3787 Label: "boom_port", 3788 }, 3789 }, 3790 }, 3791 New: &Task{ 3792 Config: map[string]interface{}{ 3793 "foo": 2, 3794 "bar": "baz", 3795 "bam": []string{"a", "c", "d"}, 3796 "baz": map[string]int{ 3797 "a": 1, 3798 "b": 2, 3799 }, 3800 "boom": &Port{ 3801 Label: "boom_port", 3802 }, 3803 }, 3804 }, 3805 Expected: &TaskDiff{ 3806 Type: DiffTypeEdited, 3807 Objects: []*ObjectDiff{ 3808 { 3809 Type: DiffTypeEdited, 3810 Name: "Config", 3811 Fields: []*FieldDiff{ 3812 { 3813 Type: DiffTypeNone, 3814 Name: "bam[0]", 3815 Old: "a", 3816 New: "a", 3817 }, 3818 { 3819 Type: DiffTypeEdited, 3820 Name: "bam[1]", 3821 Old: "b", 3822 New: "c", 3823 }, 3824 { 3825 Type: DiffTypeAdded, 3826 Name: "bam[2]", 3827 Old: "", 3828 New: "d", 3829 }, 3830 { 3831 Type: DiffTypeNone, 3832 Name: "bar", 3833 Old: "baz", 3834 New: "baz", 3835 }, 3836 { 3837 Type: DiffTypeNone, 3838 Name: "baz[a]", 3839 Old: "1", 3840 New: "1", 3841 }, 3842 { 3843 Type: DiffTypeNone, 3844 Name: "baz[b]", 3845 Old: "2", 3846 New: "2", 3847 }, 3848 { 3849 Type: DiffTypeNone, 3850 Name: "boom.Label", 3851 Old: "boom_port", 3852 New: "boom_port", 3853 }, 3854 { 3855 Type: DiffTypeNone, 3856 Name: "boom.Value", 3857 Old: "0", 3858 New: "0", 3859 }, 3860 { 3861 Type: DiffTypeEdited, 3862 Name: "foo", 3863 Old: "1", 3864 New: "2", 3865 }, 3866 }, 3867 }, 3868 }, 3869 }, 3870 }, 3871 { 3872 Name: "Services edited (no checks)", 3873 Old: &Task{ 3874 Services: []*Service{ 3875 { 3876 Name: "foo", 3877 PortLabel: "foo", 3878 }, 3879 { 3880 Name: "bar", 3881 PortLabel: "bar", 3882 }, 3883 { 3884 Name: "baz", 3885 PortLabel: "baz", 3886 }, 3887 }, 3888 }, 3889 New: &Task{ 3890 Services: []*Service{ 3891 { 3892 Name: "bar", 3893 PortLabel: "bar", 3894 }, 3895 { 3896 Name: "baz", 3897 PortLabel: "baz2", 3898 }, 3899 { 3900 Name: "bam", 3901 PortLabel: "bam", 3902 }, 3903 }, 3904 }, 3905 Expected: &TaskDiff{ 3906 Type: DiffTypeEdited, 3907 Objects: []*ObjectDiff{ 3908 { 3909 Type: DiffTypeEdited, 3910 Name: "Service", 3911 Fields: []*FieldDiff{ 3912 { 3913 Type: DiffTypeEdited, 3914 Name: "PortLabel", 3915 Old: "baz", 3916 New: "baz2", 3917 }, 3918 }, 3919 }, 3920 { 3921 Type: DiffTypeAdded, 3922 Name: "Service", 3923 Fields: []*FieldDiff{ 3924 { 3925 Type: DiffTypeAdded, 3926 Name: "Name", 3927 Old: "", 3928 New: "bam", 3929 }, 3930 { 3931 Type: DiffTypeAdded, 3932 Name: "PortLabel", 3933 Old: "", 3934 New: "bam", 3935 }, 3936 }, 3937 }, 3938 { 3939 Type: DiffTypeDeleted, 3940 Name: "Service", 3941 Fields: []*FieldDiff{ 3942 { 3943 Type: DiffTypeDeleted, 3944 Name: "Name", 3945 Old: "foo", 3946 New: "", 3947 }, 3948 { 3949 Type: DiffTypeDeleted, 3950 Name: "PortLabel", 3951 Old: "foo", 3952 New: "", 3953 }, 3954 }, 3955 }, 3956 }, 3957 }, 3958 }, 3959 { 3960 Name: "Services edited (no checks) with context", 3961 Contextual: true, 3962 Old: &Task{ 3963 Services: []*Service{ 3964 { 3965 Name: "foo", 3966 PortLabel: "foo", 3967 }, 3968 }, 3969 }, 3970 New: &Task{ 3971 Services: []*Service{ 3972 { 3973 Name: "foo", 3974 PortLabel: "bar", 3975 AddressMode: "driver", 3976 }, 3977 }, 3978 }, 3979 Expected: &TaskDiff{ 3980 Type: DiffTypeEdited, 3981 Objects: []*ObjectDiff{ 3982 { 3983 Type: DiffTypeEdited, 3984 Name: "Service", 3985 Fields: []*FieldDiff{ 3986 { 3987 Type: DiffTypeAdded, 3988 Name: "AddressMode", 3989 New: "driver", 3990 }, 3991 { 3992 Type: DiffTypeNone, 3993 Name: "Name", 3994 Old: "foo", 3995 New: "foo", 3996 }, 3997 { 3998 Type: DiffTypeEdited, 3999 Name: "PortLabel", 4000 Old: "foo", 4001 New: "bar", 4002 }, 4003 }, 4004 }, 4005 }, 4006 }, 4007 }, 4008 { 4009 Name: "Services tags edited (no checks) with context", 4010 Contextual: true, 4011 Old: &Task{ 4012 Services: []*Service{ 4013 { 4014 Tags: []string{"foo", "bar"}, 4015 CanaryTags: []string{"foo", "bar"}, 4016 }, 4017 }, 4018 }, 4019 New: &Task{ 4020 Services: []*Service{ 4021 { 4022 Tags: []string{"bar", "bam"}, 4023 CanaryTags: []string{"bar", "bam"}, 4024 }, 4025 }, 4026 }, 4027 Expected: &TaskDiff{ 4028 Type: DiffTypeEdited, 4029 Objects: []*ObjectDiff{ 4030 { 4031 Type: DiffTypeEdited, 4032 Name: "Service", 4033 Objects: []*ObjectDiff{ 4034 { 4035 Type: DiffTypeEdited, 4036 Name: "CanaryTags", 4037 Fields: []*FieldDiff{ 4038 { 4039 Type: DiffTypeAdded, 4040 Name: "CanaryTags", 4041 Old: "", 4042 New: "bam", 4043 }, 4044 { 4045 Type: DiffTypeNone, 4046 Name: "CanaryTags", 4047 Old: "bar", 4048 New: "bar", 4049 }, 4050 { 4051 Type: DiffTypeDeleted, 4052 Name: "CanaryTags", 4053 Old: "foo", 4054 New: "", 4055 }, 4056 }, 4057 }, 4058 { 4059 Type: DiffTypeEdited, 4060 Name: "Tags", 4061 Fields: []*FieldDiff{ 4062 { 4063 Type: DiffTypeAdded, 4064 Name: "Tags", 4065 Old: "", 4066 New: "bam", 4067 }, 4068 { 4069 Type: DiffTypeNone, 4070 Name: "Tags", 4071 Old: "bar", 4072 New: "bar", 4073 }, 4074 { 4075 Type: DiffTypeDeleted, 4076 Name: "Tags", 4077 Old: "foo", 4078 New: "", 4079 }, 4080 }, 4081 }, 4082 }, 4083 Fields: []*FieldDiff{ 4084 { 4085 Type: DiffTypeNone, 4086 Name: "AddressMode", 4087 }, 4088 { 4089 Type: DiffTypeNone, 4090 Name: "Name", 4091 }, 4092 { 4093 Type: DiffTypeNone, 4094 Name: "PortLabel", 4095 }, 4096 }, 4097 }, 4098 }, 4099 }, 4100 }, 4101 { 4102 Name: "Service Checks edited", 4103 Old: &Task{ 4104 Services: []*Service{ 4105 { 4106 Name: "foo", 4107 Checks: []*ServiceCheck{ 4108 { 4109 Name: "foo", 4110 Type: "http", 4111 Command: "foo", 4112 Args: []string{"foo"}, 4113 Path: "foo", 4114 Protocol: "http", 4115 Interval: 1 * time.Second, 4116 Timeout: 1 * time.Second, 4117 Header: map[string][]string{ 4118 "Foo": {"bar"}, 4119 }, 4120 }, 4121 { 4122 Name: "bar", 4123 Type: "http", 4124 Command: "foo", 4125 Args: []string{"foo"}, 4126 Path: "foo", 4127 Protocol: "http", 4128 Interval: 1 * time.Second, 4129 Timeout: 1 * time.Second, 4130 }, 4131 { 4132 Name: "baz", 4133 Type: "http", 4134 Command: "foo", 4135 Args: []string{"foo"}, 4136 Path: "foo", 4137 Protocol: "http", 4138 Interval: 1 * time.Second, 4139 Timeout: 1 * time.Second, 4140 }, 4141 }, 4142 }, 4143 }, 4144 }, 4145 New: &Task{ 4146 Services: []*Service{ 4147 { 4148 Name: "foo", 4149 Checks: []*ServiceCheck{ 4150 { 4151 Name: "bar", 4152 Type: "http", 4153 Command: "foo", 4154 Args: []string{"foo"}, 4155 Path: "foo", 4156 Protocol: "http", 4157 Interval: 1 * time.Second, 4158 Timeout: 1 * time.Second, 4159 }, 4160 { 4161 Name: "baz", 4162 Type: "tcp", 4163 Command: "foo", 4164 Args: []string{"foo"}, 4165 Path: "foo", 4166 Protocol: "http", 4167 Interval: 1 * time.Second, 4168 Timeout: 1 * time.Second, 4169 Header: map[string][]string{ 4170 "Eggs": {"spam"}, 4171 }, 4172 }, 4173 { 4174 Name: "bam", 4175 Type: "http", 4176 Command: "foo", 4177 Args: []string{"foo"}, 4178 Path: "foo", 4179 Protocol: "http", 4180 Interval: 1 * time.Second, 4181 Timeout: 1 * time.Second, 4182 }, 4183 }, 4184 }, 4185 }, 4186 }, 4187 Expected: &TaskDiff{ 4188 Type: DiffTypeEdited, 4189 Objects: []*ObjectDiff{ 4190 { 4191 Type: DiffTypeEdited, 4192 Name: "Service", 4193 Objects: []*ObjectDiff{ 4194 { 4195 Type: DiffTypeEdited, 4196 Name: "Check", 4197 Fields: []*FieldDiff{ 4198 { 4199 Type: DiffTypeEdited, 4200 Name: "Type", 4201 Old: "http", 4202 New: "tcp", 4203 }, 4204 }, 4205 Objects: []*ObjectDiff{ 4206 { 4207 Type: DiffTypeAdded, 4208 Name: "Header", 4209 Fields: []*FieldDiff{ 4210 { 4211 Type: DiffTypeAdded, 4212 Name: "Eggs[0]", 4213 Old: "", 4214 New: "spam", 4215 }, 4216 }, 4217 }, 4218 }, 4219 }, 4220 { 4221 Type: DiffTypeAdded, 4222 Name: "Check", 4223 Fields: []*FieldDiff{ 4224 { 4225 Type: DiffTypeAdded, 4226 Name: "Command", 4227 Old: "", 4228 New: "foo", 4229 }, 4230 { 4231 Type: DiffTypeAdded, 4232 Name: "GRPCUseTLS", 4233 Old: "", 4234 New: "false", 4235 }, 4236 { 4237 Type: DiffTypeAdded, 4238 Name: "Interval", 4239 Old: "", 4240 New: "1000000000", 4241 }, 4242 { 4243 Type: DiffTypeAdded, 4244 Name: "Name", 4245 Old: "", 4246 New: "bam", 4247 }, 4248 { 4249 Type: DiffTypeAdded, 4250 Name: "Path", 4251 Old: "", 4252 New: "foo", 4253 }, 4254 { 4255 Type: DiffTypeAdded, 4256 Name: "Protocol", 4257 Old: "", 4258 New: "http", 4259 }, 4260 { 4261 Type: DiffTypeAdded, 4262 Name: "TLSSkipVerify", 4263 Old: "", 4264 New: "false", 4265 }, 4266 { 4267 Type: DiffTypeAdded, 4268 Name: "Timeout", 4269 Old: "", 4270 New: "1000000000", 4271 }, 4272 { 4273 Type: DiffTypeAdded, 4274 Name: "Type", 4275 Old: "", 4276 New: "http", 4277 }, 4278 }, 4279 }, 4280 { 4281 Type: DiffTypeDeleted, 4282 Name: "Check", 4283 Fields: []*FieldDiff{ 4284 { 4285 Type: DiffTypeDeleted, 4286 Name: "Command", 4287 Old: "foo", 4288 New: "", 4289 }, 4290 { 4291 Type: DiffTypeDeleted, 4292 Name: "GRPCUseTLS", 4293 Old: "false", 4294 New: "", 4295 }, 4296 { 4297 Type: DiffTypeDeleted, 4298 Name: "Interval", 4299 Old: "1000000000", 4300 New: "", 4301 }, 4302 { 4303 Type: DiffTypeDeleted, 4304 Name: "Name", 4305 Old: "foo", 4306 New: "", 4307 }, 4308 { 4309 Type: DiffTypeDeleted, 4310 Name: "Path", 4311 Old: "foo", 4312 New: "", 4313 }, 4314 { 4315 Type: DiffTypeDeleted, 4316 Name: "Protocol", 4317 Old: "http", 4318 New: "", 4319 }, 4320 { 4321 Type: DiffTypeDeleted, 4322 Name: "TLSSkipVerify", 4323 Old: "false", 4324 New: "", 4325 }, 4326 { 4327 Type: DiffTypeDeleted, 4328 Name: "Timeout", 4329 Old: "1000000000", 4330 New: "", 4331 }, 4332 { 4333 Type: DiffTypeDeleted, 4334 Name: "Type", 4335 Old: "http", 4336 New: "", 4337 }, 4338 }, 4339 Objects: []*ObjectDiff{ 4340 { 4341 Type: DiffTypeDeleted, 4342 Name: "Header", 4343 Fields: []*FieldDiff{ 4344 { 4345 Type: DiffTypeDeleted, 4346 Name: "Foo[0]", 4347 Old: "bar", 4348 }, 4349 }, 4350 }, 4351 }, 4352 }, 4353 }, 4354 }, 4355 }, 4356 }, 4357 }, 4358 { 4359 Name: "Service Checks edited with context", 4360 Contextual: true, 4361 Old: &Task{ 4362 Services: []*Service{ 4363 { 4364 Name: "foo", 4365 Checks: []*ServiceCheck{ 4366 { 4367 Name: "foo", 4368 Type: "http", 4369 Command: "foo", 4370 Args: []string{"foo"}, 4371 Path: "foo", 4372 Protocol: "http", 4373 Interval: 1 * time.Second, 4374 Timeout: 1 * time.Second, 4375 InitialStatus: "critical", 4376 Header: map[string][]string{ 4377 "Foo": {"bar"}, 4378 }, 4379 }, 4380 }, 4381 }, 4382 }, 4383 }, 4384 New: &Task{ 4385 Services: []*Service{ 4386 { 4387 Name: "foo", 4388 Checks: []*ServiceCheck{ 4389 { 4390 Name: "foo", 4391 Type: "tcp", 4392 Command: "foo", 4393 Args: []string{"foo"}, 4394 Path: "foo", 4395 Protocol: "http", 4396 Interval: 1 * time.Second, 4397 Timeout: 1 * time.Second, 4398 InitialStatus: "passing", 4399 Method: "POST", 4400 Header: map[string][]string{ 4401 "Foo": {"bar", "baz"}, 4402 "Eggs": {"spam"}, 4403 }, 4404 }, 4405 }, 4406 }, 4407 }, 4408 }, 4409 Expected: &TaskDiff{ 4410 Type: DiffTypeEdited, 4411 Objects: []*ObjectDiff{ 4412 { 4413 Type: DiffTypeEdited, 4414 Name: "Service", 4415 Fields: []*FieldDiff{ 4416 { 4417 Type: DiffTypeNone, 4418 Name: "AddressMode", 4419 Old: "", 4420 New: "", 4421 }, 4422 { 4423 Type: DiffTypeNone, 4424 Name: "Name", 4425 Old: "foo", 4426 New: "foo", 4427 }, 4428 { 4429 Type: DiffTypeNone, 4430 Name: "PortLabel", 4431 Old: "", 4432 New: "", 4433 }, 4434 }, 4435 Objects: []*ObjectDiff{ 4436 { 4437 Type: DiffTypeEdited, 4438 Name: "Check", 4439 Fields: []*FieldDiff{ 4440 { 4441 Type: DiffTypeNone, 4442 Name: "AddressMode", 4443 Old: "", 4444 New: "", 4445 }, 4446 { 4447 Type: DiffTypeNone, 4448 Name: "Command", 4449 Old: "foo", 4450 New: "foo", 4451 }, 4452 { 4453 Type: DiffTypeNone, 4454 Name: "GRPCService", 4455 Old: "", 4456 New: "", 4457 }, 4458 { 4459 Type: DiffTypeNone, 4460 Name: "GRPCUseTLS", 4461 Old: "false", 4462 New: "false", 4463 }, 4464 { 4465 Type: DiffTypeEdited, 4466 Name: "InitialStatus", 4467 Old: "critical", 4468 New: "passing", 4469 }, 4470 { 4471 Type: DiffTypeNone, 4472 Name: "Interval", 4473 Old: "1000000000", 4474 New: "1000000000", 4475 }, 4476 { 4477 Type: DiffTypeAdded, 4478 Name: "Method", 4479 Old: "", 4480 New: "POST", 4481 }, 4482 { 4483 Type: DiffTypeNone, 4484 Name: "Name", 4485 Old: "foo", 4486 New: "foo", 4487 }, 4488 { 4489 Type: DiffTypeNone, 4490 Name: "Path", 4491 Old: "foo", 4492 New: "foo", 4493 }, 4494 { 4495 Type: DiffTypeNone, 4496 Name: "PortLabel", 4497 Old: "", 4498 New: "", 4499 }, 4500 { 4501 Type: DiffTypeNone, 4502 Name: "Protocol", 4503 Old: "http", 4504 New: "http", 4505 }, 4506 { 4507 Type: DiffTypeNone, 4508 Name: "TLSSkipVerify", 4509 Old: "false", 4510 New: "false", 4511 }, 4512 { 4513 Type: DiffTypeNone, 4514 Name: "Timeout", 4515 Old: "1000000000", 4516 New: "1000000000", 4517 }, 4518 { 4519 Type: DiffTypeEdited, 4520 Name: "Type", 4521 Old: "http", 4522 New: "tcp", 4523 }, 4524 }, 4525 Objects: []*ObjectDiff{ 4526 { 4527 Type: DiffTypeEdited, 4528 Name: "Header", 4529 Fields: []*FieldDiff{ 4530 { 4531 Type: DiffTypeAdded, 4532 Name: "Eggs[0]", 4533 Old: "", 4534 New: "spam", 4535 }, 4536 { 4537 Type: DiffTypeNone, 4538 Name: "Foo[0]", 4539 Old: "bar", 4540 New: "bar", 4541 }, 4542 { 4543 Type: DiffTypeAdded, 4544 Name: "Foo[1]", 4545 Old: "", 4546 New: "baz", 4547 }, 4548 }, 4549 }, 4550 }, 4551 }, 4552 }, 4553 }, 4554 }, 4555 }, 4556 }, 4557 { 4558 Name: "CheckRestart edited", 4559 Old: &Task{ 4560 Services: []*Service{ 4561 { 4562 Name: "foo", 4563 Checks: []*ServiceCheck{ 4564 { 4565 Name: "foo", 4566 Type: "http", 4567 Command: "foo", 4568 Args: []string{"foo"}, 4569 Path: "foo", 4570 Protocol: "http", 4571 Interval: 1 * time.Second, 4572 Timeout: 1 * time.Second, 4573 }, 4574 { 4575 Name: "bar", 4576 Type: "http", 4577 Command: "foo", 4578 Args: []string{"foo"}, 4579 Path: "foo", 4580 Protocol: "http", 4581 Interval: 1 * time.Second, 4582 Timeout: 1 * time.Second, 4583 CheckRestart: &CheckRestart{ 4584 Limit: 2, 4585 Grace: 2 * time.Second, 4586 }, 4587 }, 4588 { 4589 Name: "baz", 4590 Type: "http", 4591 Command: "foo", 4592 Args: []string{"foo"}, 4593 Path: "foo", 4594 Protocol: "http", 4595 Interval: 1 * time.Second, 4596 Timeout: 1 * time.Second, 4597 CheckRestart: &CheckRestart{ 4598 Limit: 3, 4599 Grace: 3 * time.Second, 4600 }, 4601 }, 4602 }, 4603 }, 4604 }, 4605 }, 4606 New: &Task{ 4607 Services: []*Service{ 4608 { 4609 Name: "foo", 4610 Checks: []*ServiceCheck{ 4611 { 4612 Name: "foo", 4613 Type: "http", 4614 Command: "foo", 4615 Args: []string{"foo"}, 4616 Path: "foo", 4617 Protocol: "http", 4618 Interval: 1 * time.Second, 4619 Timeout: 1 * time.Second, 4620 CheckRestart: &CheckRestart{ 4621 Limit: 1, 4622 Grace: 1 * time.Second, 4623 }, 4624 }, 4625 { 4626 Name: "bar", 4627 Type: "http", 4628 Command: "foo", 4629 Args: []string{"foo"}, 4630 Path: "foo", 4631 Protocol: "http", 4632 Interval: 1 * time.Second, 4633 Timeout: 1 * time.Second, 4634 }, 4635 { 4636 Name: "baz", 4637 Type: "http", 4638 Command: "foo", 4639 Args: []string{"foo"}, 4640 Path: "foo", 4641 Protocol: "http", 4642 Interval: 1 * time.Second, 4643 Timeout: 1 * time.Second, 4644 CheckRestart: &CheckRestart{ 4645 Limit: 4, 4646 Grace: 4 * time.Second, 4647 }, 4648 }, 4649 }, 4650 }, 4651 }, 4652 }, 4653 Expected: &TaskDiff{ 4654 Type: DiffTypeEdited, 4655 Objects: []*ObjectDiff{ 4656 { 4657 Type: DiffTypeEdited, 4658 Name: "Service", 4659 Objects: []*ObjectDiff{ 4660 { 4661 Type: DiffTypeEdited, 4662 Name: "Check", 4663 Objects: []*ObjectDiff{ 4664 { 4665 Type: DiffTypeEdited, 4666 Name: "CheckRestart", 4667 Fields: []*FieldDiff{ 4668 { 4669 Type: DiffTypeEdited, 4670 Name: "Grace", 4671 Old: "3000000000", 4672 New: "4000000000", 4673 }, 4674 { 4675 Type: DiffTypeEdited, 4676 Name: "Limit", 4677 Old: "3", 4678 New: "4", 4679 }, 4680 }, 4681 }, 4682 }, 4683 }, 4684 { 4685 Type: DiffTypeEdited, 4686 Name: "Check", 4687 Objects: []*ObjectDiff{ 4688 { 4689 Type: DiffTypeAdded, 4690 Name: "CheckRestart", 4691 Fields: []*FieldDiff{ 4692 { 4693 Type: DiffTypeAdded, 4694 Name: "Grace", 4695 New: "1000000000", 4696 }, 4697 { 4698 Type: DiffTypeAdded, 4699 Name: "IgnoreWarnings", 4700 New: "false", 4701 }, 4702 { 4703 Type: DiffTypeAdded, 4704 Name: "Limit", 4705 New: "1", 4706 }, 4707 }, 4708 }, 4709 }, 4710 }, 4711 { 4712 Type: DiffTypeEdited, 4713 Name: "Check", 4714 Objects: []*ObjectDiff{ 4715 { 4716 Type: DiffTypeDeleted, 4717 Name: "CheckRestart", 4718 Fields: []*FieldDiff{ 4719 { 4720 Type: DiffTypeDeleted, 4721 Name: "Grace", 4722 Old: "2000000000", 4723 }, 4724 { 4725 Type: DiffTypeDeleted, 4726 Name: "IgnoreWarnings", 4727 Old: "false", 4728 }, 4729 { 4730 Type: DiffTypeDeleted, 4731 Name: "Limit", 4732 Old: "2", 4733 }, 4734 }, 4735 }, 4736 }, 4737 }, 4738 }, 4739 }, 4740 }, 4741 }, 4742 }, 4743 { 4744 Name: "Vault added", 4745 Old: &Task{}, 4746 New: &Task{ 4747 Vault: &Vault{ 4748 Policies: []string{"foo", "bar"}, 4749 Env: true, 4750 ChangeMode: "signal", 4751 ChangeSignal: "SIGUSR1", 4752 }, 4753 }, 4754 Expected: &TaskDiff{ 4755 Type: DiffTypeEdited, 4756 Objects: []*ObjectDiff{ 4757 { 4758 Type: DiffTypeAdded, 4759 Name: "Vault", 4760 Fields: []*FieldDiff{ 4761 { 4762 Type: DiffTypeAdded, 4763 Name: "ChangeMode", 4764 Old: "", 4765 New: "signal", 4766 }, 4767 { 4768 Type: DiffTypeAdded, 4769 Name: "ChangeSignal", 4770 Old: "", 4771 New: "SIGUSR1", 4772 }, 4773 { 4774 Type: DiffTypeAdded, 4775 Name: "Env", 4776 Old: "", 4777 New: "true", 4778 }, 4779 }, 4780 Objects: []*ObjectDiff{ 4781 { 4782 Type: DiffTypeAdded, 4783 Name: "Policies", 4784 Fields: []*FieldDiff{ 4785 { 4786 Type: DiffTypeAdded, 4787 Name: "Policies", 4788 Old: "", 4789 New: "bar", 4790 }, 4791 { 4792 Type: DiffTypeAdded, 4793 Name: "Policies", 4794 Old: "", 4795 New: "foo", 4796 }, 4797 }, 4798 }, 4799 }, 4800 }, 4801 }, 4802 }, 4803 }, 4804 { 4805 Name: "Vault deleted", 4806 Old: &Task{ 4807 Vault: &Vault{ 4808 Policies: []string{"foo", "bar"}, 4809 Env: true, 4810 ChangeMode: "signal", 4811 ChangeSignal: "SIGUSR1", 4812 }, 4813 }, 4814 New: &Task{}, 4815 Expected: &TaskDiff{ 4816 Type: DiffTypeEdited, 4817 Objects: []*ObjectDiff{ 4818 { 4819 Type: DiffTypeDeleted, 4820 Name: "Vault", 4821 Fields: []*FieldDiff{ 4822 { 4823 Type: DiffTypeDeleted, 4824 Name: "ChangeMode", 4825 Old: "signal", 4826 New: "", 4827 }, 4828 { 4829 Type: DiffTypeDeleted, 4830 Name: "ChangeSignal", 4831 Old: "SIGUSR1", 4832 New: "", 4833 }, 4834 { 4835 Type: DiffTypeDeleted, 4836 Name: "Env", 4837 Old: "true", 4838 New: "", 4839 }, 4840 }, 4841 Objects: []*ObjectDiff{ 4842 { 4843 Type: DiffTypeDeleted, 4844 Name: "Policies", 4845 Fields: []*FieldDiff{ 4846 { 4847 Type: DiffTypeDeleted, 4848 Name: "Policies", 4849 Old: "bar", 4850 New: "", 4851 }, 4852 { 4853 Type: DiffTypeDeleted, 4854 Name: "Policies", 4855 Old: "foo", 4856 New: "", 4857 }, 4858 }, 4859 }, 4860 }, 4861 }, 4862 }, 4863 }, 4864 }, 4865 { 4866 Name: "Vault edited", 4867 Old: &Task{ 4868 Vault: &Vault{ 4869 Policies: []string{"foo", "bar"}, 4870 Env: true, 4871 ChangeMode: "signal", 4872 ChangeSignal: "SIGUSR1", 4873 }, 4874 }, 4875 New: &Task{ 4876 Vault: &Vault{ 4877 Policies: []string{"bar", "baz"}, 4878 Env: false, 4879 ChangeMode: "restart", 4880 ChangeSignal: "foo", 4881 }, 4882 }, 4883 Expected: &TaskDiff{ 4884 Type: DiffTypeEdited, 4885 Objects: []*ObjectDiff{ 4886 { 4887 Type: DiffTypeEdited, 4888 Name: "Vault", 4889 Fields: []*FieldDiff{ 4890 { 4891 Type: DiffTypeEdited, 4892 Name: "ChangeMode", 4893 Old: "signal", 4894 New: "restart", 4895 }, 4896 { 4897 Type: DiffTypeEdited, 4898 Name: "ChangeSignal", 4899 Old: "SIGUSR1", 4900 New: "foo", 4901 }, 4902 { 4903 Type: DiffTypeEdited, 4904 Name: "Env", 4905 Old: "true", 4906 New: "false", 4907 }, 4908 }, 4909 Objects: []*ObjectDiff{ 4910 { 4911 Type: DiffTypeEdited, 4912 Name: "Policies", 4913 Fields: []*FieldDiff{ 4914 { 4915 Type: DiffTypeAdded, 4916 Name: "Policies", 4917 Old: "", 4918 New: "baz", 4919 }, 4920 { 4921 Type: DiffTypeDeleted, 4922 Name: "Policies", 4923 Old: "foo", 4924 New: "", 4925 }, 4926 }, 4927 }, 4928 }, 4929 }, 4930 }, 4931 }, 4932 }, 4933 { 4934 Name: "Vault edited with context", 4935 Contextual: true, 4936 Old: &Task{ 4937 Vault: &Vault{ 4938 Policies: []string{"foo", "bar"}, 4939 Env: true, 4940 ChangeMode: "signal", 4941 ChangeSignal: "SIGUSR1", 4942 }, 4943 }, 4944 New: &Task{ 4945 Vault: &Vault{ 4946 Policies: []string{"bar", "baz"}, 4947 Env: true, 4948 ChangeMode: "signal", 4949 ChangeSignal: "SIGUSR1", 4950 }, 4951 }, 4952 Expected: &TaskDiff{ 4953 Type: DiffTypeEdited, 4954 Objects: []*ObjectDiff{ 4955 { 4956 Type: DiffTypeEdited, 4957 Name: "Vault", 4958 Fields: []*FieldDiff{ 4959 { 4960 Type: DiffTypeNone, 4961 Name: "ChangeMode", 4962 Old: "signal", 4963 New: "signal", 4964 }, 4965 { 4966 Type: DiffTypeNone, 4967 Name: "ChangeSignal", 4968 Old: "SIGUSR1", 4969 New: "SIGUSR1", 4970 }, 4971 { 4972 Type: DiffTypeNone, 4973 Name: "Env", 4974 Old: "true", 4975 New: "true", 4976 }, 4977 }, 4978 Objects: []*ObjectDiff{ 4979 { 4980 Type: DiffTypeEdited, 4981 Name: "Policies", 4982 Fields: []*FieldDiff{ 4983 { 4984 Type: DiffTypeAdded, 4985 Name: "Policies", 4986 Old: "", 4987 New: "baz", 4988 }, 4989 { 4990 Type: DiffTypeNone, 4991 Name: "Policies", 4992 Old: "bar", 4993 New: "bar", 4994 }, 4995 { 4996 Type: DiffTypeDeleted, 4997 Name: "Policies", 4998 Old: "foo", 4999 New: "", 5000 }, 5001 }, 5002 }, 5003 }, 5004 }, 5005 }, 5006 }, 5007 }, 5008 { 5009 Name: "Template edited", 5010 Old: &Task{ 5011 Templates: []*Template{ 5012 { 5013 SourcePath: "foo", 5014 DestPath: "bar", 5015 EmbeddedTmpl: "baz", 5016 ChangeMode: "bam", 5017 ChangeSignal: "SIGHUP", 5018 Splay: 1, 5019 Perms: "0644", 5020 VaultGrace: 3 * time.Second, 5021 }, 5022 { 5023 SourcePath: "foo2", 5024 DestPath: "bar2", 5025 EmbeddedTmpl: "baz2", 5026 ChangeMode: "bam2", 5027 ChangeSignal: "SIGHUP2", 5028 Splay: 2, 5029 Perms: "0666", 5030 Envvars: true, 5031 VaultGrace: 5 * time.Second, 5032 }, 5033 }, 5034 }, 5035 New: &Task{ 5036 Templates: []*Template{ 5037 { 5038 SourcePath: "foo", 5039 DestPath: "bar", 5040 EmbeddedTmpl: "baz", 5041 ChangeMode: "bam", 5042 ChangeSignal: "SIGHUP", 5043 Splay: 1, 5044 Perms: "0644", 5045 VaultGrace: 3 * time.Second, 5046 }, 5047 { 5048 SourcePath: "foo3", 5049 DestPath: "bar3", 5050 EmbeddedTmpl: "baz3", 5051 ChangeMode: "bam3", 5052 ChangeSignal: "SIGHUP3", 5053 Splay: 3, 5054 Perms: "0776", 5055 VaultGrace: 10 * time.Second, 5056 }, 5057 }, 5058 }, 5059 Expected: &TaskDiff{ 5060 Type: DiffTypeEdited, 5061 Objects: []*ObjectDiff{ 5062 { 5063 Type: DiffTypeAdded, 5064 Name: "Template", 5065 Fields: []*FieldDiff{ 5066 { 5067 Type: DiffTypeAdded, 5068 Name: "ChangeMode", 5069 Old: "", 5070 New: "bam3", 5071 }, 5072 { 5073 Type: DiffTypeAdded, 5074 Name: "ChangeSignal", 5075 Old: "", 5076 New: "SIGHUP3", 5077 }, 5078 { 5079 Type: DiffTypeAdded, 5080 Name: "DestPath", 5081 Old: "", 5082 New: "bar3", 5083 }, 5084 { 5085 Type: DiffTypeAdded, 5086 Name: "EmbeddedTmpl", 5087 Old: "", 5088 New: "baz3", 5089 }, 5090 { 5091 Type: DiffTypeAdded, 5092 Name: "Envvars", 5093 Old: "", 5094 New: "false", 5095 }, 5096 { 5097 Type: DiffTypeAdded, 5098 Name: "Perms", 5099 Old: "", 5100 New: "0776", 5101 }, 5102 { 5103 Type: DiffTypeAdded, 5104 Name: "SourcePath", 5105 Old: "", 5106 New: "foo3", 5107 }, 5108 { 5109 Type: DiffTypeAdded, 5110 Name: "Splay", 5111 Old: "", 5112 New: "3", 5113 }, 5114 { 5115 Type: DiffTypeAdded, 5116 Name: "VaultGrace", 5117 Old: "", 5118 New: "10000000000", 5119 }, 5120 }, 5121 }, 5122 { 5123 Type: DiffTypeDeleted, 5124 Name: "Template", 5125 Fields: []*FieldDiff{ 5126 { 5127 Type: DiffTypeDeleted, 5128 Name: "ChangeMode", 5129 Old: "bam2", 5130 New: "", 5131 }, 5132 { 5133 Type: DiffTypeDeleted, 5134 Name: "ChangeSignal", 5135 Old: "SIGHUP2", 5136 New: "", 5137 }, 5138 { 5139 Type: DiffTypeDeleted, 5140 Name: "DestPath", 5141 Old: "bar2", 5142 New: "", 5143 }, 5144 { 5145 Type: DiffTypeDeleted, 5146 Name: "EmbeddedTmpl", 5147 Old: "baz2", 5148 New: "", 5149 }, 5150 { 5151 Type: DiffTypeDeleted, 5152 Name: "Envvars", 5153 Old: "true", 5154 New: "", 5155 }, 5156 { 5157 Type: DiffTypeDeleted, 5158 Name: "Perms", 5159 Old: "0666", 5160 New: "", 5161 }, 5162 { 5163 Type: DiffTypeDeleted, 5164 Name: "SourcePath", 5165 Old: "foo2", 5166 New: "", 5167 }, 5168 { 5169 Type: DiffTypeDeleted, 5170 Name: "Splay", 5171 Old: "2", 5172 New: "", 5173 }, 5174 { 5175 Type: DiffTypeDeleted, 5176 Name: "VaultGrace", 5177 Old: "5000000000", 5178 New: "", 5179 }, 5180 }, 5181 }, 5182 }, 5183 }, 5184 }, 5185 { 5186 Name: "DispatchPayload added", 5187 Old: &Task{}, 5188 New: &Task{ 5189 DispatchPayload: &DispatchPayloadConfig{ 5190 File: "foo", 5191 }, 5192 }, 5193 Expected: &TaskDiff{ 5194 Type: DiffTypeEdited, 5195 Objects: []*ObjectDiff{ 5196 { 5197 Type: DiffTypeAdded, 5198 Name: "DispatchPayload", 5199 Fields: []*FieldDiff{ 5200 { 5201 Type: DiffTypeAdded, 5202 Name: "File", 5203 Old: "", 5204 New: "foo", 5205 }, 5206 }, 5207 }, 5208 }, 5209 }, 5210 }, 5211 { 5212 Name: "DispatchPayload deleted", 5213 Old: &Task{ 5214 DispatchPayload: &DispatchPayloadConfig{ 5215 File: "foo", 5216 }, 5217 }, 5218 New: &Task{}, 5219 Expected: &TaskDiff{ 5220 Type: DiffTypeEdited, 5221 Objects: []*ObjectDiff{ 5222 { 5223 Type: DiffTypeDeleted, 5224 Name: "DispatchPayload", 5225 Fields: []*FieldDiff{ 5226 { 5227 Type: DiffTypeDeleted, 5228 Name: "File", 5229 Old: "foo", 5230 New: "", 5231 }, 5232 }, 5233 }, 5234 }, 5235 }, 5236 }, 5237 { 5238 Name: "Dispatch payload edited", 5239 Old: &Task{ 5240 DispatchPayload: &DispatchPayloadConfig{ 5241 File: "foo", 5242 }, 5243 }, 5244 New: &Task{ 5245 DispatchPayload: &DispatchPayloadConfig{ 5246 File: "bar", 5247 }, 5248 }, 5249 Expected: &TaskDiff{ 5250 Type: DiffTypeEdited, 5251 Objects: []*ObjectDiff{ 5252 { 5253 Type: DiffTypeEdited, 5254 Name: "DispatchPayload", 5255 Fields: []*FieldDiff{ 5256 { 5257 Type: DiffTypeEdited, 5258 Name: "File", 5259 Old: "foo", 5260 New: "bar", 5261 }, 5262 }, 5263 }, 5264 }, 5265 }, 5266 }, 5267 { 5268 // Place holder for if more fields are added 5269 Name: "DispatchPayload edited with context", 5270 Contextual: true, 5271 Old: &Task{ 5272 DispatchPayload: &DispatchPayloadConfig{ 5273 File: "foo", 5274 }, 5275 }, 5276 New: &Task{ 5277 DispatchPayload: &DispatchPayloadConfig{ 5278 File: "bar", 5279 }, 5280 }, 5281 Expected: &TaskDiff{ 5282 Type: DiffTypeEdited, 5283 Objects: []*ObjectDiff{ 5284 { 5285 Type: DiffTypeEdited, 5286 Name: "DispatchPayload", 5287 Fields: []*FieldDiff{ 5288 { 5289 Type: DiffTypeEdited, 5290 Name: "File", 5291 Old: "foo", 5292 New: "bar", 5293 }, 5294 }, 5295 }, 5296 }, 5297 }, 5298 }, 5299 } 5300 5301 for i, c := range cases { 5302 t.Run(c.Name, func(t *testing.T) { 5303 actual, err := c.Old.Diff(c.New, c.Contextual) 5304 if c.Error && err == nil { 5305 t.Fatalf("case %d: expected errored", i+1) 5306 } else if err != nil { 5307 if !c.Error { 5308 t.Fatalf("case %d: errored %#v", i+1, err) 5309 } else { 5310 return 5311 } 5312 } 5313 5314 if !reflect.DeepEqual(actual, c.Expected) { 5315 t.Errorf("case %d: got:\n%#v\n want:\n%#v\n", 5316 i+1, actual, c.Expected) 5317 } 5318 }) 5319 } 5320 }