github.com/hhrutter/nomad@v0.6.0-rc2.0.20170723054333-80c4b03f0705/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: "Meta[foo]", 156 Old: "bar", 157 New: "", 158 }, 159 { 160 Type: DiffTypeDeleted, 161 Name: "Name", 162 Old: "foo", 163 New: "", 164 }, 165 { 166 Type: DiffTypeDeleted, 167 Name: "Priority", 168 Old: "10", 169 New: "", 170 }, 171 { 172 Type: DiffTypeDeleted, 173 Name: "Region", 174 Old: "foo", 175 New: "", 176 }, 177 { 178 Type: DiffTypeDeleted, 179 Name: "Stop", 180 Old: "false", 181 New: "", 182 }, 183 { 184 Type: DiffTypeDeleted, 185 Name: "Type", 186 Old: "batch", 187 New: "", 188 }, 189 }, 190 }, 191 }, 192 { 193 // Primitive only added job 194 Old: nil, 195 New: &Job{ 196 Region: "foo", 197 ID: "foo", 198 Name: "foo", 199 Type: "batch", 200 Priority: 10, 201 AllAtOnce: true, 202 Meta: map[string]string{ 203 "foo": "bar", 204 }, 205 }, 206 Expected: &JobDiff{ 207 Type: DiffTypeAdded, 208 ID: "foo", 209 Fields: []*FieldDiff{ 210 { 211 Type: DiffTypeAdded, 212 Name: "AllAtOnce", 213 Old: "", 214 New: "true", 215 }, 216 { 217 Type: DiffTypeAdded, 218 Name: "Meta[foo]", 219 Old: "", 220 New: "bar", 221 }, 222 { 223 Type: DiffTypeAdded, 224 Name: "Name", 225 Old: "", 226 New: "foo", 227 }, 228 { 229 Type: DiffTypeAdded, 230 Name: "Priority", 231 Old: "", 232 New: "10", 233 }, 234 { 235 Type: DiffTypeAdded, 236 Name: "Region", 237 Old: "", 238 New: "foo", 239 }, 240 { 241 Type: DiffTypeAdded, 242 Name: "Stop", 243 Old: "", 244 New: "false", 245 }, 246 { 247 Type: DiffTypeAdded, 248 Name: "Type", 249 Old: "", 250 New: "batch", 251 }, 252 }, 253 }, 254 }, 255 { 256 // Map diff 257 Old: &Job{ 258 Meta: map[string]string{ 259 "foo": "foo", 260 "bar": "bar", 261 }, 262 }, 263 New: &Job{ 264 Meta: map[string]string{ 265 "bar": "bar", 266 "baz": "baz", 267 }, 268 }, 269 Expected: &JobDiff{ 270 Type: DiffTypeEdited, 271 Fields: []*FieldDiff{ 272 { 273 Type: DiffTypeAdded, 274 Name: "Meta[baz]", 275 Old: "", 276 New: "baz", 277 }, 278 { 279 Type: DiffTypeDeleted, 280 Name: "Meta[foo]", 281 Old: "foo", 282 New: "", 283 }, 284 }, 285 }, 286 }, 287 { 288 // Datacenter diff both added and removed 289 Old: &Job{ 290 Datacenters: []string{"foo", "bar"}, 291 }, 292 New: &Job{ 293 Datacenters: []string{"baz", "bar"}, 294 }, 295 Expected: &JobDiff{ 296 Type: DiffTypeEdited, 297 Objects: []*ObjectDiff{ 298 { 299 Type: DiffTypeEdited, 300 Name: "Datacenters", 301 Fields: []*FieldDiff{ 302 { 303 Type: DiffTypeAdded, 304 Name: "Datacenters", 305 Old: "", 306 New: "baz", 307 }, 308 { 309 Type: DiffTypeDeleted, 310 Name: "Datacenters", 311 Old: "foo", 312 New: "", 313 }, 314 }, 315 }, 316 }, 317 }, 318 }, 319 { 320 // Datacenter diff just added 321 Old: &Job{ 322 Datacenters: []string{"foo", "bar"}, 323 }, 324 New: &Job{ 325 Datacenters: []string{"foo", "bar", "baz"}, 326 }, 327 Expected: &JobDiff{ 328 Type: DiffTypeEdited, 329 Objects: []*ObjectDiff{ 330 { 331 Type: DiffTypeAdded, 332 Name: "Datacenters", 333 Fields: []*FieldDiff{ 334 { 335 Type: DiffTypeAdded, 336 Name: "Datacenters", 337 Old: "", 338 New: "baz", 339 }, 340 }, 341 }, 342 }, 343 }, 344 }, 345 { 346 // Datacenter diff just deleted 347 Old: &Job{ 348 Datacenters: []string{"foo", "bar"}, 349 }, 350 New: &Job{ 351 Datacenters: []string{"foo"}, 352 }, 353 Expected: &JobDiff{ 354 Type: DiffTypeEdited, 355 Objects: []*ObjectDiff{ 356 { 357 Type: DiffTypeDeleted, 358 Name: "Datacenters", 359 Fields: []*FieldDiff{ 360 { 361 Type: DiffTypeDeleted, 362 Name: "Datacenters", 363 Old: "bar", 364 New: "", 365 }, 366 }, 367 }, 368 }, 369 }, 370 }, 371 { 372 // Datacenter contextual no change 373 Contextual: true, 374 Old: &Job{ 375 Datacenters: []string{"foo", "bar"}, 376 }, 377 New: &Job{ 378 Datacenters: []string{"foo", "bar"}, 379 }, 380 Expected: &JobDiff{ 381 Type: DiffTypeNone, 382 }, 383 }, 384 { 385 // Datacenter contextual 386 Contextual: true, 387 Old: &Job{ 388 Datacenters: []string{"foo", "bar"}, 389 }, 390 New: &Job{ 391 Datacenters: []string{"foo", "bar", "baz"}, 392 }, 393 Expected: &JobDiff{ 394 Type: DiffTypeEdited, 395 Objects: []*ObjectDiff{ 396 { 397 Type: DiffTypeAdded, 398 Name: "Datacenters", 399 Fields: []*FieldDiff{ 400 { 401 Type: DiffTypeAdded, 402 Name: "Datacenters", 403 Old: "", 404 New: "baz", 405 }, 406 { 407 Type: DiffTypeNone, 408 Name: "Datacenters", 409 Old: "bar", 410 New: "bar", 411 }, 412 { 413 Type: DiffTypeNone, 414 Name: "Datacenters", 415 Old: "foo", 416 New: "foo", 417 }, 418 }, 419 }, 420 }, 421 }, 422 }, 423 { 424 // Periodic added 425 Old: &Job{}, 426 New: &Job{ 427 Periodic: &PeriodicConfig{ 428 Enabled: false, 429 Spec: "*/15 * * * * *", 430 SpecType: "foo", 431 ProhibitOverlap: false, 432 TimeZone: "Europe/Minsk", 433 }, 434 }, 435 Expected: &JobDiff{ 436 Type: DiffTypeEdited, 437 Objects: []*ObjectDiff{ 438 { 439 Type: DiffTypeAdded, 440 Name: "Periodic", 441 Fields: []*FieldDiff{ 442 { 443 Type: DiffTypeAdded, 444 Name: "Enabled", 445 Old: "", 446 New: "false", 447 }, 448 { 449 Type: DiffTypeAdded, 450 Name: "ProhibitOverlap", 451 Old: "", 452 New: "false", 453 }, 454 { 455 Type: DiffTypeAdded, 456 Name: "Spec", 457 Old: "", 458 New: "*/15 * * * * *", 459 }, 460 { 461 Type: DiffTypeAdded, 462 Name: "SpecType", 463 Old: "", 464 New: "foo", 465 }, 466 { 467 Type: DiffTypeAdded, 468 Name: "TimeZone", 469 Old: "", 470 New: "Europe/Minsk", 471 }, 472 }, 473 }, 474 }, 475 }, 476 }, 477 { 478 // Periodic deleted 479 Old: &Job{ 480 Periodic: &PeriodicConfig{ 481 Enabled: false, 482 Spec: "*/15 * * * * *", 483 SpecType: "foo", 484 ProhibitOverlap: false, 485 TimeZone: "Europe/Minsk", 486 }, 487 }, 488 New: &Job{}, 489 Expected: &JobDiff{ 490 Type: DiffTypeEdited, 491 Objects: []*ObjectDiff{ 492 { 493 Type: DiffTypeDeleted, 494 Name: "Periodic", 495 Fields: []*FieldDiff{ 496 { 497 Type: DiffTypeDeleted, 498 Name: "Enabled", 499 Old: "false", 500 New: "", 501 }, 502 { 503 Type: DiffTypeDeleted, 504 Name: "ProhibitOverlap", 505 Old: "false", 506 New: "", 507 }, 508 { 509 Type: DiffTypeDeleted, 510 Name: "Spec", 511 Old: "*/15 * * * * *", 512 New: "", 513 }, 514 { 515 Type: DiffTypeDeleted, 516 Name: "SpecType", 517 Old: "foo", 518 New: "", 519 }, 520 { 521 Type: DiffTypeDeleted, 522 Name: "TimeZone", 523 Old: "Europe/Minsk", 524 New: "", 525 }, 526 }, 527 }, 528 }, 529 }, 530 }, 531 { 532 // Periodic edited 533 Old: &Job{ 534 Periodic: &PeriodicConfig{ 535 Enabled: false, 536 Spec: "*/15 * * * * *", 537 SpecType: "foo", 538 ProhibitOverlap: false, 539 TimeZone: "Europe/Minsk", 540 }, 541 }, 542 New: &Job{ 543 Periodic: &PeriodicConfig{ 544 Enabled: true, 545 Spec: "* * * * * *", 546 SpecType: "cron", 547 ProhibitOverlap: true, 548 TimeZone: "America/Los_Angeles", 549 }, 550 }, 551 Expected: &JobDiff{ 552 Type: DiffTypeEdited, 553 Objects: []*ObjectDiff{ 554 { 555 Type: DiffTypeEdited, 556 Name: "Periodic", 557 Fields: []*FieldDiff{ 558 { 559 Type: DiffTypeEdited, 560 Name: "Enabled", 561 Old: "false", 562 New: "true", 563 }, 564 { 565 Type: DiffTypeEdited, 566 Name: "ProhibitOverlap", 567 Old: "false", 568 New: "true", 569 }, 570 { 571 Type: DiffTypeEdited, 572 Name: "Spec", 573 Old: "*/15 * * * * *", 574 New: "* * * * * *", 575 }, 576 { 577 Type: DiffTypeEdited, 578 Name: "SpecType", 579 Old: "foo", 580 New: "cron", 581 }, 582 { 583 Type: DiffTypeEdited, 584 Name: "TimeZone", 585 Old: "Europe/Minsk", 586 New: "America/Los_Angeles", 587 }, 588 }, 589 }, 590 }, 591 }, 592 }, 593 { 594 // Periodic edited with context 595 Contextual: true, 596 Old: &Job{ 597 Periodic: &PeriodicConfig{ 598 Enabled: false, 599 Spec: "*/15 * * * * *", 600 SpecType: "foo", 601 ProhibitOverlap: false, 602 TimeZone: "Europe/Minsk", 603 }, 604 }, 605 New: &Job{ 606 Periodic: &PeriodicConfig{ 607 Enabled: true, 608 Spec: "* * * * * *", 609 SpecType: "foo", 610 ProhibitOverlap: false, 611 TimeZone: "Europe/Minsk", 612 }, 613 }, 614 Expected: &JobDiff{ 615 Type: DiffTypeEdited, 616 Objects: []*ObjectDiff{ 617 { 618 Type: DiffTypeEdited, 619 Name: "Periodic", 620 Fields: []*FieldDiff{ 621 { 622 Type: DiffTypeEdited, 623 Name: "Enabled", 624 Old: "false", 625 New: "true", 626 }, 627 { 628 Type: DiffTypeNone, 629 Name: "ProhibitOverlap", 630 Old: "false", 631 New: "false", 632 }, 633 { 634 Type: DiffTypeEdited, 635 Name: "Spec", 636 Old: "*/15 * * * * *", 637 New: "* * * * * *", 638 }, 639 { 640 Type: DiffTypeNone, 641 Name: "SpecType", 642 Old: "foo", 643 New: "foo", 644 }, 645 { 646 Type: DiffTypeNone, 647 Name: "TimeZone", 648 Old: "Europe/Minsk", 649 New: "Europe/Minsk", 650 }, 651 }, 652 }, 653 }, 654 }, 655 }, 656 { 657 // Constraints edited 658 Old: &Job{ 659 Constraints: []*Constraint{ 660 { 661 LTarget: "foo", 662 RTarget: "foo", 663 Operand: "foo", 664 str: "foo", 665 }, 666 { 667 LTarget: "bar", 668 RTarget: "bar", 669 Operand: "bar", 670 str: "bar", 671 }, 672 }, 673 }, 674 New: &Job{ 675 Constraints: []*Constraint{ 676 { 677 LTarget: "foo", 678 RTarget: "foo", 679 Operand: "foo", 680 str: "foo", 681 }, 682 { 683 LTarget: "baz", 684 RTarget: "baz", 685 Operand: "baz", 686 str: "baz", 687 }, 688 }, 689 }, 690 Expected: &JobDiff{ 691 Type: DiffTypeEdited, 692 Objects: []*ObjectDiff{ 693 { 694 Type: DiffTypeAdded, 695 Name: "Constraint", 696 Fields: []*FieldDiff{ 697 { 698 Type: DiffTypeAdded, 699 Name: "LTarget", 700 Old: "", 701 New: "baz", 702 }, 703 { 704 Type: DiffTypeAdded, 705 Name: "Operand", 706 Old: "", 707 New: "baz", 708 }, 709 { 710 Type: DiffTypeAdded, 711 Name: "RTarget", 712 Old: "", 713 New: "baz", 714 }, 715 }, 716 }, 717 { 718 Type: DiffTypeDeleted, 719 Name: "Constraint", 720 Fields: []*FieldDiff{ 721 { 722 Type: DiffTypeDeleted, 723 Name: "LTarget", 724 Old: "bar", 725 New: "", 726 }, 727 { 728 Type: DiffTypeDeleted, 729 Name: "Operand", 730 Old: "bar", 731 New: "", 732 }, 733 { 734 Type: DiffTypeDeleted, 735 Name: "RTarget", 736 Old: "bar", 737 New: "", 738 }, 739 }, 740 }, 741 }, 742 }, 743 }, 744 { 745 // Task groups edited 746 Old: &Job{ 747 TaskGroups: []*TaskGroup{ 748 { 749 Name: "foo", 750 Count: 1, 751 }, 752 { 753 Name: "bar", 754 Count: 1, 755 }, 756 { 757 Name: "baz", 758 Count: 1, 759 }, 760 }, 761 }, 762 New: &Job{ 763 TaskGroups: []*TaskGroup{ 764 { 765 Name: "bar", 766 Count: 1, 767 }, 768 { 769 Name: "baz", 770 Count: 2, 771 }, 772 { 773 Name: "bam", 774 Count: 1, 775 }, 776 }, 777 }, 778 Expected: &JobDiff{ 779 Type: DiffTypeEdited, 780 TaskGroups: []*TaskGroupDiff{ 781 { 782 Type: DiffTypeAdded, 783 Name: "bam", 784 Fields: []*FieldDiff{ 785 { 786 Type: DiffTypeAdded, 787 Name: "Count", 788 Old: "", 789 New: "1", 790 }, 791 }, 792 }, 793 { 794 Type: DiffTypeNone, 795 Name: "bar", 796 }, 797 { 798 Type: DiffTypeEdited, 799 Name: "baz", 800 Fields: []*FieldDiff{ 801 { 802 Type: DiffTypeEdited, 803 Name: "Count", 804 Old: "1", 805 New: "2", 806 }, 807 }, 808 }, 809 { 810 Type: DiffTypeDeleted, 811 Name: "foo", 812 Fields: []*FieldDiff{ 813 { 814 Type: DiffTypeDeleted, 815 Name: "Count", 816 Old: "1", 817 New: "", 818 }, 819 }, 820 }, 821 }, 822 }, 823 }, 824 { 825 // Parameterized Job added 826 Old: &Job{}, 827 New: &Job{ 828 ParameterizedJob: &ParameterizedJobConfig{ 829 Payload: DispatchPayloadRequired, 830 MetaOptional: []string{"foo"}, 831 MetaRequired: []string{"bar"}, 832 }, 833 }, 834 Expected: &JobDiff{ 835 Type: DiffTypeEdited, 836 Objects: []*ObjectDiff{ 837 { 838 Type: DiffTypeAdded, 839 Name: "ParameterizedJob", 840 Fields: []*FieldDiff{ 841 { 842 Type: DiffTypeAdded, 843 Name: "Payload", 844 Old: "", 845 New: DispatchPayloadRequired, 846 }, 847 }, 848 Objects: []*ObjectDiff{ 849 { 850 Type: DiffTypeAdded, 851 Name: "MetaOptional", 852 Fields: []*FieldDiff{ 853 { 854 Type: DiffTypeAdded, 855 Name: "MetaOptional", 856 Old: "", 857 New: "foo", 858 }, 859 }, 860 }, 861 { 862 Type: DiffTypeAdded, 863 Name: "MetaRequired", 864 Fields: []*FieldDiff{ 865 { 866 Type: DiffTypeAdded, 867 Name: "MetaRequired", 868 Old: "", 869 New: "bar", 870 }, 871 }, 872 }, 873 }, 874 }, 875 }, 876 }, 877 }, 878 { 879 // Parameterized Job deleted 880 Old: &Job{ 881 ParameterizedJob: &ParameterizedJobConfig{ 882 Payload: DispatchPayloadRequired, 883 MetaOptional: []string{"foo"}, 884 MetaRequired: []string{"bar"}, 885 }, 886 }, 887 New: &Job{}, 888 Expected: &JobDiff{ 889 Type: DiffTypeEdited, 890 Objects: []*ObjectDiff{ 891 { 892 Type: DiffTypeDeleted, 893 Name: "ParameterizedJob", 894 Fields: []*FieldDiff{ 895 { 896 Type: DiffTypeDeleted, 897 Name: "Payload", 898 Old: DispatchPayloadRequired, 899 New: "", 900 }, 901 }, 902 Objects: []*ObjectDiff{ 903 { 904 Type: DiffTypeDeleted, 905 Name: "MetaOptional", 906 Fields: []*FieldDiff{ 907 { 908 Type: DiffTypeDeleted, 909 Name: "MetaOptional", 910 Old: "foo", 911 New: "", 912 }, 913 }, 914 }, 915 { 916 Type: DiffTypeDeleted, 917 Name: "MetaRequired", 918 Fields: []*FieldDiff{ 919 { 920 Type: DiffTypeDeleted, 921 Name: "MetaRequired", 922 Old: "bar", 923 New: "", 924 }, 925 }, 926 }, 927 }, 928 }, 929 }, 930 }, 931 }, 932 { 933 // Parameterized Job edited 934 Old: &Job{ 935 ParameterizedJob: &ParameterizedJobConfig{ 936 Payload: DispatchPayloadRequired, 937 MetaOptional: []string{"foo"}, 938 MetaRequired: []string{"bar"}, 939 }, 940 }, 941 New: &Job{ 942 ParameterizedJob: &ParameterizedJobConfig{ 943 Payload: DispatchPayloadOptional, 944 MetaOptional: []string{"bam"}, 945 MetaRequired: []string{"bang"}, 946 }, 947 }, 948 Expected: &JobDiff{ 949 Type: DiffTypeEdited, 950 Objects: []*ObjectDiff{ 951 { 952 Type: DiffTypeEdited, 953 Name: "ParameterizedJob", 954 Fields: []*FieldDiff{ 955 { 956 Type: DiffTypeEdited, 957 Name: "Payload", 958 Old: DispatchPayloadRequired, 959 New: DispatchPayloadOptional, 960 }, 961 }, 962 Objects: []*ObjectDiff{ 963 { 964 Type: DiffTypeEdited, 965 Name: "MetaOptional", 966 Fields: []*FieldDiff{ 967 { 968 Type: DiffTypeAdded, 969 Name: "MetaOptional", 970 Old: "", 971 New: "bam", 972 }, 973 { 974 Type: DiffTypeDeleted, 975 Name: "MetaOptional", 976 Old: "foo", 977 New: "", 978 }, 979 }, 980 }, 981 { 982 Type: DiffTypeEdited, 983 Name: "MetaRequired", 984 Fields: []*FieldDiff{ 985 { 986 Type: DiffTypeAdded, 987 Name: "MetaRequired", 988 Old: "", 989 New: "bang", 990 }, 991 { 992 Type: DiffTypeDeleted, 993 Name: "MetaRequired", 994 Old: "bar", 995 New: "", 996 }, 997 }, 998 }, 999 }, 1000 }, 1001 }, 1002 }, 1003 }, 1004 { 1005 // Parameterized Job edited with context 1006 Contextual: true, 1007 Old: &Job{ 1008 ParameterizedJob: &ParameterizedJobConfig{ 1009 Payload: DispatchPayloadRequired, 1010 MetaOptional: []string{"foo"}, 1011 MetaRequired: []string{"bar"}, 1012 }, 1013 }, 1014 New: &Job{ 1015 ParameterizedJob: &ParameterizedJobConfig{ 1016 Payload: DispatchPayloadOptional, 1017 MetaOptional: []string{"foo"}, 1018 MetaRequired: []string{"bar"}, 1019 }, 1020 }, 1021 Expected: &JobDiff{ 1022 Type: DiffTypeEdited, 1023 Objects: []*ObjectDiff{ 1024 { 1025 Type: DiffTypeEdited, 1026 Name: "ParameterizedJob", 1027 Fields: []*FieldDiff{ 1028 { 1029 Type: DiffTypeEdited, 1030 Name: "Payload", 1031 Old: DispatchPayloadRequired, 1032 New: DispatchPayloadOptional, 1033 }, 1034 }, 1035 Objects: []*ObjectDiff{ 1036 { 1037 Type: DiffTypeNone, 1038 Name: "MetaOptional", 1039 Fields: []*FieldDiff{ 1040 { 1041 Type: DiffTypeNone, 1042 Name: "MetaOptional", 1043 Old: "foo", 1044 New: "foo", 1045 }, 1046 }, 1047 }, 1048 { 1049 Type: DiffTypeNone, 1050 Name: "MetaRequired", 1051 Fields: []*FieldDiff{ 1052 { 1053 Type: DiffTypeNone, 1054 Name: "MetaRequired", 1055 Old: "bar", 1056 New: "bar", 1057 }, 1058 }, 1059 }, 1060 }, 1061 }, 1062 }, 1063 }, 1064 }, 1065 } 1066 1067 for i, c := range cases { 1068 actual, err := c.Old.Diff(c.New, c.Contextual) 1069 if c.Error && err == nil { 1070 t.Fatalf("case %d: expected errored", i+1) 1071 } else if err != nil { 1072 if !c.Error { 1073 t.Fatalf("case %d: errored %#v", i+1, err) 1074 } else { 1075 continue 1076 } 1077 } 1078 1079 if !reflect.DeepEqual(actual, c.Expected) { 1080 t.Fatalf("case %d: got:\n%#v\n want:\n%#v\n", 1081 i+1, actual, c.Expected) 1082 } 1083 } 1084 } 1085 1086 func TestTaskGroupDiff(t *testing.T) { 1087 cases := []struct { 1088 Old, New *TaskGroup 1089 Expected *TaskGroupDiff 1090 Error bool 1091 Contextual bool 1092 }{ 1093 { 1094 Old: nil, 1095 New: nil, 1096 Expected: &TaskGroupDiff{ 1097 Type: DiffTypeNone, 1098 }, 1099 }, 1100 { 1101 // Primitive only that has different names 1102 Old: &TaskGroup{ 1103 Name: "foo", 1104 Count: 10, 1105 Meta: map[string]string{ 1106 "foo": "bar", 1107 }, 1108 }, 1109 New: &TaskGroup{ 1110 Name: "bar", 1111 Count: 10, 1112 Meta: map[string]string{ 1113 "foo": "bar", 1114 }, 1115 }, 1116 Error: true, 1117 }, 1118 { 1119 // Primitive only that is the same 1120 Old: &TaskGroup{ 1121 Name: "foo", 1122 Count: 10, 1123 Meta: map[string]string{ 1124 "foo": "bar", 1125 }, 1126 }, 1127 New: &TaskGroup{ 1128 Name: "foo", 1129 Count: 10, 1130 Meta: map[string]string{ 1131 "foo": "bar", 1132 }, 1133 }, 1134 Expected: &TaskGroupDiff{ 1135 Type: DiffTypeNone, 1136 Name: "foo", 1137 }, 1138 }, 1139 { 1140 // Primitive only that has diffs 1141 Old: &TaskGroup{ 1142 Name: "foo", 1143 Count: 10, 1144 Meta: map[string]string{ 1145 "foo": "bar", 1146 }, 1147 }, 1148 New: &TaskGroup{ 1149 Name: "foo", 1150 Count: 100, 1151 Meta: map[string]string{ 1152 "foo": "baz", 1153 }, 1154 }, 1155 Expected: &TaskGroupDiff{ 1156 Type: DiffTypeEdited, 1157 Name: "foo", 1158 Fields: []*FieldDiff{ 1159 { 1160 Type: DiffTypeEdited, 1161 Name: "Count", 1162 Old: "10", 1163 New: "100", 1164 }, 1165 { 1166 Type: DiffTypeEdited, 1167 Name: "Meta[foo]", 1168 Old: "bar", 1169 New: "baz", 1170 }, 1171 }, 1172 }, 1173 }, 1174 { 1175 // Map diff 1176 Old: &TaskGroup{ 1177 Meta: map[string]string{ 1178 "foo": "foo", 1179 "bar": "bar", 1180 }, 1181 }, 1182 New: &TaskGroup{ 1183 Meta: map[string]string{ 1184 "bar": "bar", 1185 "baz": "baz", 1186 }, 1187 }, 1188 Expected: &TaskGroupDiff{ 1189 Type: DiffTypeEdited, 1190 Fields: []*FieldDiff{ 1191 { 1192 Type: DiffTypeAdded, 1193 Name: "Meta[baz]", 1194 Old: "", 1195 New: "baz", 1196 }, 1197 { 1198 Type: DiffTypeDeleted, 1199 Name: "Meta[foo]", 1200 Old: "foo", 1201 New: "", 1202 }, 1203 }, 1204 }, 1205 }, 1206 { 1207 // Constraints edited 1208 Old: &TaskGroup{ 1209 Constraints: []*Constraint{ 1210 { 1211 LTarget: "foo", 1212 RTarget: "foo", 1213 Operand: "foo", 1214 str: "foo", 1215 }, 1216 { 1217 LTarget: "bar", 1218 RTarget: "bar", 1219 Operand: "bar", 1220 str: "bar", 1221 }, 1222 }, 1223 }, 1224 New: &TaskGroup{ 1225 Constraints: []*Constraint{ 1226 { 1227 LTarget: "foo", 1228 RTarget: "foo", 1229 Operand: "foo", 1230 str: "foo", 1231 }, 1232 { 1233 LTarget: "baz", 1234 RTarget: "baz", 1235 Operand: "baz", 1236 str: "baz", 1237 }, 1238 }, 1239 }, 1240 Expected: &TaskGroupDiff{ 1241 Type: DiffTypeEdited, 1242 Objects: []*ObjectDiff{ 1243 { 1244 Type: DiffTypeAdded, 1245 Name: "Constraint", 1246 Fields: []*FieldDiff{ 1247 { 1248 Type: DiffTypeAdded, 1249 Name: "LTarget", 1250 Old: "", 1251 New: "baz", 1252 }, 1253 { 1254 Type: DiffTypeAdded, 1255 Name: "Operand", 1256 Old: "", 1257 New: "baz", 1258 }, 1259 { 1260 Type: DiffTypeAdded, 1261 Name: "RTarget", 1262 Old: "", 1263 New: "baz", 1264 }, 1265 }, 1266 }, 1267 { 1268 Type: DiffTypeDeleted, 1269 Name: "Constraint", 1270 Fields: []*FieldDiff{ 1271 { 1272 Type: DiffTypeDeleted, 1273 Name: "LTarget", 1274 Old: "bar", 1275 New: "", 1276 }, 1277 { 1278 Type: DiffTypeDeleted, 1279 Name: "Operand", 1280 Old: "bar", 1281 New: "", 1282 }, 1283 { 1284 Type: DiffTypeDeleted, 1285 Name: "RTarget", 1286 Old: "bar", 1287 New: "", 1288 }, 1289 }, 1290 }, 1291 }, 1292 }, 1293 }, 1294 { 1295 // RestartPolicy added 1296 Old: &TaskGroup{}, 1297 New: &TaskGroup{ 1298 RestartPolicy: &RestartPolicy{ 1299 Attempts: 1, 1300 Interval: 1 * time.Second, 1301 Delay: 1 * time.Second, 1302 Mode: "fail", 1303 }, 1304 }, 1305 Expected: &TaskGroupDiff{ 1306 Type: DiffTypeEdited, 1307 Objects: []*ObjectDiff{ 1308 { 1309 Type: DiffTypeAdded, 1310 Name: "RestartPolicy", 1311 Fields: []*FieldDiff{ 1312 { 1313 Type: DiffTypeAdded, 1314 Name: "Attempts", 1315 Old: "", 1316 New: "1", 1317 }, 1318 { 1319 Type: DiffTypeAdded, 1320 Name: "Delay", 1321 Old: "", 1322 New: "1000000000", 1323 }, 1324 { 1325 Type: DiffTypeAdded, 1326 Name: "Interval", 1327 Old: "", 1328 New: "1000000000", 1329 }, 1330 { 1331 Type: DiffTypeAdded, 1332 Name: "Mode", 1333 Old: "", 1334 New: "fail", 1335 }, 1336 }, 1337 }, 1338 }, 1339 }, 1340 }, 1341 { 1342 // RestartPolicy deleted 1343 Old: &TaskGroup{ 1344 RestartPolicy: &RestartPolicy{ 1345 Attempts: 1, 1346 Interval: 1 * time.Second, 1347 Delay: 1 * time.Second, 1348 Mode: "fail", 1349 }, 1350 }, 1351 New: &TaskGroup{}, 1352 Expected: &TaskGroupDiff{ 1353 Type: DiffTypeEdited, 1354 Objects: []*ObjectDiff{ 1355 { 1356 Type: DiffTypeDeleted, 1357 Name: "RestartPolicy", 1358 Fields: []*FieldDiff{ 1359 { 1360 Type: DiffTypeDeleted, 1361 Name: "Attempts", 1362 Old: "1", 1363 New: "", 1364 }, 1365 { 1366 Type: DiffTypeDeleted, 1367 Name: "Delay", 1368 Old: "1000000000", 1369 New: "", 1370 }, 1371 { 1372 Type: DiffTypeDeleted, 1373 Name: "Interval", 1374 Old: "1000000000", 1375 New: "", 1376 }, 1377 { 1378 Type: DiffTypeDeleted, 1379 Name: "Mode", 1380 Old: "fail", 1381 New: "", 1382 }, 1383 }, 1384 }, 1385 }, 1386 }, 1387 }, 1388 { 1389 // RestartPolicy edited 1390 Old: &TaskGroup{ 1391 RestartPolicy: &RestartPolicy{ 1392 Attempts: 1, 1393 Interval: 1 * time.Second, 1394 Delay: 1 * time.Second, 1395 Mode: "fail", 1396 }, 1397 }, 1398 New: &TaskGroup{ 1399 RestartPolicy: &RestartPolicy{ 1400 Attempts: 2, 1401 Interval: 2 * time.Second, 1402 Delay: 2 * time.Second, 1403 Mode: "delay", 1404 }, 1405 }, 1406 Expected: &TaskGroupDiff{ 1407 Type: DiffTypeEdited, 1408 Objects: []*ObjectDiff{ 1409 { 1410 Type: DiffTypeEdited, 1411 Name: "RestartPolicy", 1412 Fields: []*FieldDiff{ 1413 { 1414 Type: DiffTypeEdited, 1415 Name: "Attempts", 1416 Old: "1", 1417 New: "2", 1418 }, 1419 { 1420 Type: DiffTypeEdited, 1421 Name: "Delay", 1422 Old: "1000000000", 1423 New: "2000000000", 1424 }, 1425 { 1426 Type: DiffTypeEdited, 1427 Name: "Interval", 1428 Old: "1000000000", 1429 New: "2000000000", 1430 }, 1431 { 1432 Type: DiffTypeEdited, 1433 Name: "Mode", 1434 Old: "fail", 1435 New: "delay", 1436 }, 1437 }, 1438 }, 1439 }, 1440 }, 1441 }, 1442 { 1443 // RestartPolicy edited with context 1444 Contextual: true, 1445 Old: &TaskGroup{ 1446 RestartPolicy: &RestartPolicy{ 1447 Attempts: 1, 1448 Interval: 1 * time.Second, 1449 Delay: 1 * time.Second, 1450 Mode: "fail", 1451 }, 1452 }, 1453 New: &TaskGroup{ 1454 RestartPolicy: &RestartPolicy{ 1455 Attempts: 2, 1456 Interval: 2 * time.Second, 1457 Delay: 1 * time.Second, 1458 Mode: "fail", 1459 }, 1460 }, 1461 Expected: &TaskGroupDiff{ 1462 Type: DiffTypeEdited, 1463 Objects: []*ObjectDiff{ 1464 { 1465 Type: DiffTypeEdited, 1466 Name: "RestartPolicy", 1467 Fields: []*FieldDiff{ 1468 { 1469 Type: DiffTypeEdited, 1470 Name: "Attempts", 1471 Old: "1", 1472 New: "2", 1473 }, 1474 { 1475 Type: DiffTypeNone, 1476 Name: "Delay", 1477 Old: "1000000000", 1478 New: "1000000000", 1479 }, 1480 { 1481 Type: DiffTypeEdited, 1482 Name: "Interval", 1483 Old: "1000000000", 1484 New: "2000000000", 1485 }, 1486 { 1487 Type: DiffTypeNone, 1488 Name: "Mode", 1489 Old: "fail", 1490 New: "fail", 1491 }, 1492 }, 1493 }, 1494 }, 1495 }, 1496 }, 1497 { 1498 // Update strategy deleted 1499 Old: &TaskGroup{ 1500 Update: &UpdateStrategy{ 1501 AutoRevert: true, 1502 }, 1503 }, 1504 New: &TaskGroup{}, 1505 Expected: &TaskGroupDiff{ 1506 Type: DiffTypeEdited, 1507 Objects: []*ObjectDiff{ 1508 { 1509 Type: DiffTypeDeleted, 1510 Name: "Update", 1511 Fields: []*FieldDiff{ 1512 { 1513 Type: DiffTypeDeleted, 1514 Name: "AutoRevert", 1515 Old: "true", 1516 New: "", 1517 }, 1518 { 1519 Type: DiffTypeDeleted, 1520 Name: "Canary", 1521 Old: "0", 1522 New: "", 1523 }, 1524 { 1525 Type: DiffTypeDeleted, 1526 Name: "HealthyDeadline", 1527 Old: "0", 1528 New: "", 1529 }, 1530 { 1531 Type: DiffTypeDeleted, 1532 Name: "MaxParallel", 1533 Old: "0", 1534 New: "", 1535 }, 1536 { 1537 Type: DiffTypeDeleted, 1538 Name: "MinHealthyTime", 1539 Old: "0", 1540 New: "", 1541 }, 1542 }, 1543 }, 1544 }, 1545 }, 1546 }, 1547 { 1548 // Update strategy added 1549 Old: &TaskGroup{}, 1550 New: &TaskGroup{ 1551 Update: &UpdateStrategy{ 1552 AutoRevert: true, 1553 }, 1554 }, 1555 Expected: &TaskGroupDiff{ 1556 Type: DiffTypeEdited, 1557 Objects: []*ObjectDiff{ 1558 { 1559 Type: DiffTypeAdded, 1560 Name: "Update", 1561 Fields: []*FieldDiff{ 1562 { 1563 Type: DiffTypeAdded, 1564 Name: "AutoRevert", 1565 Old: "", 1566 New: "true", 1567 }, 1568 { 1569 Type: DiffTypeAdded, 1570 Name: "Canary", 1571 Old: "", 1572 New: "0", 1573 }, 1574 { 1575 Type: DiffTypeAdded, 1576 Name: "HealthyDeadline", 1577 Old: "", 1578 New: "0", 1579 }, 1580 { 1581 Type: DiffTypeAdded, 1582 Name: "MaxParallel", 1583 Old: "", 1584 New: "0", 1585 }, 1586 { 1587 Type: DiffTypeAdded, 1588 Name: "MinHealthyTime", 1589 Old: "", 1590 New: "0", 1591 }, 1592 }, 1593 }, 1594 }, 1595 }, 1596 }, 1597 { 1598 // Update strategy edited 1599 Old: &TaskGroup{ 1600 Update: &UpdateStrategy{ 1601 MaxParallel: 5, 1602 HealthCheck: "foo", 1603 MinHealthyTime: 1 * time.Second, 1604 HealthyDeadline: 30 * time.Second, 1605 AutoRevert: true, 1606 Canary: 2, 1607 }, 1608 }, 1609 New: &TaskGroup{ 1610 Update: &UpdateStrategy{ 1611 MaxParallel: 7, 1612 HealthCheck: "bar", 1613 MinHealthyTime: 2 * time.Second, 1614 HealthyDeadline: 31 * time.Second, 1615 AutoRevert: false, 1616 Canary: 1, 1617 }, 1618 }, 1619 Expected: &TaskGroupDiff{ 1620 Type: DiffTypeEdited, 1621 Objects: []*ObjectDiff{ 1622 { 1623 Type: DiffTypeEdited, 1624 Name: "Update", 1625 Fields: []*FieldDiff{ 1626 { 1627 Type: DiffTypeEdited, 1628 Name: "AutoRevert", 1629 Old: "true", 1630 New: "false", 1631 }, 1632 { 1633 Type: DiffTypeEdited, 1634 Name: "Canary", 1635 Old: "2", 1636 New: "1", 1637 }, 1638 { 1639 Type: DiffTypeEdited, 1640 Name: "HealthCheck", 1641 Old: "foo", 1642 New: "bar", 1643 }, 1644 { 1645 Type: DiffTypeEdited, 1646 Name: "HealthyDeadline", 1647 Old: "30000000000", 1648 New: "31000000000", 1649 }, 1650 { 1651 Type: DiffTypeEdited, 1652 Name: "MaxParallel", 1653 Old: "5", 1654 New: "7", 1655 }, 1656 { 1657 Type: DiffTypeEdited, 1658 Name: "MinHealthyTime", 1659 Old: "1000000000", 1660 New: "2000000000", 1661 }, 1662 }, 1663 }, 1664 }, 1665 }, 1666 }, 1667 { 1668 // Update strategy edited with context 1669 Contextual: true, 1670 Old: &TaskGroup{ 1671 Update: &UpdateStrategy{ 1672 MaxParallel: 5, 1673 HealthCheck: "foo", 1674 MinHealthyTime: 1 * time.Second, 1675 HealthyDeadline: 30 * time.Second, 1676 AutoRevert: true, 1677 Canary: 2, 1678 }, 1679 }, 1680 New: &TaskGroup{ 1681 Update: &UpdateStrategy{ 1682 MaxParallel: 7, 1683 HealthCheck: "foo", 1684 MinHealthyTime: 1 * time.Second, 1685 HealthyDeadline: 30 * time.Second, 1686 AutoRevert: true, 1687 Canary: 2, 1688 }, 1689 }, 1690 Expected: &TaskGroupDiff{ 1691 Type: DiffTypeEdited, 1692 Objects: []*ObjectDiff{ 1693 { 1694 Type: DiffTypeEdited, 1695 Name: "Update", 1696 Fields: []*FieldDiff{ 1697 { 1698 Type: DiffTypeNone, 1699 Name: "AutoRevert", 1700 Old: "true", 1701 New: "true", 1702 }, 1703 { 1704 Type: DiffTypeNone, 1705 Name: "Canary", 1706 Old: "2", 1707 New: "2", 1708 }, 1709 { 1710 Type: DiffTypeNone, 1711 Name: "HealthCheck", 1712 Old: "foo", 1713 New: "foo", 1714 }, 1715 { 1716 Type: DiffTypeNone, 1717 Name: "HealthyDeadline", 1718 Old: "30000000000", 1719 New: "30000000000", 1720 }, 1721 { 1722 Type: DiffTypeEdited, 1723 Name: "MaxParallel", 1724 Old: "5", 1725 New: "7", 1726 }, 1727 { 1728 Type: DiffTypeNone, 1729 Name: "MinHealthyTime", 1730 Old: "1000000000", 1731 New: "1000000000", 1732 }, 1733 }, 1734 }, 1735 }, 1736 }, 1737 }, 1738 { 1739 // EphemeralDisk added 1740 Old: &TaskGroup{}, 1741 New: &TaskGroup{ 1742 EphemeralDisk: &EphemeralDisk{ 1743 Migrate: true, 1744 Sticky: true, 1745 SizeMB: 100, 1746 }, 1747 }, 1748 Expected: &TaskGroupDiff{ 1749 Type: DiffTypeEdited, 1750 Objects: []*ObjectDiff{ 1751 { 1752 Type: DiffTypeAdded, 1753 Name: "EphemeralDisk", 1754 Fields: []*FieldDiff{ 1755 { 1756 Type: DiffTypeAdded, 1757 Name: "Migrate", 1758 Old: "", 1759 New: "true", 1760 }, 1761 { 1762 Type: DiffTypeAdded, 1763 Name: "SizeMB", 1764 Old: "", 1765 New: "100", 1766 }, 1767 { 1768 Type: DiffTypeAdded, 1769 Name: "Sticky", 1770 Old: "", 1771 New: "true", 1772 }, 1773 }, 1774 }, 1775 }, 1776 }, 1777 }, 1778 { 1779 // EphemeralDisk deleted 1780 Old: &TaskGroup{ 1781 EphemeralDisk: &EphemeralDisk{ 1782 Migrate: true, 1783 Sticky: true, 1784 SizeMB: 100, 1785 }, 1786 }, 1787 New: &TaskGroup{}, 1788 Expected: &TaskGroupDiff{ 1789 Type: DiffTypeEdited, 1790 Objects: []*ObjectDiff{ 1791 { 1792 Type: DiffTypeDeleted, 1793 Name: "EphemeralDisk", 1794 Fields: []*FieldDiff{ 1795 { 1796 Type: DiffTypeDeleted, 1797 Name: "Migrate", 1798 Old: "true", 1799 New: "", 1800 }, 1801 { 1802 Type: DiffTypeDeleted, 1803 Name: "SizeMB", 1804 Old: "100", 1805 New: "", 1806 }, 1807 { 1808 Type: DiffTypeDeleted, 1809 Name: "Sticky", 1810 Old: "true", 1811 New: "", 1812 }, 1813 }, 1814 }, 1815 }, 1816 }, 1817 }, 1818 { 1819 // EphemeralDisk edited 1820 Old: &TaskGroup{ 1821 EphemeralDisk: &EphemeralDisk{ 1822 Migrate: true, 1823 Sticky: true, 1824 SizeMB: 150, 1825 }, 1826 }, 1827 New: &TaskGroup{ 1828 EphemeralDisk: &EphemeralDisk{ 1829 Migrate: false, 1830 Sticky: false, 1831 SizeMB: 90, 1832 }, 1833 }, 1834 Expected: &TaskGroupDiff{ 1835 Type: DiffTypeEdited, 1836 Objects: []*ObjectDiff{ 1837 { 1838 Type: DiffTypeEdited, 1839 Name: "EphemeralDisk", 1840 Fields: []*FieldDiff{ 1841 { 1842 Type: DiffTypeEdited, 1843 Name: "Migrate", 1844 Old: "true", 1845 New: "false", 1846 }, 1847 { 1848 Type: DiffTypeEdited, 1849 Name: "SizeMB", 1850 Old: "150", 1851 New: "90", 1852 }, 1853 1854 { 1855 Type: DiffTypeEdited, 1856 Name: "Sticky", 1857 Old: "true", 1858 New: "false", 1859 }, 1860 }, 1861 }, 1862 }, 1863 }, 1864 }, 1865 { 1866 // EphemeralDisk edited with context 1867 Contextual: true, 1868 Old: &TaskGroup{ 1869 EphemeralDisk: &EphemeralDisk{ 1870 Migrate: false, 1871 Sticky: false, 1872 SizeMB: 100, 1873 }, 1874 }, 1875 New: &TaskGroup{ 1876 EphemeralDisk: &EphemeralDisk{ 1877 Migrate: true, 1878 Sticky: true, 1879 SizeMB: 90, 1880 }, 1881 }, 1882 Expected: &TaskGroupDiff{ 1883 Type: DiffTypeEdited, 1884 Objects: []*ObjectDiff{ 1885 { 1886 Type: DiffTypeEdited, 1887 Name: "EphemeralDisk", 1888 Fields: []*FieldDiff{ 1889 { 1890 Type: DiffTypeEdited, 1891 Name: "Migrate", 1892 Old: "false", 1893 New: "true", 1894 }, 1895 { 1896 Type: DiffTypeEdited, 1897 Name: "SizeMB", 1898 Old: "100", 1899 New: "90", 1900 }, 1901 { 1902 Type: DiffTypeEdited, 1903 Name: "Sticky", 1904 Old: "false", 1905 New: "true", 1906 }, 1907 }, 1908 }, 1909 }, 1910 }, 1911 }, 1912 { 1913 // Tasks edited 1914 Old: &TaskGroup{ 1915 Tasks: []*Task{ 1916 { 1917 Name: "foo", 1918 Driver: "docker", 1919 }, 1920 { 1921 Name: "bar", 1922 Driver: "docker", 1923 }, 1924 { 1925 Name: "baz", 1926 Driver: "docker", 1927 }, 1928 }, 1929 }, 1930 New: &TaskGroup{ 1931 Tasks: []*Task{ 1932 { 1933 Name: "bar", 1934 Driver: "docker", 1935 }, 1936 { 1937 Name: "baz", 1938 Driver: "exec", 1939 }, 1940 { 1941 Name: "bam", 1942 Driver: "docker", 1943 }, 1944 }, 1945 }, 1946 Expected: &TaskGroupDiff{ 1947 Type: DiffTypeEdited, 1948 Tasks: []*TaskDiff{ 1949 { 1950 Type: DiffTypeAdded, 1951 Name: "bam", 1952 Fields: []*FieldDiff{ 1953 { 1954 Type: DiffTypeAdded, 1955 Name: "Driver", 1956 Old: "", 1957 New: "docker", 1958 }, 1959 { 1960 Type: DiffTypeAdded, 1961 Name: "KillTimeout", 1962 Old: "", 1963 New: "0", 1964 }, 1965 { 1966 Type: DiffTypeAdded, 1967 Name: "Leader", 1968 Old: "", 1969 New: "false", 1970 }, 1971 }, 1972 }, 1973 { 1974 Type: DiffTypeNone, 1975 Name: "bar", 1976 }, 1977 { 1978 Type: DiffTypeEdited, 1979 Name: "baz", 1980 Fields: []*FieldDiff{ 1981 { 1982 Type: DiffTypeEdited, 1983 Name: "Driver", 1984 Old: "docker", 1985 New: "exec", 1986 }, 1987 }, 1988 }, 1989 { 1990 Type: DiffTypeDeleted, 1991 Name: "foo", 1992 Fields: []*FieldDiff{ 1993 { 1994 Type: DiffTypeDeleted, 1995 Name: "Driver", 1996 Old: "docker", 1997 New: "", 1998 }, 1999 { 2000 Type: DiffTypeDeleted, 2001 Name: "KillTimeout", 2002 Old: "0", 2003 New: "", 2004 }, 2005 { 2006 Type: DiffTypeDeleted, 2007 Name: "Leader", 2008 Old: "false", 2009 New: "", 2010 }, 2011 }, 2012 }, 2013 }, 2014 }, 2015 }, 2016 } 2017 2018 for i, c := range cases { 2019 actual, err := c.Old.Diff(c.New, c.Contextual) 2020 if c.Error && err == nil { 2021 t.Fatalf("case %d: expected errored", i+1) 2022 } else if err != nil { 2023 if !c.Error { 2024 t.Fatalf("case %d: errored %#v", i+1, err) 2025 } else { 2026 continue 2027 } 2028 } 2029 2030 if !reflect.DeepEqual(actual, c.Expected) { 2031 t.Fatalf("case %d: got:\n%#v\n want:\n%#v\n", 2032 i+1, actual, c.Expected) 2033 } 2034 } 2035 } 2036 2037 func TestTaskDiff(t *testing.T) { 2038 cases := []struct { 2039 Name string 2040 Old, New *Task 2041 Expected *TaskDiff 2042 Error bool 2043 Contextual bool 2044 }{ 2045 { 2046 Name: "Empty", 2047 Old: nil, 2048 New: nil, 2049 Expected: &TaskDiff{ 2050 Type: DiffTypeNone, 2051 }, 2052 }, 2053 { 2054 Name: "Primitive only that has different names", 2055 Old: &Task{ 2056 Name: "foo", 2057 Meta: map[string]string{ 2058 "foo": "bar", 2059 }, 2060 }, 2061 New: &Task{ 2062 Name: "bar", 2063 Meta: map[string]string{ 2064 "foo": "bar", 2065 }, 2066 }, 2067 Error: true, 2068 }, 2069 { 2070 Name: "Primitive only that is the same", 2071 Old: &Task{ 2072 Name: "foo", 2073 Driver: "exec", 2074 User: "foo", 2075 Env: map[string]string{ 2076 "FOO": "bar", 2077 }, 2078 Meta: map[string]string{ 2079 "foo": "bar", 2080 }, 2081 KillTimeout: 1 * time.Second, 2082 Leader: true, 2083 }, 2084 New: &Task{ 2085 Name: "foo", 2086 Driver: "exec", 2087 User: "foo", 2088 Env: map[string]string{ 2089 "FOO": "bar", 2090 }, 2091 Meta: map[string]string{ 2092 "foo": "bar", 2093 }, 2094 KillTimeout: 1 * time.Second, 2095 Leader: true, 2096 }, 2097 Expected: &TaskDiff{ 2098 Type: DiffTypeNone, 2099 Name: "foo", 2100 }, 2101 }, 2102 { 2103 Name: "Primitive only that has diffs", 2104 Old: &Task{ 2105 Name: "foo", 2106 Driver: "exec", 2107 User: "foo", 2108 Env: map[string]string{ 2109 "FOO": "bar", 2110 }, 2111 Meta: map[string]string{ 2112 "foo": "bar", 2113 }, 2114 KillTimeout: 1 * time.Second, 2115 Leader: true, 2116 }, 2117 New: &Task{ 2118 Name: "foo", 2119 Driver: "docker", 2120 User: "bar", 2121 Env: map[string]string{ 2122 "FOO": "baz", 2123 }, 2124 Meta: map[string]string{ 2125 "foo": "baz", 2126 }, 2127 KillTimeout: 2 * time.Second, 2128 Leader: false, 2129 }, 2130 Expected: &TaskDiff{ 2131 Type: DiffTypeEdited, 2132 Name: "foo", 2133 Fields: []*FieldDiff{ 2134 { 2135 Type: DiffTypeEdited, 2136 Name: "Driver", 2137 Old: "exec", 2138 New: "docker", 2139 }, 2140 { 2141 Type: DiffTypeEdited, 2142 Name: "Env[FOO]", 2143 Old: "bar", 2144 New: "baz", 2145 }, 2146 { 2147 Type: DiffTypeEdited, 2148 Name: "KillTimeout", 2149 Old: "1000000000", 2150 New: "2000000000", 2151 }, 2152 { 2153 Type: DiffTypeEdited, 2154 Name: "Leader", 2155 Old: "true", 2156 New: "false", 2157 }, 2158 { 2159 Type: DiffTypeEdited, 2160 Name: "Meta[foo]", 2161 Old: "bar", 2162 New: "baz", 2163 }, 2164 { 2165 Type: DiffTypeEdited, 2166 Name: "User", 2167 Old: "foo", 2168 New: "bar", 2169 }, 2170 }, 2171 }, 2172 }, 2173 { 2174 Name: "Map diff", 2175 Old: &Task{ 2176 Meta: map[string]string{ 2177 "foo": "foo", 2178 "bar": "bar", 2179 }, 2180 Env: map[string]string{ 2181 "foo": "foo", 2182 "bar": "bar", 2183 }, 2184 }, 2185 New: &Task{ 2186 Meta: map[string]string{ 2187 "bar": "bar", 2188 "baz": "baz", 2189 }, 2190 Env: map[string]string{ 2191 "bar": "bar", 2192 "baz": "baz", 2193 }, 2194 }, 2195 Expected: &TaskDiff{ 2196 Type: DiffTypeEdited, 2197 Fields: []*FieldDiff{ 2198 { 2199 Type: DiffTypeAdded, 2200 Name: "Env[baz]", 2201 Old: "", 2202 New: "baz", 2203 }, 2204 { 2205 Type: DiffTypeDeleted, 2206 Name: "Env[foo]", 2207 Old: "foo", 2208 New: "", 2209 }, 2210 { 2211 Type: DiffTypeAdded, 2212 Name: "Meta[baz]", 2213 Old: "", 2214 New: "baz", 2215 }, 2216 { 2217 Type: DiffTypeDeleted, 2218 Name: "Meta[foo]", 2219 Old: "foo", 2220 New: "", 2221 }, 2222 }, 2223 }, 2224 }, 2225 { 2226 Name: "Constraints edited", 2227 Old: &Task{ 2228 Constraints: []*Constraint{ 2229 { 2230 LTarget: "foo", 2231 RTarget: "foo", 2232 Operand: "foo", 2233 str: "foo", 2234 }, 2235 { 2236 LTarget: "bar", 2237 RTarget: "bar", 2238 Operand: "bar", 2239 str: "bar", 2240 }, 2241 }, 2242 }, 2243 New: &Task{ 2244 Constraints: []*Constraint{ 2245 { 2246 LTarget: "foo", 2247 RTarget: "foo", 2248 Operand: "foo", 2249 str: "foo", 2250 }, 2251 { 2252 LTarget: "baz", 2253 RTarget: "baz", 2254 Operand: "baz", 2255 str: "baz", 2256 }, 2257 }, 2258 }, 2259 Expected: &TaskDiff{ 2260 Type: DiffTypeEdited, 2261 Objects: []*ObjectDiff{ 2262 { 2263 Type: DiffTypeAdded, 2264 Name: "Constraint", 2265 Fields: []*FieldDiff{ 2266 { 2267 Type: DiffTypeAdded, 2268 Name: "LTarget", 2269 Old: "", 2270 New: "baz", 2271 }, 2272 { 2273 Type: DiffTypeAdded, 2274 Name: "Operand", 2275 Old: "", 2276 New: "baz", 2277 }, 2278 { 2279 Type: DiffTypeAdded, 2280 Name: "RTarget", 2281 Old: "", 2282 New: "baz", 2283 }, 2284 }, 2285 }, 2286 { 2287 Type: DiffTypeDeleted, 2288 Name: "Constraint", 2289 Fields: []*FieldDiff{ 2290 { 2291 Type: DiffTypeDeleted, 2292 Name: "LTarget", 2293 Old: "bar", 2294 New: "", 2295 }, 2296 { 2297 Type: DiffTypeDeleted, 2298 Name: "Operand", 2299 Old: "bar", 2300 New: "", 2301 }, 2302 { 2303 Type: DiffTypeDeleted, 2304 Name: "RTarget", 2305 Old: "bar", 2306 New: "", 2307 }, 2308 }, 2309 }, 2310 }, 2311 }, 2312 }, 2313 { 2314 Name: "LogConfig added", 2315 Old: &Task{}, 2316 New: &Task{ 2317 LogConfig: &LogConfig{ 2318 MaxFiles: 1, 2319 MaxFileSizeMB: 10, 2320 }, 2321 }, 2322 Expected: &TaskDiff{ 2323 Type: DiffTypeEdited, 2324 Objects: []*ObjectDiff{ 2325 { 2326 Type: DiffTypeAdded, 2327 Name: "LogConfig", 2328 Fields: []*FieldDiff{ 2329 { 2330 Type: DiffTypeAdded, 2331 Name: "MaxFileSizeMB", 2332 Old: "", 2333 New: "10", 2334 }, 2335 { 2336 Type: DiffTypeAdded, 2337 Name: "MaxFiles", 2338 Old: "", 2339 New: "1", 2340 }, 2341 }, 2342 }, 2343 }, 2344 }, 2345 }, 2346 { 2347 Name: "LogConfig deleted", 2348 Old: &Task{ 2349 LogConfig: &LogConfig{ 2350 MaxFiles: 1, 2351 MaxFileSizeMB: 10, 2352 }, 2353 }, 2354 New: &Task{}, 2355 Expected: &TaskDiff{ 2356 Type: DiffTypeEdited, 2357 Objects: []*ObjectDiff{ 2358 { 2359 Type: DiffTypeDeleted, 2360 Name: "LogConfig", 2361 Fields: []*FieldDiff{ 2362 { 2363 Type: DiffTypeDeleted, 2364 Name: "MaxFileSizeMB", 2365 Old: "10", 2366 New: "", 2367 }, 2368 { 2369 Type: DiffTypeDeleted, 2370 Name: "MaxFiles", 2371 Old: "1", 2372 New: "", 2373 }, 2374 }, 2375 }, 2376 }, 2377 }, 2378 }, 2379 { 2380 Name: "LogConfig edited", 2381 Old: &Task{ 2382 LogConfig: &LogConfig{ 2383 MaxFiles: 1, 2384 MaxFileSizeMB: 10, 2385 }, 2386 }, 2387 New: &Task{ 2388 LogConfig: &LogConfig{ 2389 MaxFiles: 2, 2390 MaxFileSizeMB: 20, 2391 }, 2392 }, 2393 Expected: &TaskDiff{ 2394 Type: DiffTypeEdited, 2395 Objects: []*ObjectDiff{ 2396 { 2397 Type: DiffTypeEdited, 2398 Name: "LogConfig", 2399 Fields: []*FieldDiff{ 2400 { 2401 Type: DiffTypeEdited, 2402 Name: "MaxFileSizeMB", 2403 Old: "10", 2404 New: "20", 2405 }, 2406 { 2407 Type: DiffTypeEdited, 2408 Name: "MaxFiles", 2409 Old: "1", 2410 New: "2", 2411 }, 2412 }, 2413 }, 2414 }, 2415 }, 2416 }, 2417 { 2418 Name: "LogConfig edited with context", 2419 Contextual: true, 2420 Old: &Task{ 2421 LogConfig: &LogConfig{ 2422 MaxFiles: 1, 2423 MaxFileSizeMB: 10, 2424 }, 2425 }, 2426 New: &Task{ 2427 LogConfig: &LogConfig{ 2428 MaxFiles: 1, 2429 MaxFileSizeMB: 20, 2430 }, 2431 }, 2432 Expected: &TaskDiff{ 2433 Type: DiffTypeEdited, 2434 Objects: []*ObjectDiff{ 2435 { 2436 Type: DiffTypeEdited, 2437 Name: "LogConfig", 2438 Fields: []*FieldDiff{ 2439 { 2440 Type: DiffTypeEdited, 2441 Name: "MaxFileSizeMB", 2442 Old: "10", 2443 New: "20", 2444 }, 2445 { 2446 Type: DiffTypeNone, 2447 Name: "MaxFiles", 2448 Old: "1", 2449 New: "1", 2450 }, 2451 }, 2452 }, 2453 }, 2454 }, 2455 }, 2456 { 2457 Name: "Artifacts edited", 2458 Old: &Task{ 2459 Artifacts: []*TaskArtifact{ 2460 { 2461 GetterSource: "foo", 2462 GetterOptions: map[string]string{ 2463 "foo": "bar", 2464 }, 2465 RelativeDest: "foo", 2466 }, 2467 { 2468 GetterSource: "bar", 2469 GetterOptions: map[string]string{ 2470 "bar": "baz", 2471 }, 2472 GetterMode: "dir", 2473 RelativeDest: "bar", 2474 }, 2475 }, 2476 }, 2477 New: &Task{ 2478 Artifacts: []*TaskArtifact{ 2479 { 2480 GetterSource: "foo", 2481 GetterOptions: map[string]string{ 2482 "foo": "bar", 2483 }, 2484 RelativeDest: "foo", 2485 }, 2486 { 2487 GetterSource: "bam", 2488 GetterOptions: map[string]string{ 2489 "bam": "baz", 2490 }, 2491 GetterMode: "file", 2492 RelativeDest: "bam", 2493 }, 2494 }, 2495 }, 2496 Expected: &TaskDiff{ 2497 Type: DiffTypeEdited, 2498 Objects: []*ObjectDiff{ 2499 { 2500 Type: DiffTypeAdded, 2501 Name: "Artifact", 2502 Fields: []*FieldDiff{ 2503 { 2504 Type: DiffTypeAdded, 2505 Name: "GetterMode", 2506 Old: "", 2507 New: "file", 2508 }, 2509 { 2510 Type: DiffTypeAdded, 2511 Name: "GetterOptions[bam]", 2512 Old: "", 2513 New: "baz", 2514 }, 2515 { 2516 Type: DiffTypeAdded, 2517 Name: "GetterSource", 2518 Old: "", 2519 New: "bam", 2520 }, 2521 { 2522 Type: DiffTypeAdded, 2523 Name: "RelativeDest", 2524 Old: "", 2525 New: "bam", 2526 }, 2527 }, 2528 }, 2529 { 2530 Type: DiffTypeDeleted, 2531 Name: "Artifact", 2532 Fields: []*FieldDiff{ 2533 { 2534 Type: DiffTypeDeleted, 2535 Name: "GetterMode", 2536 Old: "dir", 2537 New: "", 2538 }, 2539 { 2540 Type: DiffTypeDeleted, 2541 Name: "GetterOptions[bar]", 2542 Old: "baz", 2543 New: "", 2544 }, 2545 { 2546 Type: DiffTypeDeleted, 2547 Name: "GetterSource", 2548 Old: "bar", 2549 New: "", 2550 }, 2551 { 2552 Type: DiffTypeDeleted, 2553 Name: "RelativeDest", 2554 Old: "bar", 2555 New: "", 2556 }, 2557 }, 2558 }, 2559 }, 2560 }, 2561 }, 2562 { 2563 Name: "Resources edited (no networks)", 2564 Old: &Task{ 2565 Resources: &Resources{ 2566 CPU: 100, 2567 MemoryMB: 100, 2568 DiskMB: 100, 2569 IOPS: 100, 2570 }, 2571 }, 2572 New: &Task{ 2573 Resources: &Resources{ 2574 CPU: 200, 2575 MemoryMB: 200, 2576 DiskMB: 200, 2577 IOPS: 200, 2578 }, 2579 }, 2580 Expected: &TaskDiff{ 2581 Type: DiffTypeEdited, 2582 Objects: []*ObjectDiff{ 2583 { 2584 Type: DiffTypeEdited, 2585 Name: "Resources", 2586 Fields: []*FieldDiff{ 2587 { 2588 Type: DiffTypeEdited, 2589 Name: "CPU", 2590 Old: "100", 2591 New: "200", 2592 }, 2593 { 2594 Type: DiffTypeEdited, 2595 Name: "DiskMB", 2596 Old: "100", 2597 New: "200", 2598 }, 2599 { 2600 Type: DiffTypeEdited, 2601 Name: "IOPS", 2602 Old: "100", 2603 New: "200", 2604 }, 2605 { 2606 Type: DiffTypeEdited, 2607 Name: "MemoryMB", 2608 Old: "100", 2609 New: "200", 2610 }, 2611 }, 2612 }, 2613 }, 2614 }, 2615 }, 2616 { 2617 Name: "Resources edited (no networks) with context", 2618 Contextual: true, 2619 Old: &Task{ 2620 Resources: &Resources{ 2621 CPU: 100, 2622 MemoryMB: 100, 2623 DiskMB: 100, 2624 IOPS: 100, 2625 }, 2626 }, 2627 New: &Task{ 2628 Resources: &Resources{ 2629 CPU: 200, 2630 MemoryMB: 100, 2631 DiskMB: 200, 2632 IOPS: 100, 2633 }, 2634 }, 2635 Expected: &TaskDiff{ 2636 Type: DiffTypeEdited, 2637 Objects: []*ObjectDiff{ 2638 { 2639 Type: DiffTypeEdited, 2640 Name: "Resources", 2641 Fields: []*FieldDiff{ 2642 { 2643 Type: DiffTypeEdited, 2644 Name: "CPU", 2645 Old: "100", 2646 New: "200", 2647 }, 2648 { 2649 Type: DiffTypeEdited, 2650 Name: "DiskMB", 2651 Old: "100", 2652 New: "200", 2653 }, 2654 { 2655 Type: DiffTypeNone, 2656 Name: "IOPS", 2657 Old: "100", 2658 New: "100", 2659 }, 2660 { 2661 Type: DiffTypeNone, 2662 Name: "MemoryMB", 2663 Old: "100", 2664 New: "100", 2665 }, 2666 }, 2667 }, 2668 }, 2669 }, 2670 }, 2671 { 2672 Name: "Network Resources edited", 2673 Old: &Task{ 2674 Resources: &Resources{ 2675 Networks: []*NetworkResource{ 2676 { 2677 Device: "foo", 2678 CIDR: "foo", 2679 IP: "foo", 2680 MBits: 100, 2681 ReservedPorts: []Port{ 2682 { 2683 Label: "foo", 2684 Value: 80, 2685 }, 2686 }, 2687 DynamicPorts: []Port{ 2688 { 2689 Label: "bar", 2690 }, 2691 }, 2692 }, 2693 }, 2694 }, 2695 }, 2696 New: &Task{ 2697 Resources: &Resources{ 2698 Networks: []*NetworkResource{ 2699 { 2700 Device: "bar", 2701 CIDR: "bar", 2702 IP: "bar", 2703 MBits: 200, 2704 ReservedPorts: []Port{ 2705 { 2706 Label: "foo", 2707 Value: 81, 2708 }, 2709 }, 2710 DynamicPorts: []Port{ 2711 { 2712 Label: "baz", 2713 }, 2714 }, 2715 }, 2716 }, 2717 }, 2718 }, 2719 Expected: &TaskDiff{ 2720 Type: DiffTypeEdited, 2721 Objects: []*ObjectDiff{ 2722 { 2723 Type: DiffTypeEdited, 2724 Name: "Resources", 2725 Objects: []*ObjectDiff{ 2726 { 2727 Type: DiffTypeAdded, 2728 Name: "Network", 2729 Fields: []*FieldDiff{ 2730 { 2731 Type: DiffTypeAdded, 2732 Name: "MBits", 2733 Old: "", 2734 New: "200", 2735 }, 2736 }, 2737 Objects: []*ObjectDiff{ 2738 { 2739 Type: DiffTypeAdded, 2740 Name: "Static Port", 2741 Fields: []*FieldDiff{ 2742 { 2743 Type: DiffTypeAdded, 2744 Name: "Label", 2745 Old: "", 2746 New: "foo", 2747 }, 2748 { 2749 Type: DiffTypeAdded, 2750 Name: "Value", 2751 Old: "", 2752 New: "81", 2753 }, 2754 }, 2755 }, 2756 { 2757 Type: DiffTypeAdded, 2758 Name: "Dynamic Port", 2759 Fields: []*FieldDiff{ 2760 { 2761 Type: DiffTypeAdded, 2762 Name: "Label", 2763 Old: "", 2764 New: "baz", 2765 }, 2766 }, 2767 }, 2768 }, 2769 }, 2770 { 2771 Type: DiffTypeDeleted, 2772 Name: "Network", 2773 Fields: []*FieldDiff{ 2774 { 2775 Type: DiffTypeDeleted, 2776 Name: "MBits", 2777 Old: "100", 2778 New: "", 2779 }, 2780 }, 2781 Objects: []*ObjectDiff{ 2782 { 2783 Type: DiffTypeDeleted, 2784 Name: "Static Port", 2785 Fields: []*FieldDiff{ 2786 { 2787 Type: DiffTypeDeleted, 2788 Name: "Label", 2789 Old: "foo", 2790 New: "", 2791 }, 2792 { 2793 Type: DiffTypeDeleted, 2794 Name: "Value", 2795 Old: "80", 2796 New: "", 2797 }, 2798 }, 2799 }, 2800 { 2801 Type: DiffTypeDeleted, 2802 Name: "Dynamic Port", 2803 Fields: []*FieldDiff{ 2804 { 2805 Type: DiffTypeDeleted, 2806 Name: "Label", 2807 Old: "bar", 2808 New: "", 2809 }, 2810 }, 2811 }, 2812 }, 2813 }, 2814 }, 2815 }, 2816 }, 2817 }, 2818 }, 2819 { 2820 Name: "Config same", 2821 Old: &Task{ 2822 Config: map[string]interface{}{ 2823 "foo": 1, 2824 "bar": "bar", 2825 "bam": []string{"a", "b"}, 2826 "baz": map[string]int{ 2827 "a": 1, 2828 "b": 2, 2829 }, 2830 "boom": &Port{ 2831 Label: "boom_port", 2832 }, 2833 }, 2834 }, 2835 New: &Task{ 2836 Config: map[string]interface{}{ 2837 "foo": 1, 2838 "bar": "bar", 2839 "bam": []string{"a", "b"}, 2840 "baz": map[string]int{ 2841 "a": 1, 2842 "b": 2, 2843 }, 2844 "boom": &Port{ 2845 Label: "boom_port", 2846 }, 2847 }, 2848 }, 2849 Expected: &TaskDiff{ 2850 Type: DiffTypeNone, 2851 }, 2852 }, 2853 { 2854 Name: "Config edited", 2855 Old: &Task{ 2856 Config: map[string]interface{}{ 2857 "foo": 1, 2858 "bar": "baz", 2859 "bam": []string{"a", "b"}, 2860 "baz": map[string]int{ 2861 "a": 1, 2862 "b": 2, 2863 }, 2864 "boom": &Port{ 2865 Label: "boom_port", 2866 }, 2867 }, 2868 }, 2869 New: &Task{ 2870 Config: map[string]interface{}{ 2871 "foo": 2, 2872 "bar": "baz", 2873 "bam": []string{"a", "c", "d"}, 2874 "baz": map[string]int{ 2875 "b": 3, 2876 "c": 4, 2877 }, 2878 "boom": &Port{ 2879 Label: "boom_port2", 2880 }, 2881 }, 2882 }, 2883 Expected: &TaskDiff{ 2884 Type: DiffTypeEdited, 2885 Objects: []*ObjectDiff{ 2886 { 2887 Type: DiffTypeEdited, 2888 Name: "Config", 2889 Fields: []*FieldDiff{ 2890 { 2891 Type: DiffTypeEdited, 2892 Name: "bam[1]", 2893 Old: "b", 2894 New: "c", 2895 }, 2896 { 2897 Type: DiffTypeAdded, 2898 Name: "bam[2]", 2899 Old: "", 2900 New: "d", 2901 }, 2902 { 2903 Type: DiffTypeDeleted, 2904 Name: "baz[a]", 2905 Old: "1", 2906 New: "", 2907 }, 2908 { 2909 Type: DiffTypeEdited, 2910 Name: "baz[b]", 2911 Old: "2", 2912 New: "3", 2913 }, 2914 { 2915 Type: DiffTypeAdded, 2916 Name: "baz[c]", 2917 Old: "", 2918 New: "4", 2919 }, 2920 { 2921 Type: DiffTypeEdited, 2922 Name: "boom.Label", 2923 Old: "boom_port", 2924 New: "boom_port2", 2925 }, 2926 { 2927 Type: DiffTypeEdited, 2928 Name: "foo", 2929 Old: "1", 2930 New: "2", 2931 }, 2932 }, 2933 }, 2934 }, 2935 }, 2936 }, 2937 { 2938 Name: "Config edited with context", 2939 Contextual: true, 2940 Old: &Task{ 2941 Config: map[string]interface{}{ 2942 "foo": 1, 2943 "bar": "baz", 2944 "bam": []string{"a", "b"}, 2945 "baz": map[string]int{ 2946 "a": 1, 2947 "b": 2, 2948 }, 2949 "boom": &Port{ 2950 Label: "boom_port", 2951 }, 2952 }, 2953 }, 2954 New: &Task{ 2955 Config: map[string]interface{}{ 2956 "foo": 2, 2957 "bar": "baz", 2958 "bam": []string{"a", "c", "d"}, 2959 "baz": map[string]int{ 2960 "a": 1, 2961 "b": 2, 2962 }, 2963 "boom": &Port{ 2964 Label: "boom_port", 2965 }, 2966 }, 2967 }, 2968 Expected: &TaskDiff{ 2969 Type: DiffTypeEdited, 2970 Objects: []*ObjectDiff{ 2971 { 2972 Type: DiffTypeEdited, 2973 Name: "Config", 2974 Fields: []*FieldDiff{ 2975 { 2976 Type: DiffTypeNone, 2977 Name: "bam[0]", 2978 Old: "a", 2979 New: "a", 2980 }, 2981 { 2982 Type: DiffTypeEdited, 2983 Name: "bam[1]", 2984 Old: "b", 2985 New: "c", 2986 }, 2987 { 2988 Type: DiffTypeAdded, 2989 Name: "bam[2]", 2990 Old: "", 2991 New: "d", 2992 }, 2993 { 2994 Type: DiffTypeNone, 2995 Name: "bar", 2996 Old: "baz", 2997 New: "baz", 2998 }, 2999 { 3000 Type: DiffTypeNone, 3001 Name: "baz[a]", 3002 Old: "1", 3003 New: "1", 3004 }, 3005 { 3006 Type: DiffTypeNone, 3007 Name: "baz[b]", 3008 Old: "2", 3009 New: "2", 3010 }, 3011 { 3012 Type: DiffTypeNone, 3013 Name: "boom.Label", 3014 Old: "boom_port", 3015 New: "boom_port", 3016 }, 3017 { 3018 Type: DiffTypeNone, 3019 Name: "boom.Value", 3020 Old: "0", 3021 New: "0", 3022 }, 3023 { 3024 Type: DiffTypeEdited, 3025 Name: "foo", 3026 Old: "1", 3027 New: "2", 3028 }, 3029 }, 3030 }, 3031 }, 3032 }, 3033 }, 3034 { 3035 Name: "Services edited (no checks)", 3036 Old: &Task{ 3037 Services: []*Service{ 3038 { 3039 Name: "foo", 3040 PortLabel: "foo", 3041 }, 3042 { 3043 Name: "bar", 3044 PortLabel: "bar", 3045 }, 3046 { 3047 Name: "baz", 3048 PortLabel: "baz", 3049 }, 3050 }, 3051 }, 3052 New: &Task{ 3053 Services: []*Service{ 3054 { 3055 Name: "bar", 3056 PortLabel: "bar", 3057 }, 3058 { 3059 Name: "baz", 3060 PortLabel: "baz2", 3061 }, 3062 { 3063 Name: "bam", 3064 PortLabel: "bam", 3065 }, 3066 }, 3067 }, 3068 Expected: &TaskDiff{ 3069 Type: DiffTypeEdited, 3070 Objects: []*ObjectDiff{ 3071 { 3072 Type: DiffTypeEdited, 3073 Name: "Service", 3074 Fields: []*FieldDiff{ 3075 { 3076 Type: DiffTypeEdited, 3077 Name: "PortLabel", 3078 Old: "baz", 3079 New: "baz2", 3080 }, 3081 }, 3082 }, 3083 { 3084 Type: DiffTypeAdded, 3085 Name: "Service", 3086 Fields: []*FieldDiff{ 3087 { 3088 Type: DiffTypeAdded, 3089 Name: "Name", 3090 Old: "", 3091 New: "bam", 3092 }, 3093 { 3094 Type: DiffTypeAdded, 3095 Name: "PortLabel", 3096 Old: "", 3097 New: "bam", 3098 }, 3099 }, 3100 }, 3101 { 3102 Type: DiffTypeDeleted, 3103 Name: "Service", 3104 Fields: []*FieldDiff{ 3105 { 3106 Type: DiffTypeDeleted, 3107 Name: "Name", 3108 Old: "foo", 3109 New: "", 3110 }, 3111 { 3112 Type: DiffTypeDeleted, 3113 Name: "PortLabel", 3114 Old: "foo", 3115 New: "", 3116 }, 3117 }, 3118 }, 3119 }, 3120 }, 3121 }, 3122 { 3123 Name: "Services edited (no checks) with context", 3124 Contextual: true, 3125 Old: &Task{ 3126 Services: []*Service{ 3127 { 3128 Name: "foo", 3129 PortLabel: "foo", 3130 }, 3131 }, 3132 }, 3133 New: &Task{ 3134 Services: []*Service{ 3135 { 3136 Name: "foo", 3137 PortLabel: "bar", 3138 AddressMode: "driver", 3139 }, 3140 }, 3141 }, 3142 Expected: &TaskDiff{ 3143 Type: DiffTypeEdited, 3144 Objects: []*ObjectDiff{ 3145 { 3146 Type: DiffTypeEdited, 3147 Name: "Service", 3148 Fields: []*FieldDiff{ 3149 { 3150 Type: DiffTypeAdded, 3151 Name: "AddressMode", 3152 New: "driver", 3153 }, 3154 { 3155 Type: DiffTypeNone, 3156 Name: "Name", 3157 Old: "foo", 3158 New: "foo", 3159 }, 3160 { 3161 Type: DiffTypeEdited, 3162 Name: "PortLabel", 3163 Old: "foo", 3164 New: "bar", 3165 }, 3166 }, 3167 }, 3168 }, 3169 }, 3170 }, 3171 { 3172 Name: "Service Checks edited", 3173 Old: &Task{ 3174 Services: []*Service{ 3175 { 3176 Name: "foo", 3177 Checks: []*ServiceCheck{ 3178 { 3179 Name: "foo", 3180 Type: "http", 3181 Command: "foo", 3182 Args: []string{"foo"}, 3183 Path: "foo", 3184 Protocol: "http", 3185 Interval: 1 * time.Second, 3186 Timeout: 1 * time.Second, 3187 }, 3188 { 3189 Name: "bar", 3190 Type: "http", 3191 Command: "foo", 3192 Args: []string{"foo"}, 3193 Path: "foo", 3194 Protocol: "http", 3195 Interval: 1 * time.Second, 3196 Timeout: 1 * time.Second, 3197 }, 3198 { 3199 Name: "baz", 3200 Type: "http", 3201 Command: "foo", 3202 Args: []string{"foo"}, 3203 Path: "foo", 3204 Protocol: "http", 3205 Interval: 1 * time.Second, 3206 Timeout: 1 * time.Second, 3207 }, 3208 }, 3209 }, 3210 }, 3211 }, 3212 New: &Task{ 3213 Services: []*Service{ 3214 { 3215 Name: "foo", 3216 Checks: []*ServiceCheck{ 3217 { 3218 Name: "bar", 3219 Type: "http", 3220 Command: "foo", 3221 Args: []string{"foo"}, 3222 Path: "foo", 3223 Protocol: "http", 3224 Interval: 1 * time.Second, 3225 Timeout: 1 * time.Second, 3226 }, 3227 { 3228 Name: "baz", 3229 Type: "tcp", 3230 Command: "foo", 3231 Args: []string{"foo"}, 3232 Path: "foo", 3233 Protocol: "http", 3234 Interval: 1 * time.Second, 3235 Timeout: 1 * time.Second, 3236 }, 3237 { 3238 Name: "bam", 3239 Type: "http", 3240 Command: "foo", 3241 Args: []string{"foo"}, 3242 Path: "foo", 3243 Protocol: "http", 3244 Interval: 1 * time.Second, 3245 Timeout: 1 * time.Second, 3246 }, 3247 }, 3248 }, 3249 }, 3250 }, 3251 Expected: &TaskDiff{ 3252 Type: DiffTypeEdited, 3253 Objects: []*ObjectDiff{ 3254 { 3255 Type: DiffTypeEdited, 3256 Name: "Service", 3257 Objects: []*ObjectDiff{ 3258 { 3259 Type: DiffTypeEdited, 3260 Name: "Check", 3261 Fields: []*FieldDiff{ 3262 { 3263 Type: DiffTypeEdited, 3264 Name: "Type", 3265 Old: "http", 3266 New: "tcp", 3267 }, 3268 }, 3269 }, 3270 { 3271 Type: DiffTypeAdded, 3272 Name: "Check", 3273 Fields: []*FieldDiff{ 3274 { 3275 Type: DiffTypeAdded, 3276 Name: "Command", 3277 Old: "", 3278 New: "foo", 3279 }, 3280 { 3281 Type: DiffTypeAdded, 3282 Name: "Interval", 3283 Old: "", 3284 New: "1000000000", 3285 }, 3286 { 3287 Type: DiffTypeAdded, 3288 Name: "Name", 3289 Old: "", 3290 New: "bam", 3291 }, 3292 { 3293 Type: DiffTypeAdded, 3294 Name: "Path", 3295 Old: "", 3296 New: "foo", 3297 }, 3298 { 3299 Type: DiffTypeAdded, 3300 Name: "Protocol", 3301 Old: "", 3302 New: "http", 3303 }, 3304 { 3305 Type: DiffTypeAdded, 3306 Name: "TLSSkipVerify", 3307 Old: "", 3308 New: "false", 3309 }, 3310 { 3311 Type: DiffTypeAdded, 3312 Name: "Timeout", 3313 Old: "", 3314 New: "1000000000", 3315 }, 3316 { 3317 Type: DiffTypeAdded, 3318 Name: "Type", 3319 Old: "", 3320 New: "http", 3321 }, 3322 }, 3323 }, 3324 { 3325 Type: DiffTypeDeleted, 3326 Name: "Check", 3327 Fields: []*FieldDiff{ 3328 { 3329 Type: DiffTypeDeleted, 3330 Name: "Command", 3331 Old: "foo", 3332 New: "", 3333 }, 3334 { 3335 Type: DiffTypeDeleted, 3336 Name: "Interval", 3337 Old: "1000000000", 3338 New: "", 3339 }, 3340 { 3341 Type: DiffTypeDeleted, 3342 Name: "Name", 3343 Old: "foo", 3344 New: "", 3345 }, 3346 { 3347 Type: DiffTypeDeleted, 3348 Name: "Path", 3349 Old: "foo", 3350 New: "", 3351 }, 3352 { 3353 Type: DiffTypeDeleted, 3354 Name: "Protocol", 3355 Old: "http", 3356 New: "", 3357 }, 3358 { 3359 Type: DiffTypeDeleted, 3360 Name: "TLSSkipVerify", 3361 Old: "false", 3362 New: "", 3363 }, 3364 { 3365 Type: DiffTypeDeleted, 3366 Name: "Timeout", 3367 Old: "1000000000", 3368 New: "", 3369 }, 3370 { 3371 Type: DiffTypeDeleted, 3372 Name: "Type", 3373 Old: "http", 3374 New: "", 3375 }, 3376 }, 3377 }, 3378 }, 3379 }, 3380 }, 3381 }, 3382 }, 3383 { 3384 Name: "Service Checks edited with context", 3385 Contextual: true, 3386 Old: &Task{ 3387 Services: []*Service{ 3388 { 3389 Name: "foo", 3390 Checks: []*ServiceCheck{ 3391 { 3392 Name: "foo", 3393 Type: "http", 3394 Command: "foo", 3395 Args: []string{"foo"}, 3396 Path: "foo", 3397 Protocol: "http", 3398 Interval: 1 * time.Second, 3399 Timeout: 1 * time.Second, 3400 InitialStatus: "critical", 3401 }, 3402 }, 3403 }, 3404 }, 3405 }, 3406 New: &Task{ 3407 Services: []*Service{ 3408 { 3409 Name: "foo", 3410 Checks: []*ServiceCheck{ 3411 { 3412 Name: "foo", 3413 Type: "tcp", 3414 Command: "foo", 3415 Args: []string{"foo"}, 3416 Path: "foo", 3417 Protocol: "http", 3418 Interval: 1 * time.Second, 3419 Timeout: 1 * time.Second, 3420 InitialStatus: "passing", 3421 }, 3422 }, 3423 }, 3424 }, 3425 }, 3426 Expected: &TaskDiff{ 3427 Type: DiffTypeEdited, 3428 Objects: []*ObjectDiff{ 3429 { 3430 Type: DiffTypeEdited, 3431 Name: "Service", 3432 Fields: []*FieldDiff{ 3433 { 3434 Type: DiffTypeNone, 3435 Name: "AddressMode", 3436 Old: "", 3437 New: "", 3438 }, 3439 { 3440 Type: DiffTypeNone, 3441 Name: "Name", 3442 Old: "foo", 3443 New: "foo", 3444 }, 3445 { 3446 Type: DiffTypeNone, 3447 Name: "PortLabel", 3448 Old: "", 3449 New: "", 3450 }, 3451 }, 3452 Objects: []*ObjectDiff{ 3453 { 3454 Type: DiffTypeEdited, 3455 Name: "Check", 3456 Fields: []*FieldDiff{ 3457 { 3458 Type: DiffTypeNone, 3459 Name: "Command", 3460 Old: "foo", 3461 New: "foo", 3462 }, 3463 { 3464 Type: DiffTypeEdited, 3465 Name: "InitialStatus", 3466 Old: "critical", 3467 New: "passing", 3468 }, 3469 { 3470 Type: DiffTypeNone, 3471 Name: "Interval", 3472 Old: "1000000000", 3473 New: "1000000000", 3474 }, 3475 { 3476 Type: DiffTypeNone, 3477 Name: "Name", 3478 Old: "foo", 3479 New: "foo", 3480 }, 3481 { 3482 Type: DiffTypeNone, 3483 Name: "Path", 3484 Old: "foo", 3485 New: "foo", 3486 }, 3487 { 3488 Type: DiffTypeNone, 3489 Name: "PortLabel", 3490 Old: "", 3491 New: "", 3492 }, 3493 { 3494 Type: DiffTypeNone, 3495 Name: "Protocol", 3496 Old: "http", 3497 New: "http", 3498 }, 3499 { 3500 Type: DiffTypeNone, 3501 Name: "TLSSkipVerify", 3502 Old: "false", 3503 New: "false", 3504 }, 3505 { 3506 Type: DiffTypeNone, 3507 Name: "Timeout", 3508 Old: "1000000000", 3509 New: "1000000000", 3510 }, 3511 { 3512 Type: DiffTypeEdited, 3513 Name: "Type", 3514 Old: "http", 3515 New: "tcp", 3516 }, 3517 }, 3518 }, 3519 }, 3520 }, 3521 }, 3522 }, 3523 }, 3524 { 3525 Name: "Vault added", 3526 Old: &Task{}, 3527 New: &Task{ 3528 Vault: &Vault{ 3529 Policies: []string{"foo", "bar"}, 3530 Env: true, 3531 ChangeMode: "signal", 3532 ChangeSignal: "SIGUSR1", 3533 }, 3534 }, 3535 Expected: &TaskDiff{ 3536 Type: DiffTypeEdited, 3537 Objects: []*ObjectDiff{ 3538 { 3539 Type: DiffTypeAdded, 3540 Name: "Vault", 3541 Fields: []*FieldDiff{ 3542 { 3543 Type: DiffTypeAdded, 3544 Name: "ChangeMode", 3545 Old: "", 3546 New: "signal", 3547 }, 3548 { 3549 Type: DiffTypeAdded, 3550 Name: "ChangeSignal", 3551 Old: "", 3552 New: "SIGUSR1", 3553 }, 3554 { 3555 Type: DiffTypeAdded, 3556 Name: "Env", 3557 Old: "", 3558 New: "true", 3559 }, 3560 }, 3561 Objects: []*ObjectDiff{ 3562 { 3563 Type: DiffTypeAdded, 3564 Name: "Policies", 3565 Fields: []*FieldDiff{ 3566 { 3567 Type: DiffTypeAdded, 3568 Name: "Policies", 3569 Old: "", 3570 New: "bar", 3571 }, 3572 { 3573 Type: DiffTypeAdded, 3574 Name: "Policies", 3575 Old: "", 3576 New: "foo", 3577 }, 3578 }, 3579 }, 3580 }, 3581 }, 3582 }, 3583 }, 3584 }, 3585 { 3586 Name: "Vault deleted", 3587 Old: &Task{ 3588 Vault: &Vault{ 3589 Policies: []string{"foo", "bar"}, 3590 Env: true, 3591 ChangeMode: "signal", 3592 ChangeSignal: "SIGUSR1", 3593 }, 3594 }, 3595 New: &Task{}, 3596 Expected: &TaskDiff{ 3597 Type: DiffTypeEdited, 3598 Objects: []*ObjectDiff{ 3599 { 3600 Type: DiffTypeDeleted, 3601 Name: "Vault", 3602 Fields: []*FieldDiff{ 3603 { 3604 Type: DiffTypeDeleted, 3605 Name: "ChangeMode", 3606 Old: "signal", 3607 New: "", 3608 }, 3609 { 3610 Type: DiffTypeDeleted, 3611 Name: "ChangeSignal", 3612 Old: "SIGUSR1", 3613 New: "", 3614 }, 3615 { 3616 Type: DiffTypeDeleted, 3617 Name: "Env", 3618 Old: "true", 3619 New: "", 3620 }, 3621 }, 3622 Objects: []*ObjectDiff{ 3623 { 3624 Type: DiffTypeDeleted, 3625 Name: "Policies", 3626 Fields: []*FieldDiff{ 3627 { 3628 Type: DiffTypeDeleted, 3629 Name: "Policies", 3630 Old: "bar", 3631 New: "", 3632 }, 3633 { 3634 Type: DiffTypeDeleted, 3635 Name: "Policies", 3636 Old: "foo", 3637 New: "", 3638 }, 3639 }, 3640 }, 3641 }, 3642 }, 3643 }, 3644 }, 3645 }, 3646 { 3647 Name: "Vault edited", 3648 Old: &Task{ 3649 Vault: &Vault{ 3650 Policies: []string{"foo", "bar"}, 3651 Env: true, 3652 ChangeMode: "signal", 3653 ChangeSignal: "SIGUSR1", 3654 }, 3655 }, 3656 New: &Task{ 3657 Vault: &Vault{ 3658 Policies: []string{"bar", "baz"}, 3659 Env: false, 3660 ChangeMode: "restart", 3661 ChangeSignal: "foo", 3662 }, 3663 }, 3664 Expected: &TaskDiff{ 3665 Type: DiffTypeEdited, 3666 Objects: []*ObjectDiff{ 3667 { 3668 Type: DiffTypeEdited, 3669 Name: "Vault", 3670 Fields: []*FieldDiff{ 3671 { 3672 Type: DiffTypeEdited, 3673 Name: "ChangeMode", 3674 Old: "signal", 3675 New: "restart", 3676 }, 3677 { 3678 Type: DiffTypeEdited, 3679 Name: "ChangeSignal", 3680 Old: "SIGUSR1", 3681 New: "foo", 3682 }, 3683 { 3684 Type: DiffTypeEdited, 3685 Name: "Env", 3686 Old: "true", 3687 New: "false", 3688 }, 3689 }, 3690 Objects: []*ObjectDiff{ 3691 { 3692 Type: DiffTypeEdited, 3693 Name: "Policies", 3694 Fields: []*FieldDiff{ 3695 { 3696 Type: DiffTypeAdded, 3697 Name: "Policies", 3698 Old: "", 3699 New: "baz", 3700 }, 3701 { 3702 Type: DiffTypeDeleted, 3703 Name: "Policies", 3704 Old: "foo", 3705 New: "", 3706 }, 3707 }, 3708 }, 3709 }, 3710 }, 3711 }, 3712 }, 3713 }, 3714 { 3715 Name: "Vault edited with context", 3716 Contextual: true, 3717 Old: &Task{ 3718 Vault: &Vault{ 3719 Policies: []string{"foo", "bar"}, 3720 Env: true, 3721 ChangeMode: "signal", 3722 ChangeSignal: "SIGUSR1", 3723 }, 3724 }, 3725 New: &Task{ 3726 Vault: &Vault{ 3727 Policies: []string{"bar", "baz"}, 3728 Env: true, 3729 ChangeMode: "signal", 3730 ChangeSignal: "SIGUSR1", 3731 }, 3732 }, 3733 Expected: &TaskDiff{ 3734 Type: DiffTypeEdited, 3735 Objects: []*ObjectDiff{ 3736 { 3737 Type: DiffTypeEdited, 3738 Name: "Vault", 3739 Fields: []*FieldDiff{ 3740 { 3741 Type: DiffTypeNone, 3742 Name: "ChangeMode", 3743 Old: "signal", 3744 New: "signal", 3745 }, 3746 { 3747 Type: DiffTypeNone, 3748 Name: "ChangeSignal", 3749 Old: "SIGUSR1", 3750 New: "SIGUSR1", 3751 }, 3752 { 3753 Type: DiffTypeNone, 3754 Name: "Env", 3755 Old: "true", 3756 New: "true", 3757 }, 3758 }, 3759 Objects: []*ObjectDiff{ 3760 { 3761 Type: DiffTypeEdited, 3762 Name: "Policies", 3763 Fields: []*FieldDiff{ 3764 { 3765 Type: DiffTypeAdded, 3766 Name: "Policies", 3767 Old: "", 3768 New: "baz", 3769 }, 3770 { 3771 Type: DiffTypeNone, 3772 Name: "Policies", 3773 Old: "bar", 3774 New: "bar", 3775 }, 3776 { 3777 Type: DiffTypeDeleted, 3778 Name: "Policies", 3779 Old: "foo", 3780 New: "", 3781 }, 3782 }, 3783 }, 3784 }, 3785 }, 3786 }, 3787 }, 3788 }, 3789 { 3790 Name: "Template edited", 3791 Old: &Task{ 3792 Templates: []*Template{ 3793 { 3794 SourcePath: "foo", 3795 DestPath: "bar", 3796 EmbeddedTmpl: "baz", 3797 ChangeMode: "bam", 3798 ChangeSignal: "SIGHUP", 3799 Splay: 1, 3800 Perms: "0644", 3801 }, 3802 { 3803 SourcePath: "foo2", 3804 DestPath: "bar2", 3805 EmbeddedTmpl: "baz2", 3806 ChangeMode: "bam2", 3807 ChangeSignal: "SIGHUP2", 3808 Splay: 2, 3809 Perms: "0666", 3810 Envvars: true, 3811 }, 3812 }, 3813 }, 3814 New: &Task{ 3815 Templates: []*Template{ 3816 { 3817 SourcePath: "foo", 3818 DestPath: "bar", 3819 EmbeddedTmpl: "baz", 3820 ChangeMode: "bam", 3821 ChangeSignal: "SIGHUP", 3822 Splay: 1, 3823 Perms: "0644", 3824 }, 3825 { 3826 SourcePath: "foo3", 3827 DestPath: "bar3", 3828 EmbeddedTmpl: "baz3", 3829 ChangeMode: "bam3", 3830 ChangeSignal: "SIGHUP3", 3831 Splay: 3, 3832 Perms: "0776", 3833 }, 3834 }, 3835 }, 3836 Expected: &TaskDiff{ 3837 Type: DiffTypeEdited, 3838 Objects: []*ObjectDiff{ 3839 { 3840 Type: DiffTypeAdded, 3841 Name: "Template", 3842 Fields: []*FieldDiff{ 3843 { 3844 Type: DiffTypeAdded, 3845 Name: "ChangeMode", 3846 Old: "", 3847 New: "bam3", 3848 }, 3849 { 3850 Type: DiffTypeAdded, 3851 Name: "ChangeSignal", 3852 Old: "", 3853 New: "SIGHUP3", 3854 }, 3855 { 3856 Type: DiffTypeAdded, 3857 Name: "DestPath", 3858 Old: "", 3859 New: "bar3", 3860 }, 3861 { 3862 Type: DiffTypeAdded, 3863 Name: "EmbeddedTmpl", 3864 Old: "", 3865 New: "baz3", 3866 }, 3867 { 3868 Type: DiffTypeAdded, 3869 Name: "Envvars", 3870 Old: "", 3871 New: "false", 3872 }, 3873 { 3874 Type: DiffTypeAdded, 3875 Name: "Perms", 3876 Old: "", 3877 New: "0776", 3878 }, 3879 { 3880 Type: DiffTypeAdded, 3881 Name: "SourcePath", 3882 Old: "", 3883 New: "foo3", 3884 }, 3885 { 3886 Type: DiffTypeAdded, 3887 Name: "Splay", 3888 Old: "", 3889 New: "3", 3890 }, 3891 }, 3892 }, 3893 { 3894 Type: DiffTypeDeleted, 3895 Name: "Template", 3896 Fields: []*FieldDiff{ 3897 { 3898 Type: DiffTypeDeleted, 3899 Name: "ChangeMode", 3900 Old: "bam2", 3901 New: "", 3902 }, 3903 { 3904 Type: DiffTypeDeleted, 3905 Name: "ChangeSignal", 3906 Old: "SIGHUP2", 3907 New: "", 3908 }, 3909 { 3910 Type: DiffTypeDeleted, 3911 Name: "DestPath", 3912 Old: "bar2", 3913 New: "", 3914 }, 3915 { 3916 Type: DiffTypeDeleted, 3917 Name: "EmbeddedTmpl", 3918 Old: "baz2", 3919 New: "", 3920 }, 3921 { 3922 Type: DiffTypeDeleted, 3923 Name: "Envvars", 3924 Old: "true", 3925 New: "", 3926 }, 3927 { 3928 Type: DiffTypeDeleted, 3929 Name: "Perms", 3930 Old: "0666", 3931 New: "", 3932 }, 3933 { 3934 Type: DiffTypeDeleted, 3935 Name: "SourcePath", 3936 Old: "foo2", 3937 New: "", 3938 }, 3939 { 3940 Type: DiffTypeDeleted, 3941 Name: "Splay", 3942 Old: "2", 3943 New: "", 3944 }, 3945 }, 3946 }, 3947 }, 3948 }, 3949 }, 3950 { 3951 Name: "DispatchPayload added", 3952 Old: &Task{}, 3953 New: &Task{ 3954 DispatchPayload: &DispatchPayloadConfig{ 3955 File: "foo", 3956 }, 3957 }, 3958 Expected: &TaskDiff{ 3959 Type: DiffTypeEdited, 3960 Objects: []*ObjectDiff{ 3961 { 3962 Type: DiffTypeAdded, 3963 Name: "DispatchPayload", 3964 Fields: []*FieldDiff{ 3965 { 3966 Type: DiffTypeAdded, 3967 Name: "File", 3968 Old: "", 3969 New: "foo", 3970 }, 3971 }, 3972 }, 3973 }, 3974 }, 3975 }, 3976 { 3977 Name: "DispatchPayload deleted", 3978 Old: &Task{ 3979 DispatchPayload: &DispatchPayloadConfig{ 3980 File: "foo", 3981 }, 3982 }, 3983 New: &Task{}, 3984 Expected: &TaskDiff{ 3985 Type: DiffTypeEdited, 3986 Objects: []*ObjectDiff{ 3987 { 3988 Type: DiffTypeDeleted, 3989 Name: "DispatchPayload", 3990 Fields: []*FieldDiff{ 3991 { 3992 Type: DiffTypeDeleted, 3993 Name: "File", 3994 Old: "foo", 3995 New: "", 3996 }, 3997 }, 3998 }, 3999 }, 4000 }, 4001 }, 4002 { 4003 Name: "Dispatch payload edited", 4004 Old: &Task{ 4005 DispatchPayload: &DispatchPayloadConfig{ 4006 File: "foo", 4007 }, 4008 }, 4009 New: &Task{ 4010 DispatchPayload: &DispatchPayloadConfig{ 4011 File: "bar", 4012 }, 4013 }, 4014 Expected: &TaskDiff{ 4015 Type: DiffTypeEdited, 4016 Objects: []*ObjectDiff{ 4017 { 4018 Type: DiffTypeEdited, 4019 Name: "DispatchPayload", 4020 Fields: []*FieldDiff{ 4021 { 4022 Type: DiffTypeEdited, 4023 Name: "File", 4024 Old: "foo", 4025 New: "bar", 4026 }, 4027 }, 4028 }, 4029 }, 4030 }, 4031 }, 4032 { 4033 // Place holder for if more fields are added 4034 Name: "DispatchPayload edited with context", 4035 Contextual: true, 4036 Old: &Task{ 4037 DispatchPayload: &DispatchPayloadConfig{ 4038 File: "foo", 4039 }, 4040 }, 4041 New: &Task{ 4042 DispatchPayload: &DispatchPayloadConfig{ 4043 File: "bar", 4044 }, 4045 }, 4046 Expected: &TaskDiff{ 4047 Type: DiffTypeEdited, 4048 Objects: []*ObjectDiff{ 4049 { 4050 Type: DiffTypeEdited, 4051 Name: "DispatchPayload", 4052 Fields: []*FieldDiff{ 4053 { 4054 Type: DiffTypeEdited, 4055 Name: "File", 4056 Old: "foo", 4057 New: "bar", 4058 }, 4059 }, 4060 }, 4061 }, 4062 }, 4063 }, 4064 } 4065 4066 for i, c := range cases { 4067 t.Run(c.Name, func(t *testing.T) { 4068 actual, err := c.Old.Diff(c.New, c.Contextual) 4069 if c.Error && err == nil { 4070 t.Fatalf("case %d: expected errored", i+1) 4071 } else if err != nil { 4072 if !c.Error { 4073 t.Fatalf("case %d: errored %#v", i+1, err) 4074 } else { 4075 return 4076 } 4077 } 4078 4079 if !reflect.DeepEqual(actual, c.Expected) { 4080 t.Errorf("case %d: got:\n%#v\n want:\n%#v\n", 4081 i+1, actual, c.Expected) 4082 } 4083 }) 4084 } 4085 }