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