github.com/hernad/nomad@v1.6.112/nomad/structs/diff_test.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package structs 5 6 import ( 7 "reflect" 8 "testing" 9 "time" 10 11 "github.com/hernad/nomad/ci" 12 "github.com/hernad/nomad/helper/pointer" 13 "github.com/stretchr/testify/require" 14 ) 15 16 func TestJobDiff(t *testing.T) { 17 ci.Parallel(t) 18 19 cases := []struct { 20 Old, New *Job 21 Expected *JobDiff 22 Error bool 23 Contextual bool 24 }{ 25 { 26 Old: nil, 27 New: nil, 28 Expected: &JobDiff{ 29 Type: DiffTypeNone, 30 }, 31 }, 32 { 33 // Different IDs 34 Old: &Job{ 35 ID: "foo", 36 }, 37 New: &Job{ 38 ID: "bar", 39 }, 40 Error: true, 41 }, 42 { 43 // Primitive only that is the same 44 Old: &Job{ 45 Region: "foo", 46 ID: "foo", 47 Name: "foo", 48 Type: "batch", 49 Priority: 10, 50 AllAtOnce: true, 51 Meta: map[string]string{ 52 "foo": "bar", 53 }, 54 }, 55 New: &Job{ 56 Region: "foo", 57 ID: "foo", 58 Name: "foo", 59 Type: "batch", 60 Priority: 10, 61 AllAtOnce: true, 62 Meta: map[string]string{ 63 "foo": "bar", 64 }, 65 }, 66 Expected: &JobDiff{ 67 Type: DiffTypeNone, 68 ID: "foo", 69 }, 70 }, 71 { 72 // Primitive only that is has diffs 73 Old: &Job{ 74 Region: "foo", 75 ID: "foo", 76 Name: "foo", 77 Type: "batch", 78 Priority: 10, 79 AllAtOnce: true, 80 Meta: map[string]string{ 81 "foo": "bar", 82 }, 83 }, 84 New: &Job{ 85 Region: "bar", 86 ID: "foo", 87 Name: "bar", 88 Type: "system", 89 Priority: 100, 90 AllAtOnce: false, 91 Meta: map[string]string{ 92 "foo": "baz", 93 }, 94 }, 95 Expected: &JobDiff{ 96 Type: DiffTypeEdited, 97 ID: "foo", 98 Fields: []*FieldDiff{ 99 { 100 Type: DiffTypeEdited, 101 Name: "AllAtOnce", 102 Old: "true", 103 New: "false", 104 }, 105 { 106 Type: DiffTypeEdited, 107 Name: "Meta[foo]", 108 Old: "bar", 109 New: "baz", 110 }, 111 { 112 Type: DiffTypeEdited, 113 Name: "Name", 114 Old: "foo", 115 New: "bar", 116 }, 117 { 118 Type: DiffTypeEdited, 119 Name: "Priority", 120 Old: "10", 121 New: "100", 122 }, 123 { 124 Type: DiffTypeEdited, 125 Name: "Region", 126 Old: "foo", 127 New: "bar", 128 }, 129 { 130 Type: DiffTypeEdited, 131 Name: "Type", 132 Old: "batch", 133 New: "system", 134 }, 135 }, 136 }, 137 }, 138 { 139 // Primitive only deleted job 140 Old: &Job{ 141 Region: "foo", 142 ID: "foo", 143 Name: "foo", 144 Type: "batch", 145 Priority: 10, 146 AllAtOnce: true, 147 Meta: map[string]string{ 148 "foo": "bar", 149 }, 150 }, 151 New: nil, 152 Expected: &JobDiff{ 153 Type: DiffTypeDeleted, 154 ID: "foo", 155 Fields: []*FieldDiff{ 156 { 157 Type: DiffTypeDeleted, 158 Name: "AllAtOnce", 159 Old: "true", 160 New: "", 161 }, 162 { 163 Type: DiffTypeDeleted, 164 Name: "Dispatched", 165 Old: "false", 166 New: "", 167 }, 168 { 169 Type: DiffTypeDeleted, 170 Name: "Meta[foo]", 171 Old: "bar", 172 New: "", 173 }, 174 { 175 Type: DiffTypeDeleted, 176 Name: "Name", 177 Old: "foo", 178 New: "", 179 }, 180 { 181 Type: DiffTypeDeleted, 182 Name: "Priority", 183 Old: "10", 184 New: "", 185 }, 186 { 187 Type: DiffTypeDeleted, 188 Name: "Region", 189 Old: "foo", 190 New: "", 191 }, 192 { 193 Type: DiffTypeDeleted, 194 Name: "Stop", 195 Old: "false", 196 New: "", 197 }, 198 { 199 Type: DiffTypeDeleted, 200 Name: "Type", 201 Old: "batch", 202 New: "", 203 }, 204 }, 205 }, 206 }, 207 { 208 // Primitive only added job 209 Old: nil, 210 New: &Job{ 211 Region: "foo", 212 ID: "foo", 213 Name: "foo", 214 Type: "batch", 215 Priority: 10, 216 AllAtOnce: true, 217 Meta: map[string]string{ 218 "foo": "bar", 219 }, 220 }, 221 Expected: &JobDiff{ 222 Type: DiffTypeAdded, 223 ID: "foo", 224 Fields: []*FieldDiff{ 225 { 226 Type: DiffTypeAdded, 227 Name: "AllAtOnce", 228 Old: "", 229 New: "true", 230 }, 231 { 232 Type: DiffTypeAdded, 233 Name: "Dispatched", 234 Old: "", 235 New: "false", 236 }, 237 { 238 Type: DiffTypeAdded, 239 Name: "Meta[foo]", 240 Old: "", 241 New: "bar", 242 }, 243 { 244 Type: DiffTypeAdded, 245 Name: "Name", 246 Old: "", 247 New: "foo", 248 }, 249 { 250 Type: DiffTypeAdded, 251 Name: "Priority", 252 Old: "", 253 New: "10", 254 }, 255 { 256 Type: DiffTypeAdded, 257 Name: "Region", 258 Old: "", 259 New: "foo", 260 }, 261 { 262 Type: DiffTypeAdded, 263 Name: "Stop", 264 Old: "", 265 New: "false", 266 }, 267 { 268 Type: DiffTypeAdded, 269 Name: "Type", 270 Old: "", 271 New: "batch", 272 }, 273 }, 274 }, 275 }, 276 { 277 // Map diff 278 Old: &Job{ 279 Meta: map[string]string{ 280 "foo": "foo", 281 "bar": "bar", 282 }, 283 }, 284 New: &Job{ 285 Meta: map[string]string{ 286 "bar": "bar", 287 "baz": "baz", 288 }, 289 }, 290 Expected: &JobDiff{ 291 Type: DiffTypeEdited, 292 Fields: []*FieldDiff{ 293 { 294 Type: DiffTypeAdded, 295 Name: "Meta[baz]", 296 Old: "", 297 New: "baz", 298 }, 299 { 300 Type: DiffTypeDeleted, 301 Name: "Meta[foo]", 302 Old: "foo", 303 New: "", 304 }, 305 }, 306 }, 307 }, 308 { 309 // Datacenter diff both added and removed 310 Old: &Job{ 311 Datacenters: []string{"foo", "bar"}, 312 }, 313 New: &Job{ 314 Datacenters: []string{"baz", "bar"}, 315 }, 316 Expected: &JobDiff{ 317 Type: DiffTypeEdited, 318 Objects: []*ObjectDiff{ 319 { 320 Type: DiffTypeEdited, 321 Name: "Datacenters", 322 Fields: []*FieldDiff{ 323 { 324 Type: DiffTypeAdded, 325 Name: "Datacenters", 326 Old: "", 327 New: "baz", 328 }, 329 { 330 Type: DiffTypeDeleted, 331 Name: "Datacenters", 332 Old: "foo", 333 New: "", 334 }, 335 }, 336 }, 337 }, 338 }, 339 }, 340 { 341 // Datacenter diff just added 342 Old: &Job{ 343 Datacenters: []string{"foo", "bar"}, 344 }, 345 New: &Job{ 346 Datacenters: []string{"foo", "bar", "baz"}, 347 }, 348 Expected: &JobDiff{ 349 Type: DiffTypeEdited, 350 Objects: []*ObjectDiff{ 351 { 352 Type: DiffTypeAdded, 353 Name: "Datacenters", 354 Fields: []*FieldDiff{ 355 { 356 Type: DiffTypeAdded, 357 Name: "Datacenters", 358 Old: "", 359 New: "baz", 360 }, 361 }, 362 }, 363 }, 364 }, 365 }, 366 { 367 // Datacenter diff just deleted 368 Old: &Job{ 369 Datacenters: []string{"foo", "bar"}, 370 }, 371 New: &Job{ 372 Datacenters: []string{"foo"}, 373 }, 374 Expected: &JobDiff{ 375 Type: DiffTypeEdited, 376 Objects: []*ObjectDiff{ 377 { 378 Type: DiffTypeDeleted, 379 Name: "Datacenters", 380 Fields: []*FieldDiff{ 381 { 382 Type: DiffTypeDeleted, 383 Name: "Datacenters", 384 Old: "bar", 385 New: "", 386 }, 387 }, 388 }, 389 }, 390 }, 391 }, 392 { 393 // Datacenter contextual no change 394 Contextual: true, 395 Old: &Job{ 396 Datacenters: []string{"foo", "bar"}, 397 }, 398 New: &Job{ 399 Datacenters: []string{"foo", "bar"}, 400 }, 401 Expected: &JobDiff{ 402 Type: DiffTypeNone, 403 }, 404 }, 405 { 406 // Datacenter contextual 407 Contextual: true, 408 Old: &Job{ 409 Datacenters: []string{"foo", "bar"}, 410 }, 411 New: &Job{ 412 Datacenters: []string{"foo", "bar", "baz"}, 413 }, 414 Expected: &JobDiff{ 415 Type: DiffTypeEdited, 416 Objects: []*ObjectDiff{ 417 { 418 Type: DiffTypeAdded, 419 Name: "Datacenters", 420 Fields: []*FieldDiff{ 421 { 422 Type: DiffTypeAdded, 423 Name: "Datacenters", 424 Old: "", 425 New: "baz", 426 }, 427 { 428 Type: DiffTypeNone, 429 Name: "Datacenters", 430 Old: "bar", 431 New: "bar", 432 }, 433 { 434 Type: DiffTypeNone, 435 Name: "Datacenters", 436 Old: "foo", 437 New: "foo", 438 }, 439 }, 440 }, 441 }, 442 }, 443 }, 444 445 { 446 // NodePool added 447 Old: &Job{}, 448 New: &Job{ 449 NodePool: "default", 450 }, 451 Expected: &JobDiff{ 452 Type: DiffTypeEdited, 453 Fields: []*FieldDiff{ 454 { 455 Type: DiffTypeAdded, 456 Name: "NodePool", 457 Old: "", 458 New: "default", 459 }, 460 }, 461 }, 462 }, 463 { 464 // NodePool removed 465 Old: &Job{ 466 NodePool: "default", 467 }, 468 New: &Job{}, 469 Expected: &JobDiff{ 470 Type: DiffTypeEdited, 471 Fields: []*FieldDiff{ 472 { 473 Type: DiffTypeDeleted, 474 Name: "NodePool", 475 Old: "default", 476 New: "", 477 }, 478 }, 479 }, 480 }, 481 { 482 // NodePool changed 483 Old: &Job{ 484 NodePool: "default", 485 }, 486 New: &Job{ 487 NodePool: "foo", 488 }, 489 Expected: &JobDiff{ 490 Type: DiffTypeEdited, 491 Fields: []*FieldDiff{ 492 { 493 Type: DiffTypeEdited, 494 Name: "NodePool", 495 Old: "default", 496 New: "foo", 497 }, 498 }, 499 }, 500 }, 501 { 502 // NodePool unchanged 503 Old: &Job{ 504 NodePool: "foo", 505 }, 506 New: &Job{ 507 NodePool: "foo", 508 }, 509 Expected: &JobDiff{ 510 Type: DiffTypeNone, 511 }, 512 }, 513 514 { 515 // Periodic added 516 Old: &Job{}, 517 New: &Job{ 518 Periodic: &PeriodicConfig{ 519 Enabled: false, 520 Spec: "*/15 * * * * *", 521 SpecType: "foo", 522 ProhibitOverlap: false, 523 TimeZone: "Europe/Minsk", 524 }, 525 }, 526 Expected: &JobDiff{ 527 Type: DiffTypeEdited, 528 Objects: []*ObjectDiff{ 529 { 530 Type: DiffTypeAdded, 531 Name: "Periodic", 532 Fields: []*FieldDiff{ 533 { 534 Type: DiffTypeAdded, 535 Name: "Enabled", 536 Old: "", 537 New: "false", 538 }, 539 { 540 Type: DiffTypeAdded, 541 Name: "ProhibitOverlap", 542 Old: "", 543 New: "false", 544 }, 545 { 546 Type: DiffTypeAdded, 547 Name: "Spec", 548 Old: "", 549 New: "*/15 * * * * *", 550 }, 551 { 552 Type: DiffTypeAdded, 553 Name: "SpecType", 554 Old: "", 555 New: "foo", 556 }, 557 { 558 Type: DiffTypeAdded, 559 Name: "TimeZone", 560 Old: "", 561 New: "Europe/Minsk", 562 }, 563 }, 564 }, 565 }, 566 }, 567 }, 568 { 569 // Periodic deleted 570 Old: &Job{ 571 Periodic: &PeriodicConfig{ 572 Enabled: false, 573 Spec: "*/15 * * * * *", 574 SpecType: "foo", 575 ProhibitOverlap: false, 576 TimeZone: "Europe/Minsk", 577 }, 578 }, 579 New: &Job{}, 580 Expected: &JobDiff{ 581 Type: DiffTypeEdited, 582 Objects: []*ObjectDiff{ 583 { 584 Type: DiffTypeDeleted, 585 Name: "Periodic", 586 Fields: []*FieldDiff{ 587 { 588 Type: DiffTypeDeleted, 589 Name: "Enabled", 590 Old: "false", 591 New: "", 592 }, 593 { 594 Type: DiffTypeDeleted, 595 Name: "ProhibitOverlap", 596 Old: "false", 597 New: "", 598 }, 599 { 600 Type: DiffTypeDeleted, 601 Name: "Spec", 602 Old: "*/15 * * * * *", 603 New: "", 604 }, 605 { 606 Type: DiffTypeDeleted, 607 Name: "SpecType", 608 Old: "foo", 609 New: "", 610 }, 611 { 612 Type: DiffTypeDeleted, 613 Name: "TimeZone", 614 Old: "Europe/Minsk", 615 New: "", 616 }, 617 }, 618 }, 619 }, 620 }, 621 }, 622 { 623 // Periodic edited 624 Old: &Job{ 625 Periodic: &PeriodicConfig{ 626 Enabled: false, 627 Spec: "*/15 * * * * *", 628 SpecType: "foo", 629 ProhibitOverlap: false, 630 TimeZone: "Europe/Minsk", 631 }, 632 }, 633 New: &Job{ 634 Periodic: &PeriodicConfig{ 635 Enabled: true, 636 Spec: "* * * * * *", 637 SpecType: "cron", 638 ProhibitOverlap: true, 639 TimeZone: "America/Los_Angeles", 640 }, 641 }, 642 Expected: &JobDiff{ 643 Type: DiffTypeEdited, 644 Objects: []*ObjectDiff{ 645 { 646 Type: DiffTypeEdited, 647 Name: "Periodic", 648 Fields: []*FieldDiff{ 649 { 650 Type: DiffTypeEdited, 651 Name: "Enabled", 652 Old: "false", 653 New: "true", 654 }, 655 { 656 Type: DiffTypeEdited, 657 Name: "ProhibitOverlap", 658 Old: "false", 659 New: "true", 660 }, 661 { 662 Type: DiffTypeEdited, 663 Name: "Spec", 664 Old: "*/15 * * * * *", 665 New: "* * * * * *", 666 }, 667 { 668 Type: DiffTypeEdited, 669 Name: "SpecType", 670 Old: "foo", 671 New: "cron", 672 }, 673 { 674 Type: DiffTypeEdited, 675 Name: "TimeZone", 676 Old: "Europe/Minsk", 677 New: "America/Los_Angeles", 678 }, 679 }, 680 }, 681 }, 682 }, 683 }, 684 { 685 // Periodic edited with context 686 Contextual: true, 687 Old: &Job{ 688 Periodic: &PeriodicConfig{ 689 Enabled: false, 690 Spec: "*/15 * * * * *", 691 SpecType: "foo", 692 ProhibitOverlap: false, 693 TimeZone: "Europe/Minsk", 694 }, 695 }, 696 New: &Job{ 697 Periodic: &PeriodicConfig{ 698 Enabled: true, 699 Spec: "* * * * * *", 700 SpecType: "foo", 701 ProhibitOverlap: false, 702 TimeZone: "Europe/Minsk", 703 }, 704 }, 705 Expected: &JobDiff{ 706 Type: DiffTypeEdited, 707 Objects: []*ObjectDiff{ 708 { 709 Type: DiffTypeEdited, 710 Name: "Periodic", 711 Fields: []*FieldDiff{ 712 { 713 Type: DiffTypeEdited, 714 Name: "Enabled", 715 Old: "false", 716 New: "true", 717 }, 718 { 719 Type: DiffTypeNone, 720 Name: "ProhibitOverlap", 721 Old: "false", 722 New: "false", 723 }, 724 { 725 Type: DiffTypeEdited, 726 Name: "Spec", 727 Old: "*/15 * * * * *", 728 New: "* * * * * *", 729 }, 730 { 731 Type: DiffTypeNone, 732 Name: "SpecType", 733 Old: "foo", 734 New: "foo", 735 }, 736 { 737 Type: DiffTypeNone, 738 Name: "TimeZone", 739 Old: "Europe/Minsk", 740 New: "Europe/Minsk", 741 }, 742 }, 743 }, 744 }, 745 }, 746 }, 747 { 748 // Constraints edited 749 Old: &Job{ 750 Constraints: []*Constraint{ 751 { 752 LTarget: "foo", 753 RTarget: "foo", 754 Operand: "foo", 755 }, 756 { 757 LTarget: "bar", 758 RTarget: "bar", 759 Operand: "bar", 760 }, 761 }, 762 }, 763 New: &Job{ 764 Constraints: []*Constraint{ 765 { 766 LTarget: "foo", 767 RTarget: "foo", 768 Operand: "foo", 769 }, 770 { 771 LTarget: "baz", 772 RTarget: "baz", 773 Operand: "baz", 774 }, 775 }, 776 }, 777 Expected: &JobDiff{ 778 Type: DiffTypeEdited, 779 Objects: []*ObjectDiff{ 780 { 781 Type: DiffTypeAdded, 782 Name: "Constraint", 783 Fields: []*FieldDiff{ 784 { 785 Type: DiffTypeAdded, 786 Name: "LTarget", 787 Old: "", 788 New: "baz", 789 }, 790 { 791 Type: DiffTypeAdded, 792 Name: "Operand", 793 Old: "", 794 New: "baz", 795 }, 796 { 797 Type: DiffTypeAdded, 798 Name: "RTarget", 799 Old: "", 800 New: "baz", 801 }, 802 }, 803 }, 804 { 805 Type: DiffTypeDeleted, 806 Name: "Constraint", 807 Fields: []*FieldDiff{ 808 { 809 Type: DiffTypeDeleted, 810 Name: "LTarget", 811 Old: "bar", 812 New: "", 813 }, 814 { 815 Type: DiffTypeDeleted, 816 Name: "Operand", 817 Old: "bar", 818 New: "", 819 }, 820 { 821 Type: DiffTypeDeleted, 822 Name: "RTarget", 823 Old: "bar", 824 New: "", 825 }, 826 }, 827 }, 828 }, 829 }, 830 }, 831 { 832 // Affinities edited 833 Old: &Job{ 834 Affinities: []*Affinity{ 835 { 836 LTarget: "foo", 837 RTarget: "foo", 838 Operand: "foo", 839 Weight: 20, 840 }, 841 { 842 LTarget: "bar", 843 RTarget: "bar", 844 Operand: "bar", 845 Weight: 20, 846 }, 847 }, 848 }, 849 New: &Job{ 850 Affinities: []*Affinity{ 851 { 852 LTarget: "foo", 853 RTarget: "foo", 854 Operand: "foo", 855 Weight: 20, 856 }, 857 { 858 LTarget: "baz", 859 RTarget: "baz", 860 Operand: "baz", 861 Weight: 20, 862 }, 863 }, 864 }, 865 Expected: &JobDiff{ 866 Type: DiffTypeEdited, 867 Objects: []*ObjectDiff{ 868 { 869 Type: DiffTypeAdded, 870 Name: "Affinity", 871 Fields: []*FieldDiff{ 872 { 873 Type: DiffTypeAdded, 874 Name: "LTarget", 875 Old: "", 876 New: "baz", 877 }, 878 { 879 Type: DiffTypeAdded, 880 Name: "Operand", 881 Old: "", 882 New: "baz", 883 }, 884 { 885 Type: DiffTypeAdded, 886 Name: "RTarget", 887 Old: "", 888 New: "baz", 889 }, 890 { 891 Type: DiffTypeAdded, 892 Name: "Weight", 893 Old: "", 894 New: "20", 895 }, 896 }, 897 }, 898 { 899 Type: DiffTypeDeleted, 900 Name: "Affinity", 901 Fields: []*FieldDiff{ 902 { 903 Type: DiffTypeDeleted, 904 Name: "LTarget", 905 Old: "bar", 906 New: "", 907 }, 908 { 909 Type: DiffTypeDeleted, 910 Name: "Operand", 911 Old: "bar", 912 New: "", 913 }, 914 { 915 Type: DiffTypeDeleted, 916 Name: "RTarget", 917 Old: "bar", 918 New: "", 919 }, 920 { 921 Type: DiffTypeDeleted, 922 Name: "Weight", 923 Old: "20", 924 New: "", 925 }, 926 }, 927 }, 928 }, 929 }, 930 }, 931 { 932 // Task groups edited 933 Old: &Job{ 934 TaskGroups: []*TaskGroup{ 935 { 936 Name: "foo", 937 Count: 1, 938 }, 939 { 940 Name: "bar", 941 Count: 1, 942 }, 943 { 944 Name: "baz", 945 Count: 1, 946 }, 947 }, 948 }, 949 New: &Job{ 950 TaskGroups: []*TaskGroup{ 951 { 952 Name: "bar", 953 Count: 1, 954 }, 955 { 956 Name: "baz", 957 Count: 2, 958 }, 959 { 960 Name: "bam", 961 Count: 1, 962 }, 963 }, 964 }, 965 Expected: &JobDiff{ 966 Type: DiffTypeEdited, 967 TaskGroups: []*TaskGroupDiff{ 968 { 969 Type: DiffTypeAdded, 970 Name: "bam", 971 Fields: []*FieldDiff{ 972 { 973 Type: DiffTypeAdded, 974 Name: "Count", 975 Old: "", 976 New: "1", 977 }, 978 }, 979 }, 980 { 981 Type: DiffTypeNone, 982 Name: "bar", 983 }, 984 { 985 Type: DiffTypeEdited, 986 Name: "baz", 987 Fields: []*FieldDiff{ 988 { 989 Type: DiffTypeEdited, 990 Name: "Count", 991 Old: "1", 992 New: "2", 993 }, 994 }, 995 }, 996 { 997 Type: DiffTypeDeleted, 998 Name: "foo", 999 Fields: []*FieldDiff{ 1000 { 1001 Type: DiffTypeDeleted, 1002 Name: "Count", 1003 Old: "1", 1004 New: "", 1005 }, 1006 }, 1007 }, 1008 }, 1009 }, 1010 }, 1011 { 1012 // Parameterized Job added 1013 Old: &Job{}, 1014 New: &Job{ 1015 ParameterizedJob: &ParameterizedJobConfig{ 1016 Payload: DispatchPayloadRequired, 1017 MetaOptional: []string{"foo"}, 1018 MetaRequired: []string{"bar"}, 1019 }, 1020 }, 1021 Expected: &JobDiff{ 1022 Type: DiffTypeEdited, 1023 Objects: []*ObjectDiff{ 1024 { 1025 Type: DiffTypeAdded, 1026 Name: "ParameterizedJob", 1027 Fields: []*FieldDiff{ 1028 { 1029 Type: DiffTypeAdded, 1030 Name: "Payload", 1031 Old: "", 1032 New: DispatchPayloadRequired, 1033 }, 1034 }, 1035 Objects: []*ObjectDiff{ 1036 { 1037 Type: DiffTypeAdded, 1038 Name: "MetaOptional", 1039 Fields: []*FieldDiff{ 1040 { 1041 Type: DiffTypeAdded, 1042 Name: "MetaOptional", 1043 Old: "", 1044 New: "foo", 1045 }, 1046 }, 1047 }, 1048 { 1049 Type: DiffTypeAdded, 1050 Name: "MetaRequired", 1051 Fields: []*FieldDiff{ 1052 { 1053 Type: DiffTypeAdded, 1054 Name: "MetaRequired", 1055 Old: "", 1056 New: "bar", 1057 }, 1058 }, 1059 }, 1060 }, 1061 }, 1062 }, 1063 }, 1064 }, 1065 { 1066 // Parameterized Job deleted 1067 Old: &Job{ 1068 ParameterizedJob: &ParameterizedJobConfig{ 1069 Payload: DispatchPayloadRequired, 1070 MetaOptional: []string{"foo"}, 1071 MetaRequired: []string{"bar"}, 1072 }, 1073 }, 1074 New: &Job{}, 1075 Expected: &JobDiff{ 1076 Type: DiffTypeEdited, 1077 Objects: []*ObjectDiff{ 1078 { 1079 Type: DiffTypeDeleted, 1080 Name: "ParameterizedJob", 1081 Fields: []*FieldDiff{ 1082 { 1083 Type: DiffTypeDeleted, 1084 Name: "Payload", 1085 Old: DispatchPayloadRequired, 1086 New: "", 1087 }, 1088 }, 1089 Objects: []*ObjectDiff{ 1090 { 1091 Type: DiffTypeDeleted, 1092 Name: "MetaOptional", 1093 Fields: []*FieldDiff{ 1094 { 1095 Type: DiffTypeDeleted, 1096 Name: "MetaOptional", 1097 Old: "foo", 1098 New: "", 1099 }, 1100 }, 1101 }, 1102 { 1103 Type: DiffTypeDeleted, 1104 Name: "MetaRequired", 1105 Fields: []*FieldDiff{ 1106 { 1107 Type: DiffTypeDeleted, 1108 Name: "MetaRequired", 1109 Old: "bar", 1110 New: "", 1111 }, 1112 }, 1113 }, 1114 }, 1115 }, 1116 }, 1117 }, 1118 }, 1119 { 1120 // Parameterized Job edited 1121 Old: &Job{ 1122 ParameterizedJob: &ParameterizedJobConfig{ 1123 Payload: DispatchPayloadRequired, 1124 MetaOptional: []string{"foo"}, 1125 MetaRequired: []string{"bar"}, 1126 }, 1127 }, 1128 New: &Job{ 1129 ParameterizedJob: &ParameterizedJobConfig{ 1130 Payload: DispatchPayloadOptional, 1131 MetaOptional: []string{"bam"}, 1132 MetaRequired: []string{"bang"}, 1133 }, 1134 }, 1135 Expected: &JobDiff{ 1136 Type: DiffTypeEdited, 1137 Objects: []*ObjectDiff{ 1138 { 1139 Type: DiffTypeEdited, 1140 Name: "ParameterizedJob", 1141 Fields: []*FieldDiff{ 1142 { 1143 Type: DiffTypeEdited, 1144 Name: "Payload", 1145 Old: DispatchPayloadRequired, 1146 New: DispatchPayloadOptional, 1147 }, 1148 }, 1149 Objects: []*ObjectDiff{ 1150 { 1151 Type: DiffTypeEdited, 1152 Name: "MetaOptional", 1153 Fields: []*FieldDiff{ 1154 { 1155 Type: DiffTypeAdded, 1156 Name: "MetaOptional", 1157 Old: "", 1158 New: "bam", 1159 }, 1160 { 1161 Type: DiffTypeDeleted, 1162 Name: "MetaOptional", 1163 Old: "foo", 1164 New: "", 1165 }, 1166 }, 1167 }, 1168 { 1169 Type: DiffTypeEdited, 1170 Name: "MetaRequired", 1171 Fields: []*FieldDiff{ 1172 { 1173 Type: DiffTypeAdded, 1174 Name: "MetaRequired", 1175 Old: "", 1176 New: "bang", 1177 }, 1178 { 1179 Type: DiffTypeDeleted, 1180 Name: "MetaRequired", 1181 Old: "bar", 1182 New: "", 1183 }, 1184 }, 1185 }, 1186 }, 1187 }, 1188 }, 1189 }, 1190 }, 1191 { 1192 // Parameterized Job edited with context 1193 Contextual: true, 1194 Old: &Job{ 1195 ParameterizedJob: &ParameterizedJobConfig{ 1196 Payload: DispatchPayloadRequired, 1197 MetaOptional: []string{"foo"}, 1198 MetaRequired: []string{"bar"}, 1199 }, 1200 }, 1201 New: &Job{ 1202 ParameterizedJob: &ParameterizedJobConfig{ 1203 Payload: DispatchPayloadOptional, 1204 MetaOptional: []string{"foo"}, 1205 MetaRequired: []string{"bar"}, 1206 }, 1207 }, 1208 Expected: &JobDiff{ 1209 Type: DiffTypeEdited, 1210 Objects: []*ObjectDiff{ 1211 { 1212 Type: DiffTypeEdited, 1213 Name: "ParameterizedJob", 1214 Fields: []*FieldDiff{ 1215 { 1216 Type: DiffTypeEdited, 1217 Name: "Payload", 1218 Old: DispatchPayloadRequired, 1219 New: DispatchPayloadOptional, 1220 }, 1221 }, 1222 Objects: []*ObjectDiff{ 1223 { 1224 Type: DiffTypeNone, 1225 Name: "MetaOptional", 1226 Fields: []*FieldDiff{ 1227 { 1228 Type: DiffTypeNone, 1229 Name: "MetaOptional", 1230 Old: "foo", 1231 New: "foo", 1232 }, 1233 }, 1234 }, 1235 { 1236 Type: DiffTypeNone, 1237 Name: "MetaRequired", 1238 Fields: []*FieldDiff{ 1239 { 1240 Type: DiffTypeNone, 1241 Name: "MetaRequired", 1242 Old: "bar", 1243 New: "bar", 1244 }, 1245 }, 1246 }, 1247 }, 1248 }, 1249 }, 1250 }, 1251 }, 1252 { 1253 // Multiregion: region added 1254 Old: &Job{ 1255 NomadTokenID: "abcdef", 1256 Multiregion: &Multiregion{ 1257 Strategy: &MultiregionStrategy{ 1258 MaxParallel: 1, 1259 OnFailure: "fail_all", 1260 }, 1261 Regions: []*MultiregionRegion{ 1262 { 1263 Name: "west", 1264 Count: 1, 1265 Datacenters: []string{"west-1"}, 1266 Meta: map[string]string{"region_code": "W"}, 1267 }, 1268 }, 1269 }, 1270 }, 1271 1272 New: &Job{ 1273 NomadTokenID: "12345", 1274 Multiregion: &Multiregion{ 1275 Strategy: &MultiregionStrategy{ 1276 MaxParallel: 2, 1277 OnFailure: "fail_all", 1278 }, 1279 Regions: []*MultiregionRegion{ 1280 { 1281 Name: "west", 1282 Count: 3, 1283 Datacenters: []string{"west-2"}, 1284 Meta: map[string]string{"region_code": "W"}, 1285 }, 1286 { 1287 Name: "east", 1288 Count: 2, 1289 Datacenters: []string{"east-1", "east-2"}, 1290 Meta: map[string]string{"region_code": "E"}, 1291 }, 1292 }, 1293 }, 1294 }, 1295 Expected: &JobDiff{ 1296 Type: DiffTypeEdited, 1297 Objects: []*ObjectDiff{ 1298 { 1299 Type: DiffTypeEdited, 1300 Name: "Multiregion", 1301 Objects: []*ObjectDiff{ 1302 { 1303 Type: DiffTypeEdited, 1304 Name: "Region", 1305 Fields: []*FieldDiff{ 1306 { 1307 Type: DiffTypeEdited, 1308 Name: "Count", 1309 Old: "1", 1310 New: "3", 1311 }, 1312 }, 1313 Objects: []*ObjectDiff{ 1314 { 1315 Type: DiffTypeEdited, 1316 Name: "Datacenters", 1317 Fields: []*FieldDiff{ 1318 { 1319 Type: DiffTypeAdded, 1320 Name: "Datacenters", 1321 Old: "", 1322 New: "west-2", 1323 }, 1324 { 1325 Type: DiffTypeDeleted, 1326 Name: "Datacenters", 1327 Old: "west-1", 1328 New: "", 1329 }, 1330 }, 1331 }, 1332 }, 1333 }, 1334 { 1335 Type: DiffTypeAdded, 1336 Name: "Region", 1337 Fields: []*FieldDiff{ 1338 { 1339 Type: DiffTypeAdded, 1340 Name: "Count", 1341 Old: "", 1342 New: "2", 1343 }, 1344 { 1345 Type: DiffTypeAdded, 1346 Name: "Meta[region_code]", 1347 Old: "", 1348 New: "E", 1349 }, 1350 { 1351 Type: DiffTypeAdded, 1352 Name: "Name", 1353 Old: "", 1354 New: "east", 1355 }, 1356 }, 1357 1358 Objects: []*ObjectDiff{ 1359 { 1360 Type: DiffTypeAdded, 1361 Name: "Datacenters", 1362 Fields: []*FieldDiff{ 1363 { 1364 Type: DiffTypeAdded, 1365 Name: "Datacenters", 1366 Old: "", 1367 New: "east-1", 1368 }, 1369 { 1370 Type: DiffTypeAdded, 1371 Name: "Datacenters", 1372 Old: "", 1373 New: "east-2", 1374 }, 1375 }, 1376 }, 1377 }, 1378 }, 1379 { 1380 Type: DiffTypeEdited, 1381 Name: "Strategy", 1382 Fields: []*FieldDiff{ 1383 { 1384 Type: DiffTypeEdited, 1385 Name: "MaxParallel", 1386 Old: "1", 1387 New: "2", 1388 }, 1389 }, 1390 }, 1391 }, 1392 }, 1393 }, 1394 }, 1395 }, 1396 { 1397 // VaultToken is filtered 1398 Old: &Job{ 1399 ID: "vault-job", 1400 VaultToken: "secret", 1401 }, 1402 New: &Job{ 1403 ID: "vault-job", 1404 VaultToken: "new-secret", 1405 }, 1406 Expected: &JobDiff{ 1407 Type: DiffTypeNone, 1408 ID: "vault-job", 1409 }, 1410 }, 1411 } 1412 1413 for i, c := range cases { 1414 actual, err := c.Old.Diff(c.New, c.Contextual) 1415 if c.Error && err == nil { 1416 t.Fatalf("case %d: expected errored", i+1) 1417 } else if err != nil { 1418 if !c.Error { 1419 t.Fatalf("case %d: errored %#v", i+1, err) 1420 } else { 1421 continue 1422 } 1423 } 1424 1425 if !reflect.DeepEqual(actual, c.Expected) { 1426 t.Fatalf("case %d: got:\n%#v\n want:\n%#v\n", 1427 i+1, actual, c.Expected) 1428 } 1429 } 1430 } 1431 1432 func TestTaskGroupDiff(t *testing.T) { 1433 ci.Parallel(t) 1434 1435 cases := []struct { 1436 TestCase string 1437 Old, New *TaskGroup 1438 Expected *TaskGroupDiff 1439 ExpErr bool 1440 Contextual bool 1441 }{ 1442 { 1443 TestCase: "Empty", 1444 Old: nil, 1445 New: nil, 1446 Expected: &TaskGroupDiff{ 1447 Type: DiffTypeNone, 1448 }, 1449 }, 1450 { 1451 TestCase: "Primitive only that has different names", 1452 Old: &TaskGroup{ 1453 Name: "foo", 1454 Count: 10, 1455 Meta: map[string]string{ 1456 "foo": "bar", 1457 }, 1458 }, 1459 New: &TaskGroup{ 1460 Name: "bar", 1461 Count: 10, 1462 Meta: map[string]string{ 1463 "foo": "bar", 1464 }, 1465 }, 1466 ExpErr: true, 1467 }, 1468 { 1469 TestCase: "Primitive only that is the same", 1470 Old: &TaskGroup{ 1471 Name: "foo", 1472 Count: 10, 1473 Meta: map[string]string{ 1474 "foo": "bar", 1475 }, 1476 }, 1477 New: &TaskGroup{ 1478 Name: "foo", 1479 Count: 10, 1480 Meta: map[string]string{ 1481 "foo": "bar", 1482 }, 1483 }, 1484 Expected: &TaskGroupDiff{ 1485 Type: DiffTypeNone, 1486 Name: "foo", 1487 }, 1488 }, 1489 { 1490 TestCase: "Primitive only that has diffs", 1491 Old: &TaskGroup{ 1492 Name: "foo", 1493 Count: 10, 1494 Meta: map[string]string{ 1495 "foo": "bar", 1496 }, 1497 }, 1498 New: &TaskGroup{ 1499 Name: "foo", 1500 Count: 100, 1501 Meta: map[string]string{ 1502 "foo": "baz", 1503 }, 1504 }, 1505 Expected: &TaskGroupDiff{ 1506 Type: DiffTypeEdited, 1507 Name: "foo", 1508 Fields: []*FieldDiff{ 1509 { 1510 Type: DiffTypeEdited, 1511 Name: "Count", 1512 Old: "10", 1513 New: "100", 1514 }, 1515 { 1516 Type: DiffTypeEdited, 1517 Name: "Meta[foo]", 1518 Old: "bar", 1519 New: "baz", 1520 }, 1521 }, 1522 }, 1523 }, 1524 { 1525 TestCase: "Map diff", 1526 Old: &TaskGroup{ 1527 Meta: map[string]string{ 1528 "foo": "foo", 1529 "bar": "bar", 1530 }, 1531 }, 1532 New: &TaskGroup{ 1533 Meta: map[string]string{ 1534 "bar": "bar", 1535 "baz": "baz", 1536 }, 1537 }, 1538 Expected: &TaskGroupDiff{ 1539 Type: DiffTypeEdited, 1540 Fields: []*FieldDiff{ 1541 { 1542 Type: DiffTypeAdded, 1543 Name: "Meta[baz]", 1544 Old: "", 1545 New: "baz", 1546 }, 1547 { 1548 Type: DiffTypeDeleted, 1549 Name: "Meta[foo]", 1550 Old: "foo", 1551 New: "", 1552 }, 1553 }, 1554 }, 1555 }, 1556 { 1557 TestCase: "Constraints edited", 1558 Old: &TaskGroup{ 1559 Constraints: []*Constraint{ 1560 { 1561 LTarget: "foo", 1562 RTarget: "foo", 1563 Operand: "foo", 1564 }, 1565 { 1566 LTarget: "bar", 1567 RTarget: "bar", 1568 Operand: "bar", 1569 }, 1570 }, 1571 }, 1572 New: &TaskGroup{ 1573 Constraints: []*Constraint{ 1574 { 1575 LTarget: "foo", 1576 RTarget: "foo", 1577 Operand: "foo", 1578 }, 1579 { 1580 LTarget: "baz", 1581 RTarget: "baz", 1582 Operand: "baz", 1583 }, 1584 }, 1585 }, 1586 Expected: &TaskGroupDiff{ 1587 Type: DiffTypeEdited, 1588 Objects: []*ObjectDiff{ 1589 { 1590 Type: DiffTypeAdded, 1591 Name: "Constraint", 1592 Fields: []*FieldDiff{ 1593 { 1594 Type: DiffTypeAdded, 1595 Name: "LTarget", 1596 Old: "", 1597 New: "baz", 1598 }, 1599 { 1600 Type: DiffTypeAdded, 1601 Name: "Operand", 1602 Old: "", 1603 New: "baz", 1604 }, 1605 { 1606 Type: DiffTypeAdded, 1607 Name: "RTarget", 1608 Old: "", 1609 New: "baz", 1610 }, 1611 }, 1612 }, 1613 { 1614 Type: DiffTypeDeleted, 1615 Name: "Constraint", 1616 Fields: []*FieldDiff{ 1617 { 1618 Type: DiffTypeDeleted, 1619 Name: "LTarget", 1620 Old: "bar", 1621 New: "", 1622 }, 1623 { 1624 Type: DiffTypeDeleted, 1625 Name: "Operand", 1626 Old: "bar", 1627 New: "", 1628 }, 1629 { 1630 Type: DiffTypeDeleted, 1631 Name: "RTarget", 1632 Old: "bar", 1633 New: "", 1634 }, 1635 }, 1636 }, 1637 }, 1638 }, 1639 }, 1640 { 1641 TestCase: "Affinities edited", 1642 Old: &TaskGroup{ 1643 Affinities: []*Affinity{ 1644 { 1645 LTarget: "foo", 1646 RTarget: "foo", 1647 Operand: "foo", 1648 Weight: 20, 1649 }, 1650 { 1651 LTarget: "bar", 1652 RTarget: "bar", 1653 Operand: "bar", 1654 Weight: 20, 1655 }, 1656 }, 1657 }, 1658 New: &TaskGroup{ 1659 Affinities: []*Affinity{ 1660 { 1661 LTarget: "foo", 1662 RTarget: "foo", 1663 Operand: "foo", 1664 Weight: 20, 1665 }, 1666 { 1667 LTarget: "baz", 1668 RTarget: "baz", 1669 Operand: "baz", 1670 Weight: 20, 1671 }, 1672 }, 1673 }, 1674 Expected: &TaskGroupDiff{ 1675 Type: DiffTypeEdited, 1676 Objects: []*ObjectDiff{ 1677 { 1678 Type: DiffTypeAdded, 1679 Name: "Affinity", 1680 Fields: []*FieldDiff{ 1681 { 1682 Type: DiffTypeAdded, 1683 Name: "LTarget", 1684 Old: "", 1685 New: "baz", 1686 }, 1687 { 1688 Type: DiffTypeAdded, 1689 Name: "Operand", 1690 Old: "", 1691 New: "baz", 1692 }, 1693 { 1694 Type: DiffTypeAdded, 1695 Name: "RTarget", 1696 Old: "", 1697 New: "baz", 1698 }, 1699 { 1700 Type: DiffTypeAdded, 1701 Name: "Weight", 1702 Old: "", 1703 New: "20", 1704 }, 1705 }, 1706 }, 1707 { 1708 Type: DiffTypeDeleted, 1709 Name: "Affinity", 1710 Fields: []*FieldDiff{ 1711 { 1712 Type: DiffTypeDeleted, 1713 Name: "LTarget", 1714 Old: "bar", 1715 New: "", 1716 }, 1717 { 1718 Type: DiffTypeDeleted, 1719 Name: "Operand", 1720 Old: "bar", 1721 New: "", 1722 }, 1723 { 1724 Type: DiffTypeDeleted, 1725 Name: "RTarget", 1726 Old: "bar", 1727 New: "", 1728 }, 1729 { 1730 Type: DiffTypeDeleted, 1731 Name: "Weight", 1732 Old: "20", 1733 New: "", 1734 }, 1735 }, 1736 }, 1737 }, 1738 }, 1739 }, 1740 { 1741 TestCase: "Consul added", 1742 Old: &TaskGroup{}, 1743 New: &TaskGroup{ 1744 Consul: &Consul{ 1745 Namespace: "team1", 1746 }, 1747 }, 1748 Expected: &TaskGroupDiff{ 1749 Type: DiffTypeEdited, 1750 Objects: []*ObjectDiff{ 1751 { 1752 Type: DiffTypeAdded, 1753 Name: "Consul", 1754 Fields: []*FieldDiff{ 1755 { 1756 Type: DiffTypeAdded, 1757 Name: "Namespace", 1758 Old: "", 1759 New: "team1", 1760 }, 1761 }, 1762 }, 1763 }, 1764 }, 1765 }, 1766 { 1767 TestCase: "Consul deleted", 1768 Old: &TaskGroup{ 1769 Consul: &Consul{ 1770 Namespace: "team1", 1771 }, 1772 }, 1773 New: &TaskGroup{}, 1774 Expected: &TaskGroupDiff{ 1775 Type: DiffTypeEdited, 1776 Objects: []*ObjectDiff{ 1777 { 1778 Type: DiffTypeDeleted, 1779 Name: "Consul", 1780 Fields: []*FieldDiff{ 1781 { 1782 Type: DiffTypeDeleted, 1783 Name: "Namespace", 1784 Old: "team1", 1785 New: "", 1786 }, 1787 }, 1788 }, 1789 }, 1790 }, 1791 }, 1792 { 1793 TestCase: "Consul updated", 1794 Old: &TaskGroup{ 1795 Consul: &Consul{ 1796 Namespace: "team1", 1797 }, 1798 }, 1799 New: &TaskGroup{ 1800 Consul: &Consul{ 1801 Namespace: "team2", 1802 }, 1803 }, 1804 Expected: &TaskGroupDiff{ 1805 Type: DiffTypeEdited, 1806 Objects: []*ObjectDiff{ 1807 { 1808 Type: DiffTypeEdited, 1809 Name: "Consul", 1810 Fields: []*FieldDiff{ 1811 { 1812 Type: DiffTypeEdited, 1813 Name: "Namespace", 1814 Old: "team1", 1815 New: "team2", 1816 }, 1817 }, 1818 }, 1819 }, 1820 }, 1821 }, 1822 { 1823 TestCase: "RestartPolicy added", 1824 Old: &TaskGroup{}, 1825 New: &TaskGroup{ 1826 RestartPolicy: &RestartPolicy{ 1827 Attempts: 1, 1828 Interval: 1 * time.Second, 1829 Delay: 1 * time.Second, 1830 Mode: "fail", 1831 }, 1832 }, 1833 Expected: &TaskGroupDiff{ 1834 Type: DiffTypeEdited, 1835 Objects: []*ObjectDiff{ 1836 { 1837 Type: DiffTypeAdded, 1838 Name: "RestartPolicy", 1839 Fields: []*FieldDiff{ 1840 { 1841 Type: DiffTypeAdded, 1842 Name: "Attempts", 1843 Old: "", 1844 New: "1", 1845 }, 1846 { 1847 Type: DiffTypeAdded, 1848 Name: "Delay", 1849 Old: "", 1850 New: "1000000000", 1851 }, 1852 { 1853 Type: DiffTypeAdded, 1854 Name: "Interval", 1855 Old: "", 1856 New: "1000000000", 1857 }, 1858 { 1859 Type: DiffTypeAdded, 1860 Name: "Mode", 1861 Old: "", 1862 New: "fail", 1863 }, 1864 }, 1865 }, 1866 }, 1867 }, 1868 }, 1869 { 1870 TestCase: "RestartPolicy deleted", 1871 Old: &TaskGroup{ 1872 RestartPolicy: &RestartPolicy{ 1873 Attempts: 1, 1874 Interval: 1 * time.Second, 1875 Delay: 1 * time.Second, 1876 Mode: "fail", 1877 }, 1878 }, 1879 New: &TaskGroup{}, 1880 Expected: &TaskGroupDiff{ 1881 Type: DiffTypeEdited, 1882 Objects: []*ObjectDiff{ 1883 { 1884 Type: DiffTypeDeleted, 1885 Name: "RestartPolicy", 1886 Fields: []*FieldDiff{ 1887 { 1888 Type: DiffTypeDeleted, 1889 Name: "Attempts", 1890 Old: "1", 1891 New: "", 1892 }, 1893 { 1894 Type: DiffTypeDeleted, 1895 Name: "Delay", 1896 Old: "1000000000", 1897 New: "", 1898 }, 1899 { 1900 Type: DiffTypeDeleted, 1901 Name: "Interval", 1902 Old: "1000000000", 1903 New: "", 1904 }, 1905 { 1906 Type: DiffTypeDeleted, 1907 Name: "Mode", 1908 Old: "fail", 1909 New: "", 1910 }, 1911 }, 1912 }, 1913 }, 1914 }, 1915 }, 1916 { 1917 TestCase: "RestartPolicy edited", 1918 Old: &TaskGroup{ 1919 RestartPolicy: &RestartPolicy{ 1920 Attempts: 1, 1921 Interval: 1 * time.Second, 1922 Delay: 1 * time.Second, 1923 Mode: "fail", 1924 }, 1925 }, 1926 New: &TaskGroup{ 1927 RestartPolicy: &RestartPolicy{ 1928 Attempts: 2, 1929 Interval: 2 * time.Second, 1930 Delay: 2 * time.Second, 1931 Mode: "delay", 1932 }, 1933 }, 1934 Expected: &TaskGroupDiff{ 1935 Type: DiffTypeEdited, 1936 Objects: []*ObjectDiff{ 1937 { 1938 Type: DiffTypeEdited, 1939 Name: "RestartPolicy", 1940 Fields: []*FieldDiff{ 1941 { 1942 Type: DiffTypeEdited, 1943 Name: "Attempts", 1944 Old: "1", 1945 New: "2", 1946 }, 1947 { 1948 Type: DiffTypeEdited, 1949 Name: "Delay", 1950 Old: "1000000000", 1951 New: "2000000000", 1952 }, 1953 { 1954 Type: DiffTypeEdited, 1955 Name: "Interval", 1956 Old: "1000000000", 1957 New: "2000000000", 1958 }, 1959 { 1960 Type: DiffTypeEdited, 1961 Name: "Mode", 1962 Old: "fail", 1963 New: "delay", 1964 }, 1965 }, 1966 }, 1967 }, 1968 }, 1969 }, 1970 { 1971 TestCase: "RestartPolicy edited with context", 1972 Contextual: true, 1973 Old: &TaskGroup{ 1974 RestartPolicy: &RestartPolicy{ 1975 Attempts: 1, 1976 Interval: 1 * time.Second, 1977 Delay: 1 * time.Second, 1978 Mode: "fail", 1979 }, 1980 }, 1981 New: &TaskGroup{ 1982 RestartPolicy: &RestartPolicy{ 1983 Attempts: 2, 1984 Interval: 2 * time.Second, 1985 Delay: 1 * time.Second, 1986 Mode: "fail", 1987 }, 1988 }, 1989 Expected: &TaskGroupDiff{ 1990 Type: DiffTypeEdited, 1991 Objects: []*ObjectDiff{ 1992 { 1993 Type: DiffTypeEdited, 1994 Name: "RestartPolicy", 1995 Fields: []*FieldDiff{ 1996 { 1997 Type: DiffTypeEdited, 1998 Name: "Attempts", 1999 Old: "1", 2000 New: "2", 2001 }, 2002 { 2003 Type: DiffTypeNone, 2004 Name: "Delay", 2005 Old: "1000000000", 2006 New: "1000000000", 2007 }, 2008 { 2009 Type: DiffTypeEdited, 2010 Name: "Interval", 2011 Old: "1000000000", 2012 New: "2000000000", 2013 }, 2014 { 2015 Type: DiffTypeNone, 2016 Name: "Mode", 2017 Old: "fail", 2018 New: "fail", 2019 }, 2020 }, 2021 }, 2022 }, 2023 }, 2024 }, 2025 { 2026 TestCase: "ReschedulePolicy added", 2027 Old: &TaskGroup{}, 2028 New: &TaskGroup{ 2029 ReschedulePolicy: &ReschedulePolicy{ 2030 Attempts: 1, 2031 Interval: 15 * time.Second, 2032 Delay: 5 * time.Second, 2033 MaxDelay: 20 * time.Second, 2034 DelayFunction: "exponential", 2035 Unlimited: false, 2036 }, 2037 }, 2038 Expected: &TaskGroupDiff{ 2039 Type: DiffTypeEdited, 2040 Objects: []*ObjectDiff{ 2041 { 2042 Type: DiffTypeAdded, 2043 Name: "ReschedulePolicy", 2044 Fields: []*FieldDiff{ 2045 { 2046 Type: DiffTypeAdded, 2047 Name: "Attempts", 2048 Old: "", 2049 New: "1", 2050 }, 2051 { 2052 Type: DiffTypeAdded, 2053 Name: "Delay", 2054 Old: "", 2055 New: "5000000000", 2056 }, 2057 { 2058 Type: DiffTypeAdded, 2059 Name: "DelayFunction", 2060 Old: "", 2061 New: "exponential", 2062 }, 2063 { 2064 Type: DiffTypeAdded, 2065 Name: "Interval", 2066 Old: "", 2067 New: "15000000000", 2068 }, 2069 { 2070 Type: DiffTypeAdded, 2071 Name: "MaxDelay", 2072 Old: "", 2073 New: "20000000000", 2074 }, 2075 { 2076 Type: DiffTypeAdded, 2077 Name: "Unlimited", 2078 Old: "", 2079 New: "false", 2080 }, 2081 }, 2082 }, 2083 }, 2084 }, 2085 }, 2086 { 2087 TestCase: "ReschedulePolicy deleted", 2088 Old: &TaskGroup{ 2089 ReschedulePolicy: &ReschedulePolicy{ 2090 Attempts: 1, 2091 Interval: 15 * time.Second, 2092 Delay: 5 * time.Second, 2093 MaxDelay: 20 * time.Second, 2094 DelayFunction: "exponential", 2095 Unlimited: false, 2096 }, 2097 }, 2098 New: &TaskGroup{}, 2099 Expected: &TaskGroupDiff{ 2100 Type: DiffTypeEdited, 2101 Objects: []*ObjectDiff{ 2102 { 2103 Type: DiffTypeDeleted, 2104 Name: "ReschedulePolicy", 2105 Fields: []*FieldDiff{ 2106 { 2107 Type: DiffTypeDeleted, 2108 Name: "Attempts", 2109 Old: "1", 2110 New: "", 2111 }, 2112 { 2113 Type: DiffTypeDeleted, 2114 Name: "Delay", 2115 Old: "5000000000", 2116 New: "", 2117 }, 2118 { 2119 Type: DiffTypeDeleted, 2120 Name: "DelayFunction", 2121 Old: "exponential", 2122 New: "", 2123 }, 2124 { 2125 Type: DiffTypeDeleted, 2126 Name: "Interval", 2127 Old: "15000000000", 2128 New: "", 2129 }, 2130 { 2131 Type: DiffTypeDeleted, 2132 Name: "MaxDelay", 2133 Old: "20000000000", 2134 New: "", 2135 }, 2136 { 2137 Type: DiffTypeDeleted, 2138 Name: "Unlimited", 2139 Old: "false", 2140 New: "", 2141 }, 2142 }, 2143 }, 2144 }, 2145 }, 2146 }, 2147 { 2148 TestCase: "ReschedulePolicy edited", 2149 Old: &TaskGroup{ 2150 ReschedulePolicy: &ReschedulePolicy{ 2151 Attempts: 1, 2152 Interval: 1 * time.Second, 2153 DelayFunction: "exponential", 2154 Delay: 20 * time.Second, 2155 MaxDelay: 1 * time.Minute, 2156 Unlimited: false, 2157 }, 2158 }, 2159 New: &TaskGroup{ 2160 ReschedulePolicy: &ReschedulePolicy{ 2161 Attempts: 2, 2162 Interval: 2 * time.Second, 2163 DelayFunction: "constant", 2164 Delay: 30 * time.Second, 2165 MaxDelay: 1 * time.Minute, 2166 Unlimited: true, 2167 }, 2168 }, 2169 Expected: &TaskGroupDiff{ 2170 Type: DiffTypeEdited, 2171 Objects: []*ObjectDiff{ 2172 { 2173 Type: DiffTypeEdited, 2174 Name: "ReschedulePolicy", 2175 Fields: []*FieldDiff{ 2176 { 2177 Type: DiffTypeEdited, 2178 Name: "Attempts", 2179 Old: "1", 2180 New: "2", 2181 }, 2182 { 2183 Type: DiffTypeEdited, 2184 Name: "Delay", 2185 Old: "20000000000", 2186 New: "30000000000", 2187 }, 2188 { 2189 Type: DiffTypeEdited, 2190 Name: "DelayFunction", 2191 Old: "exponential", 2192 New: "constant", 2193 }, 2194 { 2195 Type: DiffTypeEdited, 2196 Name: "Interval", 2197 Old: "1000000000", 2198 New: "2000000000", 2199 }, 2200 { 2201 Type: DiffTypeEdited, 2202 Name: "Unlimited", 2203 Old: "false", 2204 New: "true", 2205 }, 2206 }, 2207 }, 2208 }, 2209 }, 2210 }, 2211 { 2212 TestCase: "ReschedulePolicy edited with context", 2213 Contextual: true, 2214 Old: &TaskGroup{ 2215 ReschedulePolicy: &ReschedulePolicy{ 2216 Attempts: 1, 2217 Interval: 1 * time.Second, 2218 }, 2219 }, 2220 New: &TaskGroup{ 2221 ReschedulePolicy: &ReschedulePolicy{ 2222 Attempts: 1, 2223 Interval: 2 * time.Second, 2224 }, 2225 }, 2226 Expected: &TaskGroupDiff{ 2227 Type: DiffTypeEdited, 2228 Objects: []*ObjectDiff{ 2229 { 2230 Type: DiffTypeEdited, 2231 Name: "ReschedulePolicy", 2232 Fields: []*FieldDiff{ 2233 { 2234 Type: DiffTypeNone, 2235 Name: "Attempts", 2236 Old: "1", 2237 New: "1", 2238 }, 2239 { 2240 Type: DiffTypeNone, 2241 Name: "Delay", 2242 Old: "0", 2243 New: "0", 2244 }, 2245 { 2246 Type: DiffTypeNone, 2247 Name: "DelayFunction", 2248 Old: "", 2249 New: "", 2250 }, 2251 { 2252 Type: DiffTypeEdited, 2253 Name: "Interval", 2254 Old: "1000000000", 2255 New: "2000000000", 2256 }, 2257 { 2258 Type: DiffTypeNone, 2259 Name: "MaxDelay", 2260 Old: "0", 2261 New: "0", 2262 }, 2263 { 2264 Type: DiffTypeNone, 2265 Name: "Unlimited", 2266 Old: "false", 2267 New: "false", 2268 }, 2269 }, 2270 }, 2271 }, 2272 }, 2273 }, 2274 { 2275 TestCase: "Update strategy deleted", 2276 Old: &TaskGroup{ 2277 Update: &UpdateStrategy{ 2278 AutoRevert: true, 2279 }, 2280 }, 2281 New: &TaskGroup{}, 2282 Expected: &TaskGroupDiff{ 2283 Type: DiffTypeEdited, 2284 Objects: []*ObjectDiff{ 2285 { 2286 Type: DiffTypeDeleted, 2287 Name: "Update", 2288 Fields: []*FieldDiff{ 2289 { 2290 Type: DiffTypeDeleted, 2291 Name: "AutoPromote", 2292 Old: "false", 2293 New: "", 2294 }, 2295 { 2296 Type: DiffTypeDeleted, 2297 Name: "AutoRevert", 2298 Old: "true", 2299 New: "", 2300 }, 2301 { 2302 Type: DiffTypeDeleted, 2303 Name: "Canary", 2304 Old: "0", 2305 New: "", 2306 }, 2307 { 2308 Type: DiffTypeDeleted, 2309 Name: "HealthyDeadline", 2310 Old: "0", 2311 New: "", 2312 }, 2313 { 2314 Type: DiffTypeDeleted, 2315 Name: "MaxParallel", 2316 Old: "0", 2317 New: "", 2318 }, 2319 { 2320 Type: DiffTypeDeleted, 2321 Name: "MinHealthyTime", 2322 Old: "0", 2323 New: "", 2324 }, 2325 { 2326 Type: DiffTypeDeleted, 2327 Name: "ProgressDeadline", 2328 Old: "0", 2329 New: "", 2330 }, 2331 }, 2332 }, 2333 }, 2334 }, 2335 }, 2336 { 2337 TestCase: "Update strategy added", 2338 Old: &TaskGroup{}, 2339 New: &TaskGroup{ 2340 Update: &UpdateStrategy{ 2341 AutoRevert: true, 2342 }, 2343 }, 2344 Expected: &TaskGroupDiff{ 2345 Type: DiffTypeEdited, 2346 Objects: []*ObjectDiff{ 2347 { 2348 Type: DiffTypeAdded, 2349 Name: "Update", 2350 Fields: []*FieldDiff{ 2351 { 2352 Type: DiffTypeAdded, 2353 Name: "AutoPromote", 2354 Old: "", 2355 New: "false", 2356 }, 2357 { 2358 Type: DiffTypeAdded, 2359 Name: "AutoRevert", 2360 Old: "", 2361 New: "true", 2362 }, 2363 { 2364 Type: DiffTypeAdded, 2365 Name: "Canary", 2366 Old: "", 2367 New: "0", 2368 }, 2369 { 2370 Type: DiffTypeAdded, 2371 Name: "HealthyDeadline", 2372 Old: "", 2373 New: "0", 2374 }, 2375 { 2376 Type: DiffTypeAdded, 2377 Name: "MaxParallel", 2378 Old: "", 2379 New: "0", 2380 }, 2381 { 2382 Type: DiffTypeAdded, 2383 Name: "MinHealthyTime", 2384 Old: "", 2385 New: "0", 2386 }, 2387 { 2388 Type: DiffTypeAdded, 2389 Name: "ProgressDeadline", 2390 Old: "", 2391 New: "0", 2392 }, 2393 }, 2394 }, 2395 }, 2396 }, 2397 }, 2398 { 2399 TestCase: "Update strategy edited", 2400 Old: &TaskGroup{ 2401 Update: &UpdateStrategy{ 2402 MaxParallel: 5, 2403 HealthCheck: "foo", 2404 MinHealthyTime: 1 * time.Second, 2405 HealthyDeadline: 30 * time.Second, 2406 ProgressDeadline: 29 * time.Second, 2407 AutoRevert: true, 2408 AutoPromote: true, 2409 Canary: 2, 2410 }, 2411 }, 2412 New: &TaskGroup{ 2413 Update: &UpdateStrategy{ 2414 MaxParallel: 7, 2415 HealthCheck: "bar", 2416 MinHealthyTime: 2 * time.Second, 2417 HealthyDeadline: 31 * time.Second, 2418 ProgressDeadline: 32 * time.Second, 2419 AutoRevert: false, 2420 AutoPromote: false, 2421 Canary: 1, 2422 }, 2423 }, 2424 Expected: &TaskGroupDiff{ 2425 Type: DiffTypeEdited, 2426 Objects: []*ObjectDiff{ 2427 { 2428 Type: DiffTypeEdited, 2429 Name: "Update", 2430 Fields: []*FieldDiff{ 2431 { 2432 Type: DiffTypeEdited, 2433 Name: "AutoPromote", 2434 Old: "true", 2435 New: "false", 2436 }, 2437 { 2438 Type: DiffTypeEdited, 2439 Name: "AutoRevert", 2440 Old: "true", 2441 New: "false", 2442 }, 2443 { 2444 Type: DiffTypeEdited, 2445 Name: "Canary", 2446 Old: "2", 2447 New: "1", 2448 }, 2449 { 2450 Type: DiffTypeEdited, 2451 Name: "HealthCheck", 2452 Old: "foo", 2453 New: "bar", 2454 }, 2455 { 2456 Type: DiffTypeEdited, 2457 Name: "HealthyDeadline", 2458 Old: "30000000000", 2459 New: "31000000000", 2460 }, 2461 { 2462 Type: DiffTypeEdited, 2463 Name: "MaxParallel", 2464 Old: "5", 2465 New: "7", 2466 }, 2467 { 2468 Type: DiffTypeEdited, 2469 Name: "MinHealthyTime", 2470 Old: "1000000000", 2471 New: "2000000000", 2472 }, 2473 { 2474 Type: DiffTypeEdited, 2475 Name: "ProgressDeadline", 2476 Old: "29000000000", 2477 New: "32000000000", 2478 }, 2479 }, 2480 }, 2481 }, 2482 }, 2483 }, 2484 { 2485 TestCase: "Update strategy edited with context", 2486 Contextual: true, 2487 Old: &TaskGroup{ 2488 Update: &UpdateStrategy{ 2489 MaxParallel: 5, 2490 HealthCheck: "foo", 2491 MinHealthyTime: 1 * time.Second, 2492 HealthyDeadline: 30 * time.Second, 2493 ProgressDeadline: 30 * time.Second, 2494 AutoRevert: true, 2495 AutoPromote: true, 2496 Canary: 2, 2497 }, 2498 }, 2499 New: &TaskGroup{ 2500 Update: &UpdateStrategy{ 2501 MaxParallel: 7, 2502 HealthCheck: "foo", 2503 MinHealthyTime: 1 * time.Second, 2504 HealthyDeadline: 30 * time.Second, 2505 ProgressDeadline: 30 * time.Second, 2506 AutoRevert: true, 2507 AutoPromote: true, 2508 Canary: 2, 2509 }, 2510 }, 2511 Expected: &TaskGroupDiff{ 2512 Type: DiffTypeEdited, 2513 Objects: []*ObjectDiff{ 2514 { 2515 Type: DiffTypeEdited, 2516 Name: "Update", 2517 Fields: []*FieldDiff{ 2518 { 2519 Type: DiffTypeNone, 2520 Name: "AutoPromote", 2521 Old: "true", 2522 New: "true", 2523 }, 2524 { 2525 Type: DiffTypeNone, 2526 Name: "AutoRevert", 2527 Old: "true", 2528 New: "true", 2529 }, 2530 { 2531 Type: DiffTypeNone, 2532 Name: "Canary", 2533 Old: "2", 2534 New: "2", 2535 }, 2536 { 2537 Type: DiffTypeNone, 2538 Name: "HealthCheck", 2539 Old: "foo", 2540 New: "foo", 2541 }, 2542 { 2543 Type: DiffTypeNone, 2544 Name: "HealthyDeadline", 2545 Old: "30000000000", 2546 New: "30000000000", 2547 }, 2548 { 2549 Type: DiffTypeEdited, 2550 Name: "MaxParallel", 2551 Old: "5", 2552 New: "7", 2553 }, 2554 { 2555 Type: DiffTypeNone, 2556 Name: "MinHealthyTime", 2557 Old: "1000000000", 2558 New: "1000000000", 2559 }, 2560 { 2561 Type: DiffTypeNone, 2562 Name: "ProgressDeadline", 2563 Old: "30000000000", 2564 New: "30000000000", 2565 }, 2566 }, 2567 }, 2568 }, 2569 }, 2570 }, 2571 { 2572 TestCase: "EphemeralDisk added", 2573 Old: &TaskGroup{}, 2574 New: &TaskGroup{ 2575 EphemeralDisk: &EphemeralDisk{ 2576 Migrate: true, 2577 Sticky: true, 2578 SizeMB: 100, 2579 }, 2580 }, 2581 Expected: &TaskGroupDiff{ 2582 Type: DiffTypeEdited, 2583 Objects: []*ObjectDiff{ 2584 { 2585 Type: DiffTypeAdded, 2586 Name: "EphemeralDisk", 2587 Fields: []*FieldDiff{ 2588 { 2589 Type: DiffTypeAdded, 2590 Name: "Migrate", 2591 Old: "", 2592 New: "true", 2593 }, 2594 { 2595 Type: DiffTypeAdded, 2596 Name: "SizeMB", 2597 Old: "", 2598 New: "100", 2599 }, 2600 { 2601 Type: DiffTypeAdded, 2602 Name: "Sticky", 2603 Old: "", 2604 New: "true", 2605 }, 2606 }, 2607 }, 2608 }, 2609 }, 2610 }, 2611 { 2612 TestCase: "EphemeralDisk deleted", 2613 Old: &TaskGroup{ 2614 EphemeralDisk: &EphemeralDisk{ 2615 Migrate: true, 2616 Sticky: true, 2617 SizeMB: 100, 2618 }, 2619 }, 2620 New: &TaskGroup{}, 2621 Expected: &TaskGroupDiff{ 2622 Type: DiffTypeEdited, 2623 Objects: []*ObjectDiff{ 2624 { 2625 Type: DiffTypeDeleted, 2626 Name: "EphemeralDisk", 2627 Fields: []*FieldDiff{ 2628 { 2629 Type: DiffTypeDeleted, 2630 Name: "Migrate", 2631 Old: "true", 2632 New: "", 2633 }, 2634 { 2635 Type: DiffTypeDeleted, 2636 Name: "SizeMB", 2637 Old: "100", 2638 New: "", 2639 }, 2640 { 2641 Type: DiffTypeDeleted, 2642 Name: "Sticky", 2643 Old: "true", 2644 New: "", 2645 }, 2646 }, 2647 }, 2648 }, 2649 }, 2650 }, 2651 { 2652 TestCase: "EphemeralDisk edited", 2653 Old: &TaskGroup{ 2654 EphemeralDisk: &EphemeralDisk{ 2655 Migrate: true, 2656 Sticky: true, 2657 SizeMB: 150, 2658 }, 2659 }, 2660 New: &TaskGroup{ 2661 EphemeralDisk: &EphemeralDisk{ 2662 Migrate: false, 2663 Sticky: false, 2664 SizeMB: 90, 2665 }, 2666 }, 2667 Expected: &TaskGroupDiff{ 2668 Type: DiffTypeEdited, 2669 Objects: []*ObjectDiff{ 2670 { 2671 Type: DiffTypeEdited, 2672 Name: "EphemeralDisk", 2673 Fields: []*FieldDiff{ 2674 { 2675 Type: DiffTypeEdited, 2676 Name: "Migrate", 2677 Old: "true", 2678 New: "false", 2679 }, 2680 { 2681 Type: DiffTypeEdited, 2682 Name: "SizeMB", 2683 Old: "150", 2684 New: "90", 2685 }, 2686 2687 { 2688 Type: DiffTypeEdited, 2689 Name: "Sticky", 2690 Old: "true", 2691 New: "false", 2692 }, 2693 }, 2694 }, 2695 }, 2696 }, 2697 }, 2698 { 2699 TestCase: "EphemeralDisk edited with context", 2700 Contextual: true, 2701 Old: &TaskGroup{ 2702 EphemeralDisk: &EphemeralDisk{ 2703 Migrate: false, 2704 Sticky: false, 2705 SizeMB: 100, 2706 }, 2707 }, 2708 New: &TaskGroup{ 2709 EphemeralDisk: &EphemeralDisk{ 2710 Migrate: true, 2711 Sticky: true, 2712 SizeMB: 90, 2713 }, 2714 }, 2715 Expected: &TaskGroupDiff{ 2716 Type: DiffTypeEdited, 2717 Objects: []*ObjectDiff{ 2718 { 2719 Type: DiffTypeEdited, 2720 Name: "EphemeralDisk", 2721 Fields: []*FieldDiff{ 2722 { 2723 Type: DiffTypeEdited, 2724 Name: "Migrate", 2725 Old: "false", 2726 New: "true", 2727 }, 2728 { 2729 Type: DiffTypeEdited, 2730 Name: "SizeMB", 2731 Old: "100", 2732 New: "90", 2733 }, 2734 { 2735 Type: DiffTypeEdited, 2736 Name: "Sticky", 2737 Old: "false", 2738 New: "true", 2739 }, 2740 }, 2741 }, 2742 }, 2743 }, 2744 }, 2745 { 2746 TestCase: "TaskGroup Services edited", 2747 Contextual: true, 2748 Old: &TaskGroup{ 2749 Services: []*Service{ 2750 { 2751 Name: "foo", 2752 Namespace: "team1", 2753 TaskName: "task1", 2754 EnableTagOverride: false, 2755 Checks: []*ServiceCheck{ 2756 { 2757 Name: "foo", 2758 Type: "http", 2759 Command: "foo", 2760 Args: []string{"foo"}, 2761 Path: "foo", 2762 Protocol: "http", 2763 Method: "POST", 2764 Body: "{\"key\": \"value\"}", 2765 Expose: true, 2766 Interval: 1 * time.Second, 2767 Timeout: 1 * time.Second, 2768 SuccessBeforePassing: 3, 2769 FailuresBeforeCritical: 4, 2770 }, 2771 }, 2772 Connect: &ConsulConnect{ 2773 Native: false, 2774 SidecarTask: &SidecarTask{ 2775 Name: "sidecar", 2776 Driver: "docker", 2777 Env: map[string]string{ 2778 "FOO": "BAR", 2779 }, 2780 Config: map[string]interface{}{ 2781 "foo": "baz", 2782 }, 2783 }, 2784 Gateway: &ConsulGateway{ 2785 Proxy: &ConsulGatewayProxy{ 2786 ConnectTimeout: pointer.Of(1 * time.Second), 2787 EnvoyGatewayBindTaggedAddresses: false, 2788 EnvoyGatewayBindAddresses: map[string]*ConsulGatewayBindAddress{ 2789 "service1": { 2790 Address: "10.0.0.1", 2791 Port: 2001, 2792 }, 2793 }, 2794 EnvoyDNSDiscoveryType: "STRICT_DNS", 2795 EnvoyGatewayNoDefaultBind: false, 2796 Config: map[string]interface{}{ 2797 "foo": 1, 2798 }, 2799 }, 2800 Ingress: &ConsulIngressConfigEntry{ 2801 TLS: &ConsulGatewayTLSConfig{ 2802 Enabled: false, 2803 }, 2804 Listeners: []*ConsulIngressListener{{ 2805 Port: 3001, 2806 Protocol: "tcp", 2807 Services: []*ConsulIngressService{{ 2808 Name: "listener1", 2809 }}, 2810 }}, 2811 }, 2812 Terminating: &ConsulTerminatingConfigEntry{ 2813 Services: []*ConsulLinkedService{{ 2814 Name: "linked1", 2815 CAFile: "ca1.pem", 2816 CertFile: "cert1.pem", 2817 KeyFile: "key1.pem", 2818 SNI: "linked1.consul", 2819 }}, 2820 }, 2821 Mesh: &ConsulMeshConfigEntry{ 2822 // nothing 2823 }, 2824 }, 2825 }, 2826 }, 2827 }, 2828 }, 2829 2830 New: &TaskGroup{ 2831 Services: []*Service{ 2832 { 2833 Name: "foo", 2834 Namespace: "team1", 2835 TaskName: "task2", 2836 EnableTagOverride: true, 2837 Checks: []*ServiceCheck{ 2838 { 2839 Name: "foo", 2840 Type: "tcp", 2841 Command: "bar", 2842 Path: "bar", 2843 Protocol: "tcp", 2844 Expose: false, 2845 Interval: 2 * time.Second, 2846 Timeout: 2 * time.Second, 2847 Header: map[string][]string{ 2848 "Foo": {"baz"}, 2849 }, 2850 SuccessBeforePassing: 5, 2851 FailuresBeforeCritical: 6, 2852 }, 2853 }, 2854 Connect: &ConsulConnect{ 2855 Native: true, 2856 SidecarService: &ConsulSidecarService{ 2857 Port: "http", 2858 Proxy: &ConsulProxy{ 2859 LocalServiceAddress: "127.0.0.1", 2860 LocalServicePort: 8080, 2861 Upstreams: []ConsulUpstream{ 2862 { 2863 DestinationName: "foo", 2864 DestinationNamespace: "ns2", 2865 LocalBindPort: 8000, 2866 Datacenter: "dc2", 2867 LocalBindAddress: "127.0.0.2", 2868 MeshGateway: ConsulMeshGateway{ 2869 Mode: "remote", 2870 }, 2871 }, 2872 }, 2873 Config: map[string]interface{}{ 2874 "foo": "qux", 2875 }, 2876 }, 2877 }, 2878 Gateway: &ConsulGateway{ 2879 Proxy: &ConsulGatewayProxy{ 2880 ConnectTimeout: pointer.Of(2 * time.Second), 2881 EnvoyGatewayBindTaggedAddresses: true, 2882 EnvoyGatewayBindAddresses: map[string]*ConsulGatewayBindAddress{ 2883 "service1": { 2884 Address: "10.0.0.2", 2885 Port: 2002, 2886 }, 2887 }, 2888 EnvoyDNSDiscoveryType: "LOGICAL_DNS", 2889 EnvoyGatewayNoDefaultBind: true, 2890 Config: map[string]interface{}{ 2891 "foo": 2, 2892 }, 2893 }, 2894 Ingress: &ConsulIngressConfigEntry{ 2895 TLS: &ConsulGatewayTLSConfig{ 2896 Enabled: true, 2897 }, 2898 Listeners: []*ConsulIngressListener{{ 2899 Port: 3002, 2900 Protocol: "http", 2901 Services: []*ConsulIngressService{{ 2902 Name: "listener2", 2903 Hosts: []string{"127.0.0.1", "127.0.0.1:3002"}, 2904 }}, 2905 }}, 2906 }, 2907 Terminating: &ConsulTerminatingConfigEntry{ 2908 Services: []*ConsulLinkedService{{ 2909 Name: "linked2", 2910 CAFile: "ca2.pem", 2911 CertFile: "cert2.pem", 2912 KeyFile: "key2.pem", 2913 SNI: "linked2.consul", 2914 }}, 2915 }, 2916 Mesh: &ConsulMeshConfigEntry{ 2917 // nothing 2918 }, 2919 }, 2920 }, 2921 }, 2922 }, 2923 }, 2924 2925 Expected: &TaskGroupDiff{ 2926 Type: DiffTypeEdited, 2927 Objects: []*ObjectDiff{ 2928 { 2929 Type: DiffTypeEdited, 2930 Name: "Service", 2931 Fields: []*FieldDiff{ 2932 { 2933 Type: DiffTypeNone, 2934 Name: "Address", 2935 Old: "", 2936 New: "", 2937 }, 2938 { 2939 Type: DiffTypeNone, 2940 Name: "AddressMode", 2941 Old: "", 2942 New: "", 2943 }, 2944 { 2945 Type: DiffTypeEdited, 2946 Name: "EnableTagOverride", 2947 Old: "false", 2948 New: "true", 2949 }, 2950 { 2951 Type: DiffTypeNone, 2952 Name: "Name", 2953 Old: "foo", 2954 New: "foo", 2955 }, 2956 { 2957 Type: DiffTypeNone, 2958 Name: "Namespace", 2959 Old: "team1", 2960 New: "team1", 2961 }, 2962 { 2963 Type: DiffTypeNone, 2964 Name: "OnUpdate", 2965 Old: "", 2966 New: "", 2967 }, 2968 { 2969 Type: DiffTypeNone, 2970 Name: "PortLabel", 2971 Old: "", 2972 New: "", 2973 }, 2974 { 2975 Type: DiffTypeNone, 2976 Name: "Provider", 2977 Old: "", 2978 New: "", 2979 }, 2980 { 2981 Type: DiffTypeEdited, 2982 Name: "TaskName", 2983 Old: "task1", 2984 New: "task2", 2985 }, 2986 }, 2987 Objects: []*ObjectDiff{ 2988 { 2989 Type: DiffTypeEdited, 2990 Name: "Check", 2991 Fields: []*FieldDiff{ 2992 { 2993 Type: DiffTypeNone, 2994 Name: "AddressMode", 2995 Old: "", 2996 New: "", 2997 }, 2998 { 2999 Type: DiffTypeDeleted, 3000 Name: "Body", 3001 Old: "{\"key\": \"value\"}", 3002 New: "", 3003 }, 3004 { 3005 Type: DiffTypeEdited, 3006 Name: "Command", 3007 Old: "foo", 3008 New: "bar", 3009 }, 3010 { 3011 Type: DiffTypeEdited, 3012 Name: "Expose", 3013 Old: "true", 3014 New: "false", 3015 }, 3016 { 3017 Type: DiffTypeEdited, 3018 Name: "FailuresBeforeCritical", 3019 Old: "4", 3020 New: "6", 3021 }, 3022 { 3023 Type: DiffTypeNone, 3024 Name: "GRPCService", 3025 Old: "", 3026 New: "", 3027 }, 3028 { 3029 Type: DiffTypeNone, 3030 Name: "GRPCUseTLS", 3031 Old: "false", 3032 New: "false", 3033 }, 3034 { 3035 Type: DiffTypeNone, 3036 Name: "InitialStatus", 3037 Old: "", 3038 New: "", 3039 }, 3040 { 3041 Type: DiffTypeEdited, 3042 Name: "Interval", 3043 Old: "1000000000", 3044 New: "2000000000", 3045 }, 3046 { 3047 Type: DiffTypeDeleted, 3048 Name: "Method", 3049 Old: "POST", 3050 New: "", 3051 }, 3052 { 3053 Type: DiffTypeNone, 3054 Name: "Name", 3055 Old: "foo", 3056 New: "foo", 3057 }, 3058 { 3059 Type: DiffTypeNone, 3060 Name: "OnUpdate", 3061 Old: "", 3062 New: "", 3063 }, 3064 { 3065 Type: DiffTypeEdited, 3066 Name: "Path", 3067 Old: "foo", 3068 New: "bar", 3069 }, 3070 { 3071 Type: DiffTypeNone, 3072 Name: "PortLabel", 3073 Old: "", 3074 New: "", 3075 }, 3076 { 3077 Type: DiffTypeEdited, 3078 Name: "Protocol", 3079 Old: "http", 3080 New: "tcp", 3081 }, 3082 { 3083 Type: DiffTypeEdited, 3084 Name: "SuccessBeforePassing", 3085 Old: "3", 3086 New: "5", 3087 }, 3088 { 3089 Type: DiffTypeNone, 3090 Name: "TLSServerName", 3091 Old: "", 3092 New: "", 3093 }, 3094 { 3095 Type: DiffTypeNone, 3096 Name: "TLSSkipVerify", 3097 Old: "false", 3098 New: "false", 3099 }, 3100 { 3101 Type: DiffTypeNone, 3102 Name: "TaskName", 3103 Old: "", 3104 New: "", 3105 }, 3106 { 3107 Type: DiffTypeEdited, 3108 Name: "Timeout", 3109 Old: "1000000000", 3110 New: "2000000000", 3111 }, 3112 { 3113 Type: DiffTypeEdited, 3114 Name: "Type", 3115 Old: "http", 3116 New: "tcp", 3117 }, 3118 }, 3119 Objects: []*ObjectDiff{ 3120 { 3121 Type: DiffTypeAdded, 3122 Name: "Header", 3123 Fields: []*FieldDiff{ 3124 { 3125 Type: DiffTypeAdded, 3126 Name: "Foo[0]", 3127 Old: "", 3128 New: "baz", 3129 }, 3130 }, 3131 }, 3132 }, 3133 }, 3134 { 3135 Type: DiffTypeEdited, 3136 Name: "ConsulConnect", 3137 Fields: []*FieldDiff{ 3138 { 3139 Type: DiffTypeEdited, 3140 Name: "Native", 3141 Old: "false", 3142 New: "true", 3143 }, 3144 }, 3145 Objects: []*ObjectDiff{ 3146 3147 { 3148 Type: DiffTypeAdded, 3149 Name: "SidecarService", 3150 Fields: []*FieldDiff{ 3151 { 3152 Type: DiffTypeAdded, 3153 Name: "DisableDefaultTCPCheck", 3154 Old: "", 3155 New: "false", 3156 }, 3157 { 3158 Type: DiffTypeAdded, 3159 Name: "Port", 3160 Old: "", 3161 New: "http", 3162 }, 3163 }, 3164 Objects: []*ObjectDiff{ 3165 { 3166 Type: DiffTypeAdded, 3167 Name: "ConsulProxy", 3168 Fields: []*FieldDiff{ 3169 { 3170 Type: DiffTypeAdded, 3171 Name: "LocalServiceAddress", 3172 Old: "", 3173 New: "127.0.0.1", 3174 }, { 3175 Type: DiffTypeAdded, 3176 Name: "LocalServicePort", 3177 Old: "", 3178 New: "8080", 3179 }, 3180 }, 3181 Objects: []*ObjectDiff{ 3182 { 3183 Type: DiffTypeAdded, 3184 Name: "ConsulUpstreams", 3185 Fields: []*FieldDiff{ 3186 { 3187 Type: DiffTypeAdded, 3188 Name: "Datacenter", 3189 Old: "", 3190 New: "dc2", 3191 }, 3192 { 3193 Type: DiffTypeAdded, 3194 Name: "DestinationName", 3195 Old: "", 3196 New: "foo", 3197 }, 3198 { 3199 Type: DiffTypeAdded, 3200 Name: "DestinationNamespace", 3201 Old: "", 3202 New: "ns2", 3203 }, 3204 { 3205 Type: DiffTypeAdded, 3206 Name: "LocalBindAddress", 3207 Old: "", 3208 New: "127.0.0.2", 3209 }, 3210 { 3211 Type: DiffTypeAdded, 3212 Name: "LocalBindPort", 3213 Old: "", 3214 New: "8000", 3215 }, 3216 }, 3217 Objects: []*ObjectDiff{ 3218 { 3219 Type: DiffTypeAdded, 3220 Name: "MeshGateway", 3221 Fields: []*FieldDiff{ 3222 { 3223 Type: DiffTypeAdded, 3224 Name: "Mode", 3225 Old: "", 3226 New: "remote", 3227 }, 3228 }, 3229 }, 3230 }, 3231 }, 3232 { 3233 Type: DiffTypeAdded, 3234 Name: "Config", 3235 Fields: []*FieldDiff{ 3236 { 3237 Type: DiffTypeAdded, 3238 Name: "foo", 3239 Old: "", 3240 New: "qux", 3241 }, 3242 }, 3243 }, 3244 }, 3245 }, 3246 }, 3247 }, 3248 3249 { 3250 Type: DiffTypeDeleted, 3251 Name: "SidecarTask", 3252 Fields: []*FieldDiff{ 3253 { 3254 Type: DiffTypeDeleted, 3255 Name: "Driver", 3256 Old: "docker", 3257 New: "", 3258 }, 3259 { 3260 Type: DiffTypeDeleted, 3261 Name: "Env[FOO]", 3262 Old: "BAR", 3263 New: "", 3264 }, 3265 { 3266 Type: DiffTypeDeleted, 3267 Name: "Name", 3268 Old: "sidecar", 3269 New: "", 3270 }, 3271 }, 3272 Objects: []*ObjectDiff{ 3273 { 3274 Type: DiffTypeDeleted, 3275 Name: "Config", 3276 Fields: []*FieldDiff{ 3277 { 3278 Type: DiffTypeDeleted, 3279 Name: "foo", 3280 Old: "baz", 3281 New: "", 3282 }, 3283 }, 3284 }, 3285 }, 3286 }, 3287 { 3288 Type: DiffTypeEdited, 3289 Name: "Gateway", 3290 Objects: []*ObjectDiff{ 3291 { 3292 Type: DiffTypeEdited, 3293 Name: "Proxy", 3294 Fields: []*FieldDiff{ 3295 { 3296 Type: DiffTypeEdited, 3297 Name: "ConnectTimeout", 3298 Old: "1s", 3299 New: "2s", 3300 }, 3301 { 3302 Type: DiffTypeEdited, 3303 Name: "EnvoyDNSDiscoveryType", 3304 Old: "STRICT_DNS", 3305 New: "LOGICAL_DNS", 3306 }, 3307 { 3308 Type: DiffTypeEdited, 3309 Name: "EnvoyGatewayBindTaggedAddresses", 3310 Old: "false", 3311 New: "true", 3312 }, 3313 { 3314 Type: DiffTypeEdited, 3315 Name: "EnvoyGatewayNoDefaultBind", 3316 Old: "false", 3317 New: "true", 3318 }, 3319 }, 3320 Objects: []*ObjectDiff{ 3321 { 3322 Type: DiffTypeEdited, 3323 Name: "EnvoyGatewayBindAddresses", 3324 Fields: []*FieldDiff{ 3325 { 3326 Type: DiffTypeEdited, 3327 Name: "service1", 3328 Old: "10.0.0.1:2001", 3329 New: "10.0.0.2:2002", 3330 }, 3331 }, 3332 }, 3333 { 3334 Type: DiffTypeEdited, 3335 Name: "Config", 3336 Fields: []*FieldDiff{ 3337 { 3338 Type: DiffTypeEdited, 3339 Name: "foo", 3340 Old: "1", 3341 New: "2", 3342 }, 3343 }, 3344 }, 3345 }, 3346 }, 3347 { 3348 Type: DiffTypeEdited, 3349 Name: "Ingress", 3350 Objects: []*ObjectDiff{ 3351 { 3352 Type: DiffTypeEdited, 3353 Name: "TLS", 3354 Fields: []*FieldDiff{ 3355 { 3356 Type: DiffTypeEdited, 3357 Name: "Enabled", 3358 Old: "false", 3359 New: "true", 3360 }, 3361 { 3362 Type: DiffTypeNone, 3363 Name: "TLSMaxVersion", 3364 Old: "", 3365 New: "", 3366 }, 3367 { 3368 Type: DiffTypeNone, 3369 Name: "TLSMinVersion", 3370 Old: "", 3371 New: "", 3372 }, 3373 }, 3374 }, 3375 { 3376 Type: DiffTypeAdded, 3377 Name: "Listener", 3378 Fields: []*FieldDiff{ 3379 { 3380 Type: DiffTypeAdded, 3381 Name: "Port", 3382 Old: "", 3383 New: "3002", 3384 }, 3385 { 3386 Type: DiffTypeAdded, 3387 Name: "Protocol", 3388 Old: "", 3389 New: "http", 3390 }, 3391 }, 3392 Objects: []*ObjectDiff{ 3393 { 3394 Type: DiffTypeAdded, 3395 Name: "ConsulIngressService", 3396 Fields: []*FieldDiff{ 3397 { 3398 Type: DiffTypeAdded, 3399 Name: "Name", 3400 Old: "", 3401 New: "listener2", 3402 }, 3403 }, 3404 Objects: []*ObjectDiff{ 3405 { 3406 Type: DiffTypeAdded, 3407 Name: "Hosts", 3408 Fields: []*FieldDiff{ 3409 { 3410 Type: DiffTypeAdded, 3411 Name: "Hosts", 3412 Old: "", 3413 New: "127.0.0.1", 3414 }, 3415 { 3416 Type: DiffTypeAdded, 3417 Name: "Hosts", 3418 Old: "", 3419 New: "127.0.0.1:3002", 3420 }, 3421 }, 3422 }, 3423 }, 3424 }, 3425 }, 3426 }, 3427 { 3428 Type: DiffTypeDeleted, 3429 Name: "Listener", 3430 Fields: []*FieldDiff{ 3431 { 3432 Type: DiffTypeDeleted, 3433 Name: "Port", 3434 Old: "3001", 3435 New: "", 3436 }, 3437 { 3438 Type: DiffTypeDeleted, 3439 Name: "Protocol", 3440 Old: "tcp", 3441 New: "", 3442 }, 3443 }, 3444 Objects: []*ObjectDiff{ 3445 { 3446 Type: DiffTypeDeleted, 3447 Name: "ConsulIngressService", 3448 Fields: []*FieldDiff{ 3449 { 3450 Type: DiffTypeDeleted, 3451 Name: "Name", 3452 Old: "listener1", 3453 New: "", 3454 }, 3455 }, 3456 }, 3457 }, 3458 }, 3459 }, 3460 }, 3461 { 3462 Type: DiffTypeEdited, 3463 Name: "Terminating", 3464 Objects: []*ObjectDiff{ 3465 { 3466 Type: DiffTypeAdded, 3467 Name: "Service", 3468 Fields: []*FieldDiff{ 3469 { 3470 Type: DiffTypeAdded, 3471 Name: "CAFile", 3472 Old: "", 3473 New: "ca2.pem", 3474 }, 3475 { 3476 Type: DiffTypeAdded, 3477 Name: "CertFile", 3478 Old: "", 3479 New: "cert2.pem", 3480 }, 3481 { 3482 Type: DiffTypeAdded, 3483 Name: "KeyFile", 3484 Old: "", 3485 New: "key2.pem", 3486 }, 3487 { 3488 Type: DiffTypeAdded, 3489 Name: "Name", 3490 Old: "", 3491 New: "linked2", 3492 }, 3493 { 3494 Type: DiffTypeAdded, 3495 Name: "SNI", 3496 Old: "", 3497 New: "linked2.consul", 3498 }, 3499 }, 3500 }, 3501 { 3502 Type: DiffTypeDeleted, 3503 Name: "Service", 3504 Fields: []*FieldDiff{ 3505 { 3506 Type: DiffTypeDeleted, 3507 Name: "CAFile", 3508 Old: "ca1.pem", 3509 New: "", 3510 }, 3511 { 3512 Type: DiffTypeDeleted, 3513 Name: "CertFile", 3514 Old: "cert1.pem", 3515 New: "", 3516 }, 3517 { 3518 Type: DiffTypeDeleted, 3519 Name: "KeyFile", 3520 Old: "key1.pem", 3521 New: "", 3522 }, 3523 { 3524 Type: DiffTypeDeleted, 3525 Name: "Name", 3526 Old: "linked1", 3527 New: "", 3528 }, 3529 { 3530 Type: DiffTypeDeleted, 3531 Name: "SNI", 3532 Old: "linked1.consul", 3533 New: "", 3534 }, 3535 }, 3536 }, 3537 }, 3538 }, 3539 }, 3540 }, 3541 }, 3542 }, 3543 }, 3544 }, 3545 }, 3546 }, 3547 }, 3548 { 3549 TestCase: "TaskGroup Networks edited", 3550 Contextual: true, 3551 Old: &TaskGroup{ 3552 Networks: Networks{ 3553 { 3554 Device: "foo", 3555 CIDR: "foo", 3556 IP: "foo", 3557 MBits: 100, 3558 Hostname: "foo", 3559 ReservedPorts: []Port{ 3560 { 3561 Label: "foo", 3562 Value: 80, 3563 }, 3564 }, 3565 }, 3566 }, 3567 }, 3568 New: &TaskGroup{ 3569 Networks: Networks{ 3570 { 3571 Device: "bar", 3572 CIDR: "bar", 3573 IP: "bar", 3574 MBits: 200, 3575 Hostname: "bar", 3576 DynamicPorts: []Port{ 3577 { 3578 Label: "bar", 3579 To: 8081, 3580 HostNetwork: "public", 3581 }, 3582 }, 3583 DNS: &DNSConfig{ 3584 Servers: []string{"1.1.1.1"}, 3585 }, 3586 }, 3587 }, 3588 }, 3589 Expected: &TaskGroupDiff{ 3590 Type: DiffTypeEdited, 3591 Objects: []*ObjectDiff{ 3592 { 3593 Type: DiffTypeAdded, 3594 Name: "Network", 3595 Fields: []*FieldDiff{ 3596 { 3597 Type: DiffTypeAdded, 3598 Name: "Hostname", 3599 Old: "", 3600 New: "bar", 3601 }, 3602 { 3603 Type: DiffTypeAdded, 3604 Name: "MBits", 3605 Old: "", 3606 New: "200", 3607 }, 3608 { 3609 Type: DiffTypeNone, 3610 Name: "Mode", 3611 Old: "", 3612 New: "", 3613 }, 3614 }, 3615 Objects: []*ObjectDiff{ 3616 { 3617 Type: DiffTypeAdded, 3618 Name: "Dynamic Port", 3619 Fields: []*FieldDiff{ 3620 { 3621 Type: DiffTypeAdded, 3622 Name: "HostNetwork", 3623 Old: "", 3624 New: "public", 3625 }, 3626 { 3627 Type: DiffTypeAdded, 3628 Name: "Label", 3629 Old: "", 3630 New: "bar", 3631 }, 3632 { 3633 Type: DiffTypeAdded, 3634 Name: "To", 3635 Old: "", 3636 New: "8081", 3637 }, 3638 }, 3639 }, 3640 { 3641 Type: DiffTypeAdded, 3642 Name: "DNS", 3643 Fields: []*FieldDiff{ 3644 { 3645 Type: DiffTypeAdded, 3646 Name: "Servers", 3647 Old: "", 3648 New: "1.1.1.1", 3649 }, 3650 }, 3651 }, 3652 }, 3653 }, 3654 { 3655 Type: DiffTypeDeleted, 3656 Name: "Network", 3657 Fields: []*FieldDiff{ 3658 { 3659 Type: DiffTypeDeleted, 3660 Name: "Hostname", 3661 Old: "foo", 3662 New: "", 3663 }, 3664 { 3665 Type: DiffTypeDeleted, 3666 Name: "MBits", 3667 Old: "100", 3668 New: "", 3669 }, 3670 { 3671 Type: DiffTypeNone, 3672 Name: "Mode", 3673 Old: "", 3674 New: "", 3675 }, 3676 }, 3677 Objects: []*ObjectDiff{ 3678 { 3679 Type: DiffTypeDeleted, 3680 Name: "Static Port", 3681 Fields: []*FieldDiff{ 3682 { 3683 Type: DiffTypeNone, 3684 Name: "HostNetwork", 3685 Old: "", 3686 New: "", 3687 }, 3688 { 3689 Type: DiffTypeDeleted, 3690 Name: "Label", 3691 Old: "foo", 3692 New: "", 3693 }, 3694 { 3695 Type: DiffTypeDeleted, 3696 Name: "To", 3697 Old: "0", 3698 New: "", 3699 }, 3700 { 3701 Type: DiffTypeDeleted, 3702 Name: "Value", 3703 Old: "80", 3704 New: "", 3705 }, 3706 }, 3707 }, 3708 }, 3709 }, 3710 }, 3711 }, 3712 }, 3713 { 3714 TestCase: "Tasks edited", 3715 Old: &TaskGroup{ 3716 Tasks: []*Task{ 3717 { 3718 Name: "foo", 3719 Driver: "docker", 3720 }, 3721 { 3722 Name: "bar", 3723 Driver: "docker", 3724 }, 3725 { 3726 Name: "baz", 3727 ShutdownDelay: 1 * time.Second, 3728 }, 3729 }, 3730 }, 3731 New: &TaskGroup{ 3732 Tasks: []*Task{ 3733 { 3734 Name: "bar", 3735 Driver: "docker", 3736 }, 3737 { 3738 Name: "bam", 3739 Driver: "docker", 3740 }, 3741 { 3742 Name: "baz", 3743 ShutdownDelay: 2 * time.Second, 3744 }, 3745 }, 3746 }, 3747 Expected: &TaskGroupDiff{ 3748 Type: DiffTypeEdited, 3749 Tasks: []*TaskDiff{ 3750 { 3751 Type: DiffTypeAdded, 3752 Name: "bam", 3753 Fields: []*FieldDiff{ 3754 { 3755 Type: DiffTypeAdded, 3756 Name: "Driver", 3757 Old: "", 3758 New: "docker", 3759 }, 3760 { 3761 Type: DiffTypeAdded, 3762 Name: "KillTimeout", 3763 Old: "", 3764 New: "0", 3765 }, 3766 { 3767 Type: DiffTypeAdded, 3768 Name: "Leader", 3769 Old: "", 3770 New: "false", 3771 }, 3772 { 3773 Type: DiffTypeAdded, 3774 Name: "ShutdownDelay", 3775 Old: "", 3776 New: "0", 3777 }, 3778 }, 3779 }, 3780 { 3781 Type: DiffTypeNone, 3782 Name: "bar", 3783 }, 3784 { 3785 Type: DiffTypeEdited, 3786 Name: "baz", 3787 Fields: []*FieldDiff{ 3788 { 3789 Type: DiffTypeEdited, 3790 Name: "ShutdownDelay", 3791 Old: "1000000000", 3792 New: "2000000000", 3793 }, 3794 }, 3795 }, 3796 { 3797 Type: DiffTypeDeleted, 3798 Name: "foo", 3799 Fields: []*FieldDiff{ 3800 { 3801 Type: DiffTypeDeleted, 3802 Name: "Driver", 3803 Old: "docker", 3804 New: "", 3805 }, 3806 { 3807 Type: DiffTypeDeleted, 3808 Name: "KillTimeout", 3809 Old: "0", 3810 New: "", 3811 }, 3812 { 3813 Type: DiffTypeDeleted, 3814 Name: "Leader", 3815 Old: "false", 3816 New: "", 3817 }, 3818 { 3819 Type: DiffTypeDeleted, 3820 Name: "ShutdownDelay", 3821 Old: "0", 3822 New: "", 3823 }, 3824 }, 3825 }, 3826 }, 3827 }, 3828 }, 3829 { 3830 TestCase: "TaskGroup shutdown_delay edited", 3831 Old: &TaskGroup{ 3832 ShutdownDelay: pointer.Of(30 * time.Second), 3833 }, 3834 New: &TaskGroup{ 3835 ShutdownDelay: pointer.Of(5 * time.Second), 3836 }, 3837 Expected: &TaskGroupDiff{ 3838 Type: DiffTypeEdited, 3839 Fields: []*FieldDiff{ 3840 { 3841 Type: DiffTypeEdited, 3842 Name: "ShutdownDelay", 3843 Old: "30000000000", 3844 New: "5000000000", 3845 }, 3846 }, 3847 }, 3848 }, 3849 { 3850 TestCase: "TaskGroup shutdown_delay removed", 3851 Old: &TaskGroup{ 3852 ShutdownDelay: pointer.Of(30 * time.Second), 3853 }, 3854 New: &TaskGroup{}, 3855 Expected: &TaskGroupDiff{ 3856 Type: DiffTypeEdited, 3857 Fields: []*FieldDiff{ 3858 { 3859 Type: DiffTypeDeleted, 3860 Name: "ShutdownDelay", 3861 Old: "30000000000", 3862 New: "", 3863 }, 3864 }, 3865 }, 3866 }, 3867 { 3868 TestCase: "TaskGroup shutdown_delay added", 3869 Old: &TaskGroup{}, 3870 New: &TaskGroup{ 3871 ShutdownDelay: pointer.Of(30 * time.Second), 3872 }, 3873 Expected: &TaskGroupDiff{ 3874 Type: DiffTypeEdited, 3875 Fields: []*FieldDiff{ 3876 { 3877 Type: DiffTypeAdded, 3878 Name: "ShutdownDelay", 3879 Old: "", 3880 New: "30000000000", 3881 }, 3882 }, 3883 }, 3884 }, 3885 3886 { 3887 TestCase: "TaskGroup volumes added", 3888 Old: &TaskGroup{}, 3889 New: &TaskGroup{ 3890 Volumes: map[string]*VolumeRequest{ 3891 "foo": { 3892 Name: "foo", 3893 Type: "host", 3894 Source: "foo-src", 3895 ReadOnly: true, 3896 PerAlloc: true, 3897 }, 3898 }, 3899 }, 3900 3901 Expected: &TaskGroupDiff{ 3902 Type: DiffTypeEdited, 3903 Objects: []*ObjectDiff{ 3904 { 3905 Type: DiffTypeAdded, 3906 Name: "Volume", 3907 Fields: []*FieldDiff{ 3908 { 3909 Type: DiffTypeAdded, 3910 Name: "Name", 3911 Old: "", 3912 New: "foo", 3913 }, 3914 { 3915 Type: DiffTypeAdded, 3916 Name: "PerAlloc", 3917 Old: "", 3918 New: "true", 3919 }, 3920 { 3921 Type: DiffTypeAdded, 3922 Name: "ReadOnly", 3923 Old: "", 3924 New: "true", 3925 }, 3926 { 3927 Type: DiffTypeAdded, 3928 Name: "Source", 3929 Old: "", 3930 New: "foo-src", 3931 }, 3932 { 3933 Type: DiffTypeAdded, 3934 Name: "Type", 3935 Old: "", 3936 New: "host", 3937 }, 3938 }, 3939 }, 3940 }, 3941 }, 3942 }, 3943 3944 { 3945 TestCase: "TaskGroup volumes edited", 3946 Old: &TaskGroup{ 3947 Volumes: map[string]*VolumeRequest{ 3948 "foo": { 3949 Name: "foo", 3950 Type: "csi", 3951 Source: "foo-src1", 3952 ReadOnly: false, 3953 MountOptions: &CSIMountOptions{ 3954 FSType: "ext4", 3955 MountFlags: []string{"relatime", "rw"}, 3956 }, 3957 }, 3958 "bar": { 3959 Name: "bar", 3960 Type: "host", 3961 Source: "bar-src", 3962 ReadOnly: true, 3963 }, 3964 }, 3965 }, 3966 New: &TaskGroup{ 3967 Volumes: map[string]*VolumeRequest{ 3968 "foo": { 3969 Name: "foo", 3970 Type: "csi", 3971 Source: "foo-src2", 3972 ReadOnly: true, 3973 MountOptions: &CSIMountOptions{ 3974 FSType: "ext4", 3975 MountFlags: []string{"relatime", "rw", "nosuid"}, 3976 }, 3977 }, 3978 "bar": { // untouched 3979 Name: "bar", 3980 Type: "host", 3981 Source: "bar-src", 3982 ReadOnly: true, 3983 }, 3984 }, 3985 }, 3986 3987 Expected: &TaskGroupDiff{ 3988 Type: DiffTypeEdited, 3989 Objects: []*ObjectDiff{ 3990 { 3991 Type: DiffTypeEdited, 3992 Name: "Volume", 3993 Fields: []*FieldDiff{ 3994 { 3995 Type: DiffTypeEdited, 3996 Name: "ReadOnly", 3997 Old: "false", 3998 New: "true", 3999 }, 4000 { 4001 Type: DiffTypeEdited, 4002 Name: "Source", 4003 Old: "foo-src1", 4004 New: "foo-src2", 4005 }, 4006 }, 4007 Objects: []*ObjectDiff{ 4008 { 4009 Type: DiffTypeEdited, 4010 Name: "MountOptions", 4011 Objects: []*ObjectDiff{ 4012 { 4013 Type: DiffTypeAdded, 4014 Name: "MountFlags", 4015 Fields: []*FieldDiff{ 4016 { 4017 Type: DiffTypeAdded, 4018 Name: "MountFlags", 4019 Old: "", 4020 New: "nosuid", 4021 }, 4022 }, 4023 }, 4024 }, 4025 }, 4026 }, 4027 }, 4028 }, 4029 }, 4030 }, 4031 { 4032 TestCase: "MaxClientDisconnect added", 4033 Old: &TaskGroup{ 4034 Name: "foo", 4035 MaxClientDisconnect: nil, 4036 }, 4037 New: &TaskGroup{ 4038 Name: "foo", 4039 MaxClientDisconnect: pointer.Of(20 * time.Second), 4040 }, 4041 Expected: &TaskGroupDiff{ 4042 Type: DiffTypeEdited, 4043 Name: "foo", 4044 Fields: []*FieldDiff{ 4045 { 4046 Type: DiffTypeAdded, 4047 Name: "MaxClientDisconnect", 4048 Old: "", 4049 New: "20000000000", 4050 }, 4051 }, 4052 }, 4053 }, 4054 { 4055 TestCase: "MaxClientDisconnect updated", 4056 Old: &TaskGroup{ 4057 Name: "foo", 4058 MaxClientDisconnect: pointer.Of(10 * time.Second), 4059 }, 4060 New: &TaskGroup{ 4061 Name: "foo", 4062 MaxClientDisconnect: pointer.Of(20 * time.Second), 4063 }, 4064 Expected: &TaskGroupDiff{ 4065 Type: DiffTypeEdited, 4066 Name: "foo", 4067 Fields: []*FieldDiff{ 4068 { 4069 Type: DiffTypeEdited, 4070 Name: "MaxClientDisconnect", 4071 Old: "10000000000", 4072 New: "20000000000", 4073 }, 4074 }, 4075 }, 4076 }, 4077 { 4078 TestCase: "MaxClientDisconnect deleted", 4079 Old: &TaskGroup{ 4080 Name: "foo", 4081 MaxClientDisconnect: pointer.Of(10 * time.Second), 4082 }, 4083 New: &TaskGroup{ 4084 Name: "foo", 4085 MaxClientDisconnect: nil, 4086 }, 4087 Expected: &TaskGroupDiff{ 4088 Type: DiffTypeEdited, 4089 Name: "foo", 4090 Fields: []*FieldDiff{ 4091 { 4092 Type: DiffTypeDeleted, 4093 Name: "MaxClientDisconnect", 4094 Old: "10000000000", 4095 New: "", 4096 }, 4097 }, 4098 }, 4099 }, 4100 } 4101 4102 for i, c := range cases { 4103 require.NotEmpty(t, c.TestCase, "case #%d needs a name", i+1) 4104 4105 t.Run(c.TestCase, func(t *testing.T) { 4106 result, err := c.Old.Diff(c.New, c.Contextual) 4107 switch c.ExpErr { 4108 case true: 4109 require.Error(t, err, "case %q expected error", c.TestCase) 4110 case false: 4111 require.NoError(t, err, "case %q expected no error", c.TestCase) 4112 require.Equal(t, c.Expected, result) 4113 } 4114 }) 4115 } 4116 } 4117 4118 func TestTaskDiff(t *testing.T) { 4119 ci.Parallel(t) 4120 4121 cases := []struct { 4122 Name string 4123 Old, New *Task 4124 Expected *TaskDiff 4125 Error bool 4126 Contextual bool 4127 }{ 4128 { 4129 Name: "Empty", 4130 Old: nil, 4131 New: nil, 4132 Expected: &TaskDiff{ 4133 Type: DiffTypeNone, 4134 }, 4135 }, 4136 { 4137 Name: "Primitive only that has different names", 4138 Old: &Task{ 4139 Name: "foo", 4140 Meta: map[string]string{ 4141 "foo": "bar", 4142 }, 4143 }, 4144 New: &Task{ 4145 Name: "bar", 4146 Meta: map[string]string{ 4147 "foo": "bar", 4148 }, 4149 }, 4150 Error: true, 4151 }, 4152 { 4153 Name: "Primitive only that is the same", 4154 Old: &Task{ 4155 Name: "foo", 4156 Driver: "exec", 4157 User: "foo", 4158 Env: map[string]string{ 4159 "FOO": "bar", 4160 }, 4161 Meta: map[string]string{ 4162 "foo": "bar", 4163 }, 4164 KillTimeout: 1 * time.Second, 4165 Leader: true, 4166 }, 4167 New: &Task{ 4168 Name: "foo", 4169 Driver: "exec", 4170 User: "foo", 4171 Env: map[string]string{ 4172 "FOO": "bar", 4173 }, 4174 Meta: map[string]string{ 4175 "foo": "bar", 4176 }, 4177 KillTimeout: 1 * time.Second, 4178 Leader: true, 4179 }, 4180 Expected: &TaskDiff{ 4181 Type: DiffTypeNone, 4182 Name: "foo", 4183 }, 4184 }, 4185 { 4186 Name: "Primitive only that has diffs", 4187 Old: &Task{ 4188 Name: "foo", 4189 Driver: "exec", 4190 User: "foo", 4191 Env: map[string]string{ 4192 "FOO": "bar", 4193 }, 4194 Meta: map[string]string{ 4195 "foo": "bar", 4196 }, 4197 KillTimeout: 1 * time.Second, 4198 Leader: true, 4199 }, 4200 New: &Task{ 4201 Name: "foo", 4202 Driver: "docker", 4203 User: "bar", 4204 Env: map[string]string{ 4205 "FOO": "baz", 4206 }, 4207 Meta: map[string]string{ 4208 "foo": "baz", 4209 }, 4210 KillTimeout: 2 * time.Second, 4211 Leader: false, 4212 }, 4213 Expected: &TaskDiff{ 4214 Type: DiffTypeEdited, 4215 Name: "foo", 4216 Fields: []*FieldDiff{ 4217 { 4218 Type: DiffTypeEdited, 4219 Name: "Driver", 4220 Old: "exec", 4221 New: "docker", 4222 }, 4223 { 4224 Type: DiffTypeEdited, 4225 Name: "Env[FOO]", 4226 Old: "bar", 4227 New: "baz", 4228 }, 4229 { 4230 Type: DiffTypeEdited, 4231 Name: "KillTimeout", 4232 Old: "1000000000", 4233 New: "2000000000", 4234 }, 4235 { 4236 Type: DiffTypeEdited, 4237 Name: "Leader", 4238 Old: "true", 4239 New: "false", 4240 }, 4241 { 4242 Type: DiffTypeEdited, 4243 Name: "Meta[foo]", 4244 Old: "bar", 4245 New: "baz", 4246 }, 4247 { 4248 Type: DiffTypeEdited, 4249 Name: "User", 4250 Old: "foo", 4251 New: "bar", 4252 }, 4253 }, 4254 }, 4255 }, 4256 { 4257 Name: "Map diff", 4258 Old: &Task{ 4259 Meta: map[string]string{ 4260 "foo": "foo", 4261 "bar": "bar", 4262 }, 4263 Env: map[string]string{ 4264 "foo": "foo", 4265 "bar": "bar", 4266 }, 4267 }, 4268 New: &Task{ 4269 Meta: map[string]string{ 4270 "bar": "bar", 4271 "baz": "baz", 4272 }, 4273 Env: map[string]string{ 4274 "bar": "bar", 4275 "baz": "baz", 4276 }, 4277 }, 4278 Expected: &TaskDiff{ 4279 Type: DiffTypeEdited, 4280 Fields: []*FieldDiff{ 4281 { 4282 Type: DiffTypeAdded, 4283 Name: "Env[baz]", 4284 Old: "", 4285 New: "baz", 4286 }, 4287 { 4288 Type: DiffTypeDeleted, 4289 Name: "Env[foo]", 4290 Old: "foo", 4291 New: "", 4292 }, 4293 { 4294 Type: DiffTypeAdded, 4295 Name: "Meta[baz]", 4296 Old: "", 4297 New: "baz", 4298 }, 4299 { 4300 Type: DiffTypeDeleted, 4301 Name: "Meta[foo]", 4302 Old: "foo", 4303 New: "", 4304 }, 4305 }, 4306 }, 4307 }, 4308 { 4309 Name: "Constraints edited", 4310 Old: &Task{ 4311 Constraints: []*Constraint{ 4312 { 4313 LTarget: "foo", 4314 RTarget: "foo", 4315 Operand: "foo", 4316 }, 4317 { 4318 LTarget: "bar", 4319 RTarget: "bar", 4320 Operand: "bar", 4321 }, 4322 }, 4323 }, 4324 New: &Task{ 4325 Constraints: []*Constraint{ 4326 { 4327 LTarget: "foo", 4328 RTarget: "foo", 4329 Operand: "foo", 4330 }, 4331 { 4332 LTarget: "baz", 4333 RTarget: "baz", 4334 Operand: "baz", 4335 }, 4336 }, 4337 }, 4338 Expected: &TaskDiff{ 4339 Type: DiffTypeEdited, 4340 Objects: []*ObjectDiff{ 4341 { 4342 Type: DiffTypeAdded, 4343 Name: "Constraint", 4344 Fields: []*FieldDiff{ 4345 { 4346 Type: DiffTypeAdded, 4347 Name: "LTarget", 4348 Old: "", 4349 New: "baz", 4350 }, 4351 { 4352 Type: DiffTypeAdded, 4353 Name: "Operand", 4354 Old: "", 4355 New: "baz", 4356 }, 4357 { 4358 Type: DiffTypeAdded, 4359 Name: "RTarget", 4360 Old: "", 4361 New: "baz", 4362 }, 4363 }, 4364 }, 4365 { 4366 Type: DiffTypeDeleted, 4367 Name: "Constraint", 4368 Fields: []*FieldDiff{ 4369 { 4370 Type: DiffTypeDeleted, 4371 Name: "LTarget", 4372 Old: "bar", 4373 New: "", 4374 }, 4375 { 4376 Type: DiffTypeDeleted, 4377 Name: "Operand", 4378 Old: "bar", 4379 New: "", 4380 }, 4381 { 4382 Type: DiffTypeDeleted, 4383 Name: "RTarget", 4384 Old: "bar", 4385 New: "", 4386 }, 4387 }, 4388 }, 4389 }, 4390 }, 4391 }, 4392 { 4393 Name: "Affinities edited", 4394 Old: &Task{ 4395 Affinities: []*Affinity{ 4396 { 4397 LTarget: "foo", 4398 RTarget: "foo", 4399 Operand: "foo", 4400 Weight: 20, 4401 }, 4402 { 4403 LTarget: "bar", 4404 RTarget: "bar", 4405 Operand: "bar", 4406 Weight: 20, 4407 }, 4408 }, 4409 }, 4410 New: &Task{ 4411 Affinities: []*Affinity{ 4412 { 4413 LTarget: "foo", 4414 RTarget: "foo", 4415 Operand: "foo", 4416 Weight: 20, 4417 }, 4418 { 4419 LTarget: "baz", 4420 RTarget: "baz", 4421 Operand: "baz", 4422 Weight: 20, 4423 }, 4424 }, 4425 }, 4426 Expected: &TaskDiff{ 4427 Type: DiffTypeEdited, 4428 Objects: []*ObjectDiff{ 4429 { 4430 Type: DiffTypeAdded, 4431 Name: "Affinity", 4432 Fields: []*FieldDiff{ 4433 { 4434 Type: DiffTypeAdded, 4435 Name: "LTarget", 4436 Old: "", 4437 New: "baz", 4438 }, 4439 { 4440 Type: DiffTypeAdded, 4441 Name: "Operand", 4442 Old: "", 4443 New: "baz", 4444 }, 4445 { 4446 Type: DiffTypeAdded, 4447 Name: "RTarget", 4448 Old: "", 4449 New: "baz", 4450 }, 4451 { 4452 Type: DiffTypeAdded, 4453 Name: "Weight", 4454 Old: "", 4455 New: "20", 4456 }, 4457 }, 4458 }, 4459 { 4460 Type: DiffTypeDeleted, 4461 Name: "Affinity", 4462 Fields: []*FieldDiff{ 4463 { 4464 Type: DiffTypeDeleted, 4465 Name: "LTarget", 4466 Old: "bar", 4467 New: "", 4468 }, 4469 { 4470 Type: DiffTypeDeleted, 4471 Name: "Operand", 4472 Old: "bar", 4473 New: "", 4474 }, 4475 { 4476 Type: DiffTypeDeleted, 4477 Name: "RTarget", 4478 Old: "bar", 4479 New: "", 4480 }, 4481 { 4482 Type: DiffTypeDeleted, 4483 Name: "Weight", 4484 Old: "20", 4485 New: "", 4486 }, 4487 }, 4488 }, 4489 }, 4490 }, 4491 }, 4492 { 4493 Name: "LogConfig added", 4494 Old: &Task{}, 4495 New: &Task{ 4496 LogConfig: &LogConfig{ 4497 MaxFiles: 1, 4498 MaxFileSizeMB: 10, 4499 Disabled: true, 4500 }, 4501 }, 4502 Expected: &TaskDiff{ 4503 Type: DiffTypeEdited, 4504 Objects: []*ObjectDiff{ 4505 { 4506 Type: DiffTypeAdded, 4507 Name: "LogConfig", 4508 Fields: []*FieldDiff{ 4509 { 4510 Type: DiffTypeAdded, 4511 Name: "Disabled", 4512 Old: "", 4513 New: "true", 4514 }, 4515 { 4516 Type: DiffTypeAdded, 4517 Name: "MaxFileSizeMB", 4518 Old: "", 4519 New: "10", 4520 }, 4521 { 4522 Type: DiffTypeAdded, 4523 Name: "MaxFiles", 4524 Old: "", 4525 New: "1", 4526 }, 4527 }, 4528 }, 4529 }, 4530 }, 4531 }, 4532 { 4533 Name: "LogConfig deleted", 4534 Old: &Task{ 4535 LogConfig: &LogConfig{ 4536 MaxFiles: 1, 4537 MaxFileSizeMB: 10, 4538 Disabled: true, 4539 }, 4540 }, 4541 New: &Task{}, 4542 Expected: &TaskDiff{ 4543 Type: DiffTypeEdited, 4544 Objects: []*ObjectDiff{ 4545 { 4546 Type: DiffTypeDeleted, 4547 Name: "LogConfig", 4548 Fields: []*FieldDiff{ 4549 { 4550 Type: DiffTypeDeleted, 4551 Name: "Disabled", 4552 Old: "true", 4553 New: "", 4554 }, 4555 { 4556 Type: DiffTypeDeleted, 4557 Name: "MaxFileSizeMB", 4558 Old: "10", 4559 New: "", 4560 }, 4561 { 4562 Type: DiffTypeDeleted, 4563 Name: "MaxFiles", 4564 Old: "1", 4565 New: "", 4566 }, 4567 }, 4568 }, 4569 }, 4570 }, 4571 }, 4572 { 4573 Name: "LogConfig edited", 4574 Old: &Task{ 4575 LogConfig: &LogConfig{ 4576 MaxFiles: 1, 4577 MaxFileSizeMB: 10, 4578 Disabled: false, 4579 }, 4580 }, 4581 New: &Task{ 4582 LogConfig: &LogConfig{ 4583 MaxFiles: 2, 4584 MaxFileSizeMB: 20, 4585 Disabled: true, 4586 }, 4587 }, 4588 Expected: &TaskDiff{ 4589 Type: DiffTypeEdited, 4590 Objects: []*ObjectDiff{ 4591 { 4592 Type: DiffTypeEdited, 4593 Name: "LogConfig", 4594 Fields: []*FieldDiff{ 4595 { 4596 Type: DiffTypeEdited, 4597 Name: "Disabled", 4598 Old: "false", 4599 New: "true", 4600 }, 4601 { 4602 Type: DiffTypeEdited, 4603 Name: "MaxFileSizeMB", 4604 Old: "10", 4605 New: "20", 4606 }, 4607 { 4608 Type: DiffTypeEdited, 4609 Name: "MaxFiles", 4610 Old: "1", 4611 New: "2", 4612 }, 4613 }, 4614 }, 4615 }, 4616 }, 4617 }, 4618 { 4619 Name: "LogConfig edited with context", 4620 Contextual: true, 4621 Old: &Task{ 4622 LogConfig: &LogConfig{ 4623 MaxFiles: 1, 4624 MaxFileSizeMB: 10, 4625 Disabled: false, 4626 }, 4627 }, 4628 New: &Task{ 4629 LogConfig: &LogConfig{ 4630 MaxFiles: 1, 4631 MaxFileSizeMB: 20, 4632 Disabled: true, 4633 }, 4634 }, 4635 Expected: &TaskDiff{ 4636 Type: DiffTypeEdited, 4637 Objects: []*ObjectDiff{ 4638 { 4639 Type: DiffTypeEdited, 4640 Name: "LogConfig", 4641 Fields: []*FieldDiff{ 4642 { 4643 Type: DiffTypeEdited, 4644 Name: "Disabled", 4645 Old: "false", 4646 New: "true", 4647 }, 4648 { 4649 Type: DiffTypeEdited, 4650 Name: "MaxFileSizeMB", 4651 Old: "10", 4652 New: "20", 4653 }, 4654 { 4655 Type: DiffTypeNone, 4656 Name: "MaxFiles", 4657 Old: "1", 4658 New: "1", 4659 }, 4660 }, 4661 }, 4662 }, 4663 }, 4664 }, 4665 { 4666 Name: "Artifacts edited", 4667 Old: &Task{ 4668 Artifacts: []*TaskArtifact{ 4669 { 4670 GetterSource: "foo", 4671 GetterOptions: map[string]string{ 4672 "foo": "bar", 4673 }, 4674 RelativeDest: "foo", 4675 }, 4676 { 4677 GetterSource: "bar", 4678 GetterOptions: map[string]string{ 4679 "bar": "baz", 4680 }, 4681 GetterHeaders: map[string]string{ 4682 "User": "user1", 4683 }, 4684 GetterMode: "dir", 4685 RelativeDest: "bar", 4686 }, 4687 }, 4688 }, 4689 New: &Task{ 4690 Artifacts: []*TaskArtifact{ 4691 { 4692 GetterSource: "foo/bar", 4693 GetterOptions: map[string]string{ 4694 "foo": "bar", 4695 }, 4696 RelativeDest: "foo", 4697 }, 4698 { 4699 GetterSource: "bam", 4700 GetterOptions: map[string]string{ 4701 "bam": "baz", 4702 }, 4703 GetterHeaders: map[string]string{ 4704 "User": "user2", 4705 "User-Agent": "nomad", 4706 }, 4707 GetterMode: "file", 4708 RelativeDest: "bam", 4709 }, 4710 }, 4711 }, 4712 Expected: &TaskDiff{ 4713 Type: DiffTypeEdited, 4714 Objects: []*ObjectDiff{ 4715 { 4716 Type: DiffTypeEdited, 4717 Name: "Artifact", 4718 Fields: []*FieldDiff{ 4719 { 4720 Type: DiffTypeEdited, 4721 Name: "GetterSource", 4722 Old: "foo", 4723 New: "foo/bar", 4724 }, 4725 }, 4726 }, 4727 { 4728 Type: DiffTypeAdded, 4729 Name: "Artifact", 4730 Fields: []*FieldDiff{ 4731 { 4732 Type: DiffTypeAdded, 4733 Name: "GetterHeaders[User-Agent]", 4734 Old: "", 4735 New: "nomad", 4736 }, 4737 { 4738 Type: DiffTypeAdded, 4739 Name: "GetterHeaders[User]", 4740 Old: "", 4741 New: "user2", 4742 }, 4743 { 4744 Type: DiffTypeAdded, 4745 Name: "GetterMode", 4746 Old: "", 4747 New: "file", 4748 }, 4749 { 4750 Type: DiffTypeAdded, 4751 Name: "GetterOptions[bam]", 4752 Old: "", 4753 New: "baz", 4754 }, 4755 { 4756 Type: DiffTypeAdded, 4757 Name: "GetterSource", 4758 Old: "", 4759 New: "bam", 4760 }, 4761 { 4762 Type: DiffTypeAdded, 4763 Name: "RelativeDest", 4764 Old: "", 4765 New: "bam", 4766 }, 4767 }, 4768 }, 4769 { 4770 Type: DiffTypeDeleted, 4771 Name: "Artifact", 4772 Fields: []*FieldDiff{ 4773 { 4774 Type: DiffTypeDeleted, 4775 Name: "GetterHeaders[User]", 4776 Old: "user1", 4777 New: "", 4778 }, 4779 { 4780 Type: DiffTypeDeleted, 4781 Name: "GetterMode", 4782 Old: "dir", 4783 New: "", 4784 }, 4785 { 4786 Type: DiffTypeDeleted, 4787 Name: "GetterOptions[bar]", 4788 Old: "baz", 4789 New: "", 4790 }, 4791 { 4792 Type: DiffTypeDeleted, 4793 Name: "GetterSource", 4794 Old: "bar", 4795 New: "", 4796 }, 4797 { 4798 Type: DiffTypeDeleted, 4799 Name: "RelativeDest", 4800 Old: "bar", 4801 New: "", 4802 }, 4803 }, 4804 }, 4805 }, 4806 }, 4807 }, 4808 { 4809 Name: "Resources edited (no networks)", 4810 Old: &Task{ 4811 Resources: &Resources{ 4812 CPU: 100, 4813 MemoryMB: 100, 4814 DiskMB: 100, 4815 }, 4816 }, 4817 New: &Task{ 4818 Resources: &Resources{ 4819 CPU: 200, 4820 MemoryMB: 200, 4821 DiskMB: 200, 4822 }, 4823 }, 4824 Expected: &TaskDiff{ 4825 Type: DiffTypeEdited, 4826 Objects: []*ObjectDiff{ 4827 { 4828 Type: DiffTypeEdited, 4829 Name: "Resources", 4830 Fields: []*FieldDiff{ 4831 { 4832 Type: DiffTypeEdited, 4833 Name: "CPU", 4834 Old: "100", 4835 New: "200", 4836 }, 4837 { 4838 Type: DiffTypeEdited, 4839 Name: "DiskMB", 4840 Old: "100", 4841 New: "200", 4842 }, 4843 { 4844 Type: DiffTypeEdited, 4845 Name: "MemoryMB", 4846 Old: "100", 4847 New: "200", 4848 }, 4849 }, 4850 }, 4851 }, 4852 }, 4853 }, 4854 { 4855 Name: "Resources edited (no networks) with context", 4856 Contextual: true, 4857 Old: &Task{ 4858 Resources: &Resources{ 4859 CPU: 100, 4860 MemoryMB: 100, 4861 DiskMB: 100, 4862 }, 4863 }, 4864 New: &Task{ 4865 Resources: &Resources{ 4866 CPU: 200, 4867 MemoryMB: 100, 4868 DiskMB: 200, 4869 }, 4870 }, 4871 Expected: &TaskDiff{ 4872 Type: DiffTypeEdited, 4873 Objects: []*ObjectDiff{ 4874 { 4875 Type: DiffTypeEdited, 4876 Name: "Resources", 4877 Fields: []*FieldDiff{ 4878 { 4879 Type: DiffTypeEdited, 4880 Name: "CPU", 4881 Old: "100", 4882 New: "200", 4883 }, 4884 { 4885 Type: DiffTypeNone, 4886 Name: "Cores", 4887 Old: "0", 4888 New: "0", 4889 }, 4890 { 4891 Type: DiffTypeEdited, 4892 Name: "DiskMB", 4893 Old: "100", 4894 New: "200", 4895 }, 4896 { 4897 Type: DiffTypeNone, 4898 Name: "IOPS", 4899 Old: "0", 4900 New: "0", 4901 }, 4902 { 4903 Type: DiffTypeNone, 4904 Name: "MemoryMB", 4905 Old: "100", 4906 New: "100", 4907 }, 4908 { 4909 Type: DiffTypeNone, 4910 Name: "MemoryMaxMB", 4911 Old: "0", 4912 New: "0", 4913 }, 4914 }, 4915 }, 4916 }, 4917 }, 4918 }, 4919 { 4920 Name: "Resources edited memory_max", 4921 Old: &Task{ 4922 Resources: &Resources{ 4923 CPU: 100, 4924 MemoryMB: 100, 4925 MemoryMaxMB: 200, 4926 DiskMB: 100, 4927 }, 4928 }, 4929 New: &Task{ 4930 Resources: &Resources{ 4931 CPU: 100, 4932 MemoryMB: 100, 4933 MemoryMaxMB: 300, 4934 DiskMB: 100, 4935 }, 4936 }, 4937 Expected: &TaskDiff{ 4938 Type: DiffTypeEdited, 4939 Objects: []*ObjectDiff{ 4940 { 4941 Type: DiffTypeEdited, 4942 Name: "Resources", 4943 Fields: []*FieldDiff{ 4944 { 4945 Type: DiffTypeEdited, 4946 Name: "MemoryMaxMB", 4947 Old: "200", 4948 New: "300", 4949 }, 4950 }, 4951 }, 4952 }, 4953 }, 4954 }, 4955 { 4956 Name: "Resources edited memory_max with context", 4957 Contextual: true, 4958 Old: &Task{ 4959 Resources: &Resources{ 4960 CPU: 100, 4961 MemoryMB: 100, 4962 MemoryMaxMB: 200, 4963 DiskMB: 100, 4964 }, 4965 }, 4966 New: &Task{ 4967 Resources: &Resources{ 4968 CPU: 100, 4969 MemoryMB: 100, 4970 MemoryMaxMB: 300, 4971 DiskMB: 100, 4972 }, 4973 }, 4974 Expected: &TaskDiff{ 4975 Type: DiffTypeEdited, 4976 Objects: []*ObjectDiff{ 4977 { 4978 Type: DiffTypeEdited, 4979 Name: "Resources", 4980 Fields: []*FieldDiff{ 4981 { 4982 Type: DiffTypeNone, 4983 Name: "CPU", 4984 Old: "100", 4985 New: "100", 4986 }, 4987 { 4988 Type: DiffTypeNone, 4989 Name: "Cores", 4990 Old: "0", 4991 New: "0", 4992 }, 4993 { 4994 Type: DiffTypeNone, 4995 Name: "DiskMB", 4996 Old: "100", 4997 New: "100", 4998 }, 4999 { 5000 Type: DiffTypeNone, 5001 Name: "IOPS", 5002 Old: "0", 5003 New: "0", 5004 }, 5005 { 5006 Type: DiffTypeNone, 5007 Name: "MemoryMB", 5008 Old: "100", 5009 New: "100", 5010 }, 5011 { 5012 Type: DiffTypeEdited, 5013 Name: "MemoryMaxMB", 5014 Old: "200", 5015 New: "300", 5016 }, 5017 }, 5018 }, 5019 }, 5020 }, 5021 }, 5022 { 5023 Name: "Network Resources edited", 5024 Old: &Task{ 5025 Resources: &Resources{ 5026 Networks: []*NetworkResource{ 5027 { 5028 Device: "foo", 5029 CIDR: "foo", 5030 IP: "foo", 5031 MBits: 100, 5032 ReservedPorts: []Port{ 5033 { 5034 Label: "foo", 5035 Value: 80, 5036 }, 5037 }, 5038 DynamicPorts: []Port{ 5039 { 5040 Label: "bar", 5041 To: 8080, 5042 }, 5043 }, 5044 }, 5045 }, 5046 }, 5047 }, 5048 New: &Task{ 5049 Resources: &Resources{ 5050 Networks: []*NetworkResource{ 5051 { 5052 Device: "bar", 5053 CIDR: "bar", 5054 IP: "bar", 5055 MBits: 200, 5056 ReservedPorts: []Port{ 5057 { 5058 Label: "foo", 5059 Value: 81, 5060 }, 5061 }, 5062 DynamicPorts: []Port{ 5063 { 5064 Label: "baz", 5065 To: 8081, 5066 }, 5067 }, 5068 }, 5069 }, 5070 }, 5071 }, 5072 Expected: &TaskDiff{ 5073 Type: DiffTypeEdited, 5074 Objects: []*ObjectDiff{ 5075 { 5076 Type: DiffTypeEdited, 5077 Name: "Resources", 5078 Objects: []*ObjectDiff{ 5079 { 5080 Type: DiffTypeAdded, 5081 Name: "Network", 5082 Fields: []*FieldDiff{ 5083 { 5084 Type: DiffTypeAdded, 5085 Name: "MBits", 5086 Old: "", 5087 New: "200", 5088 }, 5089 }, 5090 Objects: []*ObjectDiff{ 5091 { 5092 Type: DiffTypeAdded, 5093 Name: "Static Port", 5094 Fields: []*FieldDiff{ 5095 { 5096 Type: DiffTypeAdded, 5097 Name: "Label", 5098 Old: "", 5099 New: "foo", 5100 }, 5101 { 5102 Type: DiffTypeAdded, 5103 Name: "To", 5104 Old: "", 5105 New: "0", 5106 }, 5107 { 5108 Type: DiffTypeAdded, 5109 Name: "Value", 5110 Old: "", 5111 New: "81", 5112 }, 5113 }, 5114 }, 5115 { 5116 Type: DiffTypeAdded, 5117 Name: "Dynamic Port", 5118 Fields: []*FieldDiff{ 5119 { 5120 Type: DiffTypeAdded, 5121 Name: "Label", 5122 Old: "", 5123 New: "baz", 5124 }, 5125 { 5126 Type: DiffTypeAdded, 5127 Name: "To", 5128 Old: "", 5129 New: "8081", 5130 }, 5131 }, 5132 }, 5133 }, 5134 }, 5135 { 5136 Type: DiffTypeDeleted, 5137 Name: "Network", 5138 Fields: []*FieldDiff{ 5139 { 5140 Type: DiffTypeDeleted, 5141 Name: "MBits", 5142 Old: "100", 5143 New: "", 5144 }, 5145 }, 5146 Objects: []*ObjectDiff{ 5147 { 5148 Type: DiffTypeDeleted, 5149 Name: "Static Port", 5150 Fields: []*FieldDiff{ 5151 { 5152 Type: DiffTypeDeleted, 5153 Name: "Label", 5154 Old: "foo", 5155 New: "", 5156 }, 5157 { 5158 Type: DiffTypeDeleted, 5159 Name: "To", 5160 Old: "0", 5161 New: "", 5162 }, 5163 { 5164 Type: DiffTypeDeleted, 5165 Name: "Value", 5166 Old: "80", 5167 New: "", 5168 }, 5169 }, 5170 }, 5171 { 5172 Type: DiffTypeDeleted, 5173 Name: "Dynamic Port", 5174 Fields: []*FieldDiff{ 5175 { 5176 Type: DiffTypeDeleted, 5177 Name: "Label", 5178 Old: "bar", 5179 New: "", 5180 }, 5181 { 5182 Type: DiffTypeDeleted, 5183 Name: "To", 5184 Old: "8080", 5185 New: "", 5186 }, 5187 }, 5188 }, 5189 }, 5190 }, 5191 }, 5192 }, 5193 }, 5194 }, 5195 }, 5196 { 5197 Name: "Device Resources edited", 5198 Old: &Task{ 5199 Resources: &Resources{ 5200 Devices: []*RequestedDevice{ 5201 { 5202 Name: "foo", 5203 Count: 2, 5204 }, 5205 { 5206 Name: "bar", 5207 Count: 2, 5208 }, 5209 { 5210 Name: "baz", 5211 Count: 2, 5212 }, 5213 }, 5214 }, 5215 }, 5216 New: &Task{ 5217 Resources: &Resources{ 5218 Devices: []*RequestedDevice{ 5219 { 5220 Name: "foo", 5221 Count: 2, 5222 }, 5223 { 5224 Name: "bar", 5225 Count: 3, 5226 }, 5227 { 5228 Name: "bam", 5229 Count: 2, 5230 }, 5231 }, 5232 }, 5233 }, 5234 Expected: &TaskDiff{ 5235 Type: DiffTypeEdited, 5236 Objects: []*ObjectDiff{ 5237 { 5238 Type: DiffTypeEdited, 5239 Name: "Resources", 5240 Objects: []*ObjectDiff{ 5241 { 5242 Type: DiffTypeEdited, 5243 Name: "Device", 5244 Fields: []*FieldDiff{ 5245 { 5246 Type: DiffTypeEdited, 5247 Name: "Count", 5248 Old: "2", 5249 New: "3", 5250 }, 5251 }, 5252 }, 5253 { 5254 Type: DiffTypeAdded, 5255 Name: "Device", 5256 Fields: []*FieldDiff{ 5257 { 5258 Type: DiffTypeAdded, 5259 Name: "Count", 5260 Old: "", 5261 New: "2", 5262 }, 5263 { 5264 Type: DiffTypeAdded, 5265 Name: "Name", 5266 Old: "", 5267 New: "bam", 5268 }, 5269 }, 5270 }, 5271 { 5272 Type: DiffTypeDeleted, 5273 Name: "Device", 5274 Fields: []*FieldDiff{ 5275 { 5276 Type: DiffTypeDeleted, 5277 Name: "Count", 5278 Old: "2", 5279 New: "", 5280 }, 5281 { 5282 Type: DiffTypeDeleted, 5283 Name: "Name", 5284 Old: "baz", 5285 New: "", 5286 }, 5287 }, 5288 }, 5289 }, 5290 }, 5291 }, 5292 }, 5293 }, 5294 { 5295 Name: "Device Resources edited with context", 5296 Contextual: true, 5297 Old: &Task{ 5298 Resources: &Resources{ 5299 CPU: 100, 5300 MemoryMB: 100, 5301 DiskMB: 100, 5302 Devices: []*RequestedDevice{ 5303 { 5304 Name: "foo", 5305 Count: 2, 5306 }, 5307 { 5308 Name: "bar", 5309 Count: 2, 5310 }, 5311 { 5312 Name: "baz", 5313 Count: 2, 5314 }, 5315 }, 5316 }, 5317 }, 5318 New: &Task{ 5319 Resources: &Resources{ 5320 CPU: 100, 5321 MemoryMB: 100, 5322 DiskMB: 100, 5323 Devices: []*RequestedDevice{ 5324 { 5325 Name: "foo", 5326 Count: 2, 5327 }, 5328 { 5329 Name: "bar", 5330 Count: 3, 5331 }, 5332 { 5333 Name: "bam", 5334 Count: 2, 5335 }, 5336 }, 5337 }, 5338 }, 5339 Expected: &TaskDiff{ 5340 Type: DiffTypeEdited, 5341 Objects: []*ObjectDiff{ 5342 { 5343 Type: DiffTypeEdited, 5344 Name: "Resources", 5345 Fields: []*FieldDiff{ 5346 { 5347 Type: DiffTypeNone, 5348 Name: "CPU", 5349 Old: "100", 5350 New: "100", 5351 }, 5352 { 5353 Type: DiffTypeNone, 5354 Name: "Cores", 5355 Old: "0", 5356 New: "0", 5357 }, 5358 { 5359 Type: DiffTypeNone, 5360 Name: "DiskMB", 5361 Old: "100", 5362 New: "100", 5363 }, 5364 { 5365 Type: DiffTypeNone, 5366 Name: "IOPS", 5367 Old: "0", 5368 New: "0", 5369 }, 5370 { 5371 Type: DiffTypeNone, 5372 Name: "MemoryMB", 5373 Old: "100", 5374 New: "100", 5375 }, 5376 { 5377 Type: DiffTypeNone, 5378 Name: "MemoryMaxMB", 5379 Old: "0", 5380 New: "0", 5381 }, 5382 }, 5383 Objects: []*ObjectDiff{ 5384 { 5385 Type: DiffTypeEdited, 5386 Name: "Device", 5387 Fields: []*FieldDiff{ 5388 { 5389 Type: DiffTypeEdited, 5390 Name: "Count", 5391 Old: "2", 5392 New: "3", 5393 }, 5394 { 5395 Type: DiffTypeNone, 5396 Name: "Name", 5397 Old: "bar", 5398 New: "bar", 5399 }, 5400 }, 5401 }, 5402 { 5403 Type: DiffTypeAdded, 5404 Name: "Device", 5405 Fields: []*FieldDiff{ 5406 { 5407 Type: DiffTypeAdded, 5408 Name: "Count", 5409 Old: "", 5410 New: "2", 5411 }, 5412 { 5413 Type: DiffTypeAdded, 5414 Name: "Name", 5415 Old: "", 5416 New: "bam", 5417 }, 5418 }, 5419 }, 5420 { 5421 Type: DiffTypeDeleted, 5422 Name: "Device", 5423 Fields: []*FieldDiff{ 5424 { 5425 Type: DiffTypeDeleted, 5426 Name: "Count", 5427 Old: "2", 5428 New: "", 5429 }, 5430 { 5431 Type: DiffTypeDeleted, 5432 Name: "Name", 5433 Old: "baz", 5434 New: "", 5435 }, 5436 }, 5437 }, 5438 }, 5439 }, 5440 }, 5441 }, 5442 }, 5443 { 5444 Name: "Config same", 5445 Old: &Task{ 5446 Config: map[string]interface{}{ 5447 "foo": 1, 5448 "bar": "bar", 5449 "bam": []string{"a", "b"}, 5450 "baz": map[string]int{ 5451 "a": 1, 5452 "b": 2, 5453 }, 5454 "boom": &Port{ 5455 Label: "boom_port", 5456 }, 5457 }, 5458 }, 5459 New: &Task{ 5460 Config: map[string]interface{}{ 5461 "foo": 1, 5462 "bar": "bar", 5463 "bam": []string{"a", "b"}, 5464 "baz": map[string]int{ 5465 "a": 1, 5466 "b": 2, 5467 }, 5468 "boom": &Port{ 5469 Label: "boom_port", 5470 }, 5471 }, 5472 }, 5473 Expected: &TaskDiff{ 5474 Type: DiffTypeNone, 5475 }, 5476 }, 5477 { 5478 Name: "Config edited", 5479 Old: &Task{ 5480 Config: map[string]interface{}{ 5481 "foo": 1, 5482 "bar": "baz", 5483 "bam": []string{"a", "b"}, 5484 "baz": map[string]int{ 5485 "a": 1, 5486 "b": 2, 5487 }, 5488 "boom": &Port{ 5489 Label: "boom_port", 5490 }, 5491 }, 5492 }, 5493 New: &Task{ 5494 Config: map[string]interface{}{ 5495 "foo": 2, 5496 "bar": "baz", 5497 "bam": []string{"a", "c", "d"}, 5498 "baz": map[string]int{ 5499 "b": 3, 5500 "c": 4, 5501 }, 5502 "boom": &Port{ 5503 Label: "boom_port2", 5504 }, 5505 }, 5506 }, 5507 Expected: &TaskDiff{ 5508 Type: DiffTypeEdited, 5509 Objects: []*ObjectDiff{ 5510 { 5511 Type: DiffTypeEdited, 5512 Name: "Config", 5513 Fields: []*FieldDiff{ 5514 { 5515 Type: DiffTypeEdited, 5516 Name: "bam[1]", 5517 Old: "b", 5518 New: "c", 5519 }, 5520 { 5521 Type: DiffTypeAdded, 5522 Name: "bam[2]", 5523 Old: "", 5524 New: "d", 5525 }, 5526 { 5527 Type: DiffTypeDeleted, 5528 Name: "baz[a]", 5529 Old: "1", 5530 New: "", 5531 }, 5532 { 5533 Type: DiffTypeEdited, 5534 Name: "baz[b]", 5535 Old: "2", 5536 New: "3", 5537 }, 5538 { 5539 Type: DiffTypeAdded, 5540 Name: "baz[c]", 5541 Old: "", 5542 New: "4", 5543 }, 5544 { 5545 Type: DiffTypeEdited, 5546 Name: "boom.Label", 5547 Old: "boom_port", 5548 New: "boom_port2", 5549 }, 5550 { 5551 Type: DiffTypeEdited, 5552 Name: "foo", 5553 Old: "1", 5554 New: "2", 5555 }, 5556 }, 5557 }, 5558 }, 5559 }, 5560 }, 5561 { 5562 Name: "Config edited with context", 5563 Contextual: true, 5564 Old: &Task{ 5565 Config: map[string]interface{}{ 5566 "foo": 1, 5567 "bar": "baz", 5568 "bam": []string{"a", "b"}, 5569 "baz": map[string]int{ 5570 "a": 1, 5571 "b": 2, 5572 }, 5573 "boom": &Port{ 5574 Label: "boom_port", 5575 }, 5576 }, 5577 }, 5578 New: &Task{ 5579 Config: map[string]interface{}{ 5580 "foo": 2, 5581 "bar": "baz", 5582 "bam": []string{"a", "c", "d"}, 5583 "baz": map[string]int{ 5584 "a": 1, 5585 "b": 2, 5586 }, 5587 "boom": &Port{ 5588 Label: "boom_port", 5589 }, 5590 }, 5591 }, 5592 Expected: &TaskDiff{ 5593 Type: DiffTypeEdited, 5594 Objects: []*ObjectDiff{ 5595 { 5596 Type: DiffTypeEdited, 5597 Name: "Config", 5598 Fields: []*FieldDiff{ 5599 { 5600 Type: DiffTypeNone, 5601 Name: "bam[0]", 5602 Old: "a", 5603 New: "a", 5604 }, 5605 { 5606 Type: DiffTypeEdited, 5607 Name: "bam[1]", 5608 Old: "b", 5609 New: "c", 5610 }, 5611 { 5612 Type: DiffTypeAdded, 5613 Name: "bam[2]", 5614 Old: "", 5615 New: "d", 5616 }, 5617 { 5618 Type: DiffTypeNone, 5619 Name: "bar", 5620 Old: "baz", 5621 New: "baz", 5622 }, 5623 { 5624 Type: DiffTypeNone, 5625 Name: "baz[a]", 5626 Old: "1", 5627 New: "1", 5628 }, 5629 { 5630 Type: DiffTypeNone, 5631 Name: "baz[b]", 5632 Old: "2", 5633 New: "2", 5634 }, 5635 { 5636 Type: DiffTypeNone, 5637 Name: "boom.HostNetwork", 5638 Old: "", 5639 New: "", 5640 }, 5641 { 5642 Type: DiffTypeNone, 5643 Name: "boom.Label", 5644 Old: "boom_port", 5645 New: "boom_port", 5646 }, 5647 { 5648 Type: DiffTypeNone, 5649 Name: "boom.To", 5650 Old: "0", 5651 New: "0", 5652 }, 5653 { 5654 Type: DiffTypeNone, 5655 Name: "boom.Value", 5656 Old: "0", 5657 New: "0", 5658 }, 5659 { 5660 Type: DiffTypeEdited, 5661 Name: "foo", 5662 Old: "1", 5663 New: "2", 5664 }, 5665 }, 5666 }, 5667 }, 5668 }, 5669 }, 5670 { 5671 Name: "Services edited (no checks)", 5672 Old: &Task{ 5673 Services: []*Service{ 5674 { 5675 Name: "foo", 5676 PortLabel: "foo", 5677 }, 5678 { 5679 Name: "bar", 5680 PortLabel: "bar", 5681 }, 5682 { 5683 Name: "baz", 5684 PortLabel: "baz", 5685 }, 5686 }, 5687 }, 5688 New: &Task{ 5689 Services: []*Service{ 5690 { 5691 Name: "bar", 5692 PortLabel: "bar", 5693 }, 5694 { 5695 Name: "baz", 5696 PortLabel: "baz2", 5697 }, 5698 { 5699 Name: "bam", 5700 PortLabel: "bam", 5701 }, 5702 }, 5703 }, 5704 Expected: &TaskDiff{ 5705 Type: DiffTypeEdited, 5706 Objects: []*ObjectDiff{ 5707 { 5708 Type: DiffTypeEdited, 5709 Name: "Service", 5710 Fields: []*FieldDiff{ 5711 { 5712 Type: DiffTypeEdited, 5713 Name: "PortLabel", 5714 Old: "baz", 5715 New: "baz2", 5716 }, 5717 }, 5718 }, 5719 { 5720 Type: DiffTypeAdded, 5721 Name: "Service", 5722 Fields: []*FieldDiff{ 5723 { 5724 Type: DiffTypeAdded, 5725 Name: "EnableTagOverride", 5726 Old: "", 5727 New: "false", 5728 }, 5729 { 5730 Type: DiffTypeAdded, 5731 Name: "Name", 5732 Old: "", 5733 New: "bam", 5734 }, 5735 { 5736 Type: DiffTypeAdded, 5737 Name: "PortLabel", 5738 Old: "", 5739 New: "bam", 5740 }, 5741 }, 5742 }, 5743 { 5744 Type: DiffTypeDeleted, 5745 Name: "Service", 5746 Fields: []*FieldDiff{ 5747 { 5748 Type: DiffTypeDeleted, 5749 Name: "EnableTagOverride", 5750 Old: "false", 5751 New: "", 5752 }, 5753 { 5754 Type: DiffTypeDeleted, 5755 Name: "Name", 5756 Old: "foo", 5757 New: "", 5758 }, 5759 { 5760 Type: DiffTypeDeleted, 5761 Name: "PortLabel", 5762 Old: "foo", 5763 New: "", 5764 }, 5765 }, 5766 }, 5767 }, 5768 }, 5769 }, 5770 { 5771 Name: "Services edited (no checks) with context", 5772 Contextual: true, 5773 Old: &Task{ 5774 Services: []*Service{ 5775 { 5776 Name: "foo", 5777 PortLabel: "foo", 5778 }, 5779 }, 5780 }, 5781 New: &Task{ 5782 Services: []*Service{ 5783 { 5784 Name: "foo", 5785 PortLabel: "bar", 5786 AddressMode: "driver", 5787 Address: "a.example.com", 5788 TaskName: "task1", 5789 }, 5790 }, 5791 }, 5792 Expected: &TaskDiff{ 5793 Type: DiffTypeEdited, 5794 Objects: []*ObjectDiff{ 5795 { 5796 Type: DiffTypeEdited, 5797 Name: "Service", 5798 Fields: []*FieldDiff{ 5799 { 5800 Type: DiffTypeAdded, 5801 Name: "Address", 5802 Old: "", 5803 New: "a.example.com", 5804 }, 5805 { 5806 Type: DiffTypeAdded, 5807 Name: "AddressMode", 5808 Old: "", 5809 New: "driver", 5810 }, 5811 { 5812 Type: DiffTypeNone, 5813 Name: "EnableTagOverride", 5814 Old: "false", 5815 New: "false", 5816 }, 5817 { 5818 Type: DiffTypeNone, 5819 Name: "Name", 5820 Old: "foo", 5821 New: "foo", 5822 }, 5823 { 5824 Type: DiffTypeNone, 5825 Name: "Namespace", 5826 Old: "", 5827 New: "", 5828 }, 5829 { 5830 Type: DiffTypeNone, 5831 Name: "OnUpdate", 5832 Old: "", 5833 New: "", 5834 }, 5835 { 5836 Type: DiffTypeEdited, 5837 Name: "PortLabel", 5838 Old: "foo", 5839 New: "bar", 5840 }, 5841 { 5842 Type: DiffTypeNone, 5843 Name: "Provider", 5844 }, 5845 { 5846 Type: DiffTypeAdded, 5847 Name: "TaskName", 5848 Old: "", 5849 New: "task1", 5850 }, 5851 }, 5852 }, 5853 }, 5854 }, 5855 }, 5856 { 5857 Name: "Service EnableTagOverride edited no context", 5858 Contextual: false, 5859 Old: &Task{ 5860 Services: []*Service{{ 5861 EnableTagOverride: false, 5862 }}, 5863 }, 5864 New: &Task{ 5865 Services: []*Service{{ 5866 EnableTagOverride: true, 5867 }}, 5868 }, 5869 Expected: &TaskDiff{ 5870 Type: DiffTypeEdited, 5871 Objects: []*ObjectDiff{ 5872 { 5873 Type: DiffTypeEdited, 5874 Name: "Service", 5875 Fields: []*FieldDiff{ 5876 { 5877 Type: DiffTypeEdited, 5878 Name: "EnableTagOverride", 5879 Old: "false", 5880 New: "true", 5881 }, 5882 }, 5883 }, 5884 }, 5885 }, 5886 }, 5887 { 5888 Name: "Services tags edited (no checks) with context", 5889 Contextual: true, 5890 Old: &Task{ 5891 Services: []*Service{ 5892 { 5893 Tags: []string{"foo", "bar"}, 5894 CanaryTags: []string{"foo", "bar"}, 5895 }, 5896 }, 5897 }, 5898 New: &Task{ 5899 Services: []*Service{ 5900 { 5901 Tags: []string{"bar", "bam"}, 5902 CanaryTags: []string{"bar", "bam"}, 5903 }, 5904 }, 5905 }, 5906 Expected: &TaskDiff{ 5907 Type: DiffTypeEdited, 5908 Objects: []*ObjectDiff{ 5909 { 5910 Type: DiffTypeEdited, 5911 Name: "Service", 5912 Objects: []*ObjectDiff{ 5913 { 5914 Type: DiffTypeEdited, 5915 Name: "CanaryTags", 5916 Fields: []*FieldDiff{ 5917 { 5918 Type: DiffTypeAdded, 5919 Name: "CanaryTags", 5920 Old: "", 5921 New: "bam", 5922 }, 5923 { 5924 Type: DiffTypeNone, 5925 Name: "CanaryTags", 5926 Old: "bar", 5927 New: "bar", 5928 }, 5929 { 5930 Type: DiffTypeDeleted, 5931 Name: "CanaryTags", 5932 Old: "foo", 5933 New: "", 5934 }, 5935 }, 5936 }, 5937 { 5938 Type: DiffTypeEdited, 5939 Name: "Tags", 5940 Fields: []*FieldDiff{ 5941 { 5942 Type: DiffTypeAdded, 5943 Name: "Tags", 5944 Old: "", 5945 New: "bam", 5946 }, 5947 { 5948 Type: DiffTypeNone, 5949 Name: "Tags", 5950 Old: "bar", 5951 New: "bar", 5952 }, 5953 { 5954 Type: DiffTypeDeleted, 5955 Name: "Tags", 5956 Old: "foo", 5957 New: "", 5958 }, 5959 }, 5960 }, 5961 }, 5962 Fields: []*FieldDiff{ 5963 { 5964 Type: DiffTypeNone, 5965 Name: "Address", 5966 }, 5967 { 5968 Type: DiffTypeNone, 5969 Name: "AddressMode", 5970 }, 5971 { 5972 Type: DiffTypeNone, 5973 Name: "EnableTagOverride", 5974 Old: "false", 5975 New: "false", 5976 }, 5977 { 5978 Type: DiffTypeNone, 5979 Name: "Name", 5980 }, 5981 { 5982 Type: DiffTypeNone, 5983 Name: "Namespace", 5984 }, 5985 { 5986 Type: DiffTypeNone, 5987 Name: "OnUpdate", 5988 }, 5989 { 5990 Type: DiffTypeNone, 5991 Name: "PortLabel", 5992 }, 5993 { 5994 Type: DiffTypeNone, 5995 Name: "Provider", 5996 }, 5997 { 5998 Type: DiffTypeNone, 5999 Name: "TaskName", 6000 }, 6001 }, 6002 }, 6003 }, 6004 }, 6005 }, 6006 6007 { 6008 Name: "Service with Connect", 6009 Old: &Task{ 6010 Services: []*Service{ 6011 { 6012 Name: "foo", 6013 }, 6014 }, 6015 }, 6016 New: &Task{ 6017 Services: []*Service{ 6018 { 6019 Name: "foo", 6020 Connect: &ConsulConnect{ 6021 SidecarService: &ConsulSidecarService{}, 6022 }, 6023 }, 6024 }, 6025 }, 6026 Expected: &TaskDiff{ 6027 Type: DiffTypeEdited, 6028 Objects: []*ObjectDiff{ 6029 { 6030 Type: DiffTypeEdited, 6031 Name: "Service", 6032 Objects: []*ObjectDiff{ 6033 { 6034 Type: DiffTypeAdded, 6035 Name: "ConsulConnect", 6036 Fields: []*FieldDiff{ 6037 { 6038 Type: DiffTypeAdded, 6039 Name: "Native", 6040 Old: "", 6041 New: "false", 6042 }, 6043 }, 6044 Objects: []*ObjectDiff{ 6045 { 6046 Type: DiffTypeAdded, 6047 Name: "SidecarService", 6048 Fields: []*FieldDiff{ 6049 { 6050 Type: DiffTypeAdded, 6051 Name: "DisableDefaultTCPCheck", 6052 Old: "", 6053 New: "false", 6054 }, 6055 }, 6056 }, 6057 }, 6058 }, 6059 }, 6060 }, 6061 }, 6062 }, 6063 }, 6064 6065 { 6066 Name: "Service with Connect Native", 6067 Old: &Task{ 6068 Services: []*Service{ 6069 { 6070 Name: "foo", 6071 }, 6072 }, 6073 }, 6074 New: &Task{ 6075 Services: []*Service{ 6076 { 6077 Name: "foo", 6078 TaskName: "task1", 6079 Connect: &ConsulConnect{ 6080 Native: true, 6081 }, 6082 }, 6083 }, 6084 }, 6085 Expected: &TaskDiff{ 6086 Type: DiffTypeEdited, 6087 Objects: []*ObjectDiff{ 6088 { 6089 Type: DiffTypeEdited, 6090 Name: "Service", 6091 Fields: []*FieldDiff{ 6092 { 6093 Type: DiffTypeAdded, 6094 Name: "TaskName", 6095 Old: "", 6096 New: "task1", 6097 }, 6098 }, 6099 Objects: []*ObjectDiff{ 6100 { 6101 Type: DiffTypeAdded, 6102 Name: "ConsulConnect", 6103 Fields: []*FieldDiff{ 6104 { 6105 Type: DiffTypeAdded, 6106 Name: "Native", 6107 Old: "", 6108 New: "true", 6109 }, 6110 }, 6111 }, 6112 }, 6113 }, 6114 }, 6115 }, 6116 }, 6117 6118 { 6119 Name: "Service Checks edited", 6120 Old: &Task{ 6121 Services: []*Service{ 6122 { 6123 Name: "foo", 6124 Checks: []*ServiceCheck{ 6125 { 6126 Name: "foo", 6127 Type: "http", 6128 Command: "foo", 6129 Args: []string{"foo"}, 6130 Path: "foo", 6131 Protocol: "http", 6132 Interval: 1 * time.Second, 6133 Timeout: 1 * time.Second, 6134 Header: map[string][]string{ 6135 "Foo": {"bar"}, 6136 }, 6137 SuccessBeforePassing: 1, 6138 FailuresBeforeCritical: 1, 6139 }, 6140 { 6141 Name: "bar", 6142 Type: "http", 6143 Command: "foo", 6144 Args: []string{"foo"}, 6145 Path: "foo", 6146 Protocol: "http", 6147 Interval: 1 * time.Second, 6148 Timeout: 1 * time.Second, 6149 SuccessBeforePassing: 7, 6150 FailuresBeforeCritical: 7, 6151 }, 6152 { 6153 Name: "baz", 6154 Type: "http", 6155 Command: "foo", 6156 Args: []string{"foo"}, 6157 Path: "foo", 6158 Protocol: "http", 6159 Interval: 1 * time.Second, 6160 Timeout: 1 * time.Second, 6161 }, 6162 }, 6163 }, 6164 }, 6165 }, 6166 New: &Task{ 6167 Services: []*Service{ 6168 { 6169 Name: "foo", 6170 Checks: []*ServiceCheck{ 6171 { 6172 Name: "bar", 6173 Type: "http", 6174 Command: "foo", 6175 Args: []string{"foo"}, 6176 Path: "foo", 6177 Protocol: "http", 6178 Interval: 1 * time.Second, 6179 Timeout: 1 * time.Second, 6180 SuccessBeforePassing: 7, 6181 FailuresBeforeCritical: 7, 6182 }, 6183 { 6184 Name: "baz", 6185 Type: "tcp", 6186 Command: "foo", 6187 Args: []string{"foo"}, 6188 Path: "foo", 6189 Protocol: "http", 6190 Interval: 1 * time.Second, 6191 Timeout: 1 * time.Second, 6192 Header: map[string][]string{ 6193 "Eggs": {"spam"}, 6194 }, 6195 }, 6196 { 6197 Name: "bam", 6198 Type: "http", 6199 Command: "foo", 6200 Args: []string{"foo"}, 6201 Path: "foo", 6202 Protocol: "http", 6203 Interval: 1 * time.Second, 6204 Timeout: 1 * time.Second, 6205 SuccessBeforePassing: 2, 6206 FailuresBeforeCritical: 2, 6207 }, 6208 }, 6209 }, 6210 }, 6211 }, 6212 Expected: &TaskDiff{ 6213 Type: DiffTypeEdited, 6214 Objects: []*ObjectDiff{ 6215 { 6216 Type: DiffTypeEdited, 6217 Name: "Service", 6218 Objects: []*ObjectDiff{ 6219 { 6220 Type: DiffTypeEdited, 6221 Name: "Check", 6222 Fields: []*FieldDiff{ 6223 { 6224 Type: DiffTypeEdited, 6225 Name: "Type", 6226 Old: "http", 6227 New: "tcp", 6228 }, 6229 }, 6230 Objects: []*ObjectDiff{ 6231 { 6232 Type: DiffTypeAdded, 6233 Name: "Header", 6234 Fields: []*FieldDiff{ 6235 { 6236 Type: DiffTypeAdded, 6237 Name: "Eggs[0]", 6238 Old: "", 6239 New: "spam", 6240 }, 6241 }, 6242 }, 6243 }, 6244 }, 6245 { 6246 Type: DiffTypeAdded, 6247 Name: "Check", 6248 Fields: []*FieldDiff{ 6249 { 6250 Type: DiffTypeAdded, 6251 Name: "Command", 6252 Old: "", 6253 New: "foo", 6254 }, 6255 { 6256 Type: DiffTypeAdded, 6257 Name: "Expose", 6258 Old: "", 6259 New: "false", 6260 }, 6261 { 6262 Type: DiffTypeAdded, 6263 Name: "FailuresBeforeCritical", 6264 Old: "", 6265 New: "2", 6266 }, 6267 { 6268 Type: DiffTypeAdded, 6269 Name: "GRPCUseTLS", 6270 Old: "", 6271 New: "false", 6272 }, 6273 { 6274 Type: DiffTypeAdded, 6275 Name: "Interval", 6276 Old: "", 6277 New: "1000000000", 6278 }, 6279 { 6280 Type: DiffTypeAdded, 6281 Name: "Name", 6282 Old: "", 6283 New: "bam", 6284 }, 6285 { 6286 Type: DiffTypeAdded, 6287 Name: "Path", 6288 Old: "", 6289 New: "foo", 6290 }, 6291 { 6292 Type: DiffTypeAdded, 6293 Name: "Protocol", 6294 Old: "", 6295 New: "http", 6296 }, 6297 { 6298 Type: DiffTypeAdded, 6299 Name: "SuccessBeforePassing", 6300 Old: "", 6301 New: "2", 6302 }, 6303 { 6304 Type: DiffTypeAdded, 6305 Name: "TLSSkipVerify", 6306 Old: "", 6307 New: "false", 6308 }, 6309 { 6310 Type: DiffTypeAdded, 6311 Name: "Timeout", 6312 Old: "", 6313 New: "1000000000", 6314 }, 6315 { 6316 Type: DiffTypeAdded, 6317 Name: "Type", 6318 Old: "", 6319 New: "http", 6320 }, 6321 }, 6322 }, 6323 { 6324 Type: DiffTypeDeleted, 6325 Name: "Check", 6326 Fields: []*FieldDiff{ 6327 { 6328 Type: DiffTypeDeleted, 6329 Name: "Command", 6330 Old: "foo", 6331 New: "", 6332 }, 6333 { 6334 Type: DiffTypeDeleted, 6335 Name: "Expose", 6336 Old: "false", 6337 New: "", 6338 }, 6339 { 6340 Type: DiffTypeDeleted, 6341 Name: "FailuresBeforeCritical", 6342 Old: "1", 6343 New: "", 6344 }, 6345 { 6346 Type: DiffTypeDeleted, 6347 Name: "GRPCUseTLS", 6348 Old: "false", 6349 New: "", 6350 }, 6351 { 6352 Type: DiffTypeDeleted, 6353 Name: "Interval", 6354 Old: "1000000000", 6355 New: "", 6356 }, 6357 { 6358 Type: DiffTypeDeleted, 6359 Name: "Name", 6360 Old: "foo", 6361 New: "", 6362 }, 6363 { 6364 Type: DiffTypeDeleted, 6365 Name: "Path", 6366 Old: "foo", 6367 New: "", 6368 }, 6369 { 6370 Type: DiffTypeDeleted, 6371 Name: "Protocol", 6372 Old: "http", 6373 New: "", 6374 }, 6375 { 6376 Type: DiffTypeDeleted, 6377 Name: "SuccessBeforePassing", 6378 Old: "1", 6379 New: "", 6380 }, 6381 { 6382 Type: DiffTypeDeleted, 6383 Name: "TLSSkipVerify", 6384 Old: "false", 6385 New: "", 6386 }, 6387 { 6388 Type: DiffTypeDeleted, 6389 Name: "Timeout", 6390 Old: "1000000000", 6391 New: "", 6392 }, 6393 { 6394 Type: DiffTypeDeleted, 6395 Name: "Type", 6396 Old: "http", 6397 New: "", 6398 }, 6399 }, 6400 Objects: []*ObjectDiff{ 6401 { 6402 Type: DiffTypeDeleted, 6403 Name: "Header", 6404 Fields: []*FieldDiff{ 6405 { 6406 Type: DiffTypeDeleted, 6407 Name: "Foo[0]", 6408 Old: "bar", 6409 }, 6410 }, 6411 }, 6412 }, 6413 }, 6414 }, 6415 }, 6416 }, 6417 }, 6418 }, 6419 { 6420 Name: "Service Checks edited with context", 6421 Contextual: true, 6422 Old: &Task{ 6423 Services: []*Service{ 6424 { 6425 Name: "foo", 6426 Checks: []*ServiceCheck{ 6427 { 6428 Name: "foo", 6429 Type: "http", 6430 Command: "foo", 6431 Args: []string{"foo"}, 6432 Path: "foo", 6433 Protocol: "http", 6434 Interval: 1 * time.Second, 6435 Timeout: 1 * time.Second, 6436 InitialStatus: "critical", 6437 Header: map[string][]string{ 6438 "Foo": {"bar"}, 6439 }, 6440 SuccessBeforePassing: 4, 6441 FailuresBeforeCritical: 5, 6442 OnUpdate: "require_healthy", 6443 }, 6444 }, 6445 }, 6446 }, 6447 }, 6448 New: &Task{ 6449 Services: []*Service{ 6450 { 6451 Name: "foo", 6452 Checks: []*ServiceCheck{ 6453 { 6454 Name: "foo", 6455 Type: "tcp", 6456 Command: "foo", 6457 Args: []string{"foo"}, 6458 Path: "foo", 6459 Protocol: "http", 6460 Interval: 1 * time.Second, 6461 Timeout: 1 * time.Second, 6462 InitialStatus: "passing", 6463 Method: "POST", 6464 Header: map[string][]string{ 6465 "Foo": {"bar", "baz"}, 6466 "Eggs": {"spam"}, 6467 }, 6468 SuccessBeforePassing: 4, 6469 OnUpdate: "ignore_warnings", 6470 }, 6471 }, 6472 }, 6473 }, 6474 }, 6475 Expected: &TaskDiff{ 6476 Type: DiffTypeEdited, 6477 Objects: []*ObjectDiff{ 6478 { 6479 Type: DiffTypeEdited, 6480 Name: "Service", 6481 Fields: []*FieldDiff{ 6482 { 6483 Type: DiffTypeNone, 6484 Name: "Address", 6485 Old: "", 6486 New: "", 6487 }, 6488 { 6489 Type: DiffTypeNone, 6490 Name: "AddressMode", 6491 Old: "", 6492 New: "", 6493 }, 6494 { 6495 Type: DiffTypeNone, 6496 Name: "EnableTagOverride", 6497 Old: "false", 6498 New: "false", 6499 }, 6500 { 6501 Type: DiffTypeNone, 6502 Name: "Name", 6503 Old: "foo", 6504 New: "foo", 6505 }, 6506 { 6507 Type: DiffTypeNone, 6508 Name: "Namespace", 6509 Old: "", 6510 New: "", 6511 }, 6512 { 6513 Type: DiffTypeNone, 6514 Name: "OnUpdate", 6515 }, 6516 { 6517 Type: DiffTypeNone, 6518 Name: "PortLabel", 6519 Old: "", 6520 New: "", 6521 }, 6522 { 6523 Type: DiffTypeNone, 6524 Name: "Provider", 6525 }, 6526 { 6527 Type: DiffTypeNone, 6528 Name: "TaskName", 6529 Old: "", 6530 New: "", 6531 }, 6532 }, 6533 Objects: []*ObjectDiff{ 6534 { 6535 Type: DiffTypeEdited, 6536 Name: "Check", 6537 Fields: []*FieldDiff{ 6538 { 6539 Type: DiffTypeNone, 6540 Name: "AddressMode", 6541 Old: "", 6542 New: "", 6543 }, 6544 { 6545 Type: DiffTypeNone, 6546 Name: "Body", 6547 Old: "", 6548 New: "", 6549 }, 6550 { 6551 Type: DiffTypeNone, 6552 Name: "Command", 6553 Old: "foo", 6554 New: "foo", 6555 }, 6556 { 6557 Type: DiffTypeNone, 6558 Name: "Expose", 6559 Old: "false", 6560 New: "false", 6561 }, 6562 { 6563 Type: DiffTypeEdited, 6564 Name: "FailuresBeforeCritical", 6565 Old: "5", 6566 New: "0", 6567 }, 6568 { 6569 Type: DiffTypeNone, 6570 Name: "GRPCService", 6571 Old: "", 6572 New: "", 6573 }, 6574 { 6575 Type: DiffTypeNone, 6576 Name: "GRPCUseTLS", 6577 Old: "false", 6578 New: "false", 6579 }, 6580 { 6581 Type: DiffTypeEdited, 6582 Name: "InitialStatus", 6583 Old: "critical", 6584 New: "passing", 6585 }, 6586 { 6587 Type: DiffTypeNone, 6588 Name: "Interval", 6589 Old: "1000000000", 6590 New: "1000000000", 6591 }, 6592 { 6593 Type: DiffTypeAdded, 6594 Name: "Method", 6595 Old: "", 6596 New: "POST", 6597 }, 6598 { 6599 Type: DiffTypeNone, 6600 Name: "Name", 6601 Old: "foo", 6602 New: "foo", 6603 }, 6604 { 6605 Type: DiffTypeEdited, 6606 Name: "OnUpdate", 6607 Old: "require_healthy", 6608 New: "ignore_warnings", 6609 }, 6610 { 6611 Type: DiffTypeNone, 6612 Name: "Path", 6613 Old: "foo", 6614 New: "foo", 6615 }, 6616 { 6617 Type: DiffTypeNone, 6618 Name: "PortLabel", 6619 Old: "", 6620 New: "", 6621 }, 6622 { 6623 Type: DiffTypeNone, 6624 Name: "Protocol", 6625 Old: "http", 6626 New: "http", 6627 }, 6628 { 6629 Type: DiffTypeNone, 6630 Name: "SuccessBeforePassing", 6631 Old: "4", 6632 New: "4", 6633 }, 6634 { 6635 Type: DiffTypeNone, 6636 Name: "TLSServerName", 6637 Old: "", 6638 New: "", 6639 }, 6640 { 6641 Type: DiffTypeNone, 6642 Name: "TLSSkipVerify", 6643 Old: "false", 6644 New: "false", 6645 }, 6646 { 6647 Type: DiffTypeNone, 6648 Name: "TaskName", 6649 Old: "", 6650 New: "", 6651 }, 6652 { 6653 Type: DiffTypeNone, 6654 Name: "Timeout", 6655 Old: "1000000000", 6656 New: "1000000000", 6657 }, 6658 { 6659 Type: DiffTypeEdited, 6660 Name: "Type", 6661 Old: "http", 6662 New: "tcp", 6663 }, 6664 }, 6665 Objects: []*ObjectDiff{ 6666 { 6667 Type: DiffTypeEdited, 6668 Name: "Header", 6669 Fields: []*FieldDiff{ 6670 { 6671 Type: DiffTypeAdded, 6672 Name: "Eggs[0]", 6673 Old: "", 6674 New: "spam", 6675 }, 6676 { 6677 Type: DiffTypeNone, 6678 Name: "Foo[0]", 6679 Old: "bar", 6680 New: "bar", 6681 }, 6682 { 6683 Type: DiffTypeAdded, 6684 Name: "Foo[1]", 6685 Old: "", 6686 New: "baz", 6687 }, 6688 }, 6689 }, 6690 }, 6691 }, 6692 }, 6693 }, 6694 }, 6695 }, 6696 }, 6697 { 6698 Name: "CheckRestart edited", 6699 Old: &Task{ 6700 Services: []*Service{ 6701 { 6702 Name: "foo", 6703 Checks: []*ServiceCheck{ 6704 { 6705 Name: "foo", 6706 Type: "http", 6707 Command: "foo", 6708 Args: []string{"foo"}, 6709 Path: "foo", 6710 Protocol: "http", 6711 Interval: 1 * time.Second, 6712 Timeout: 1 * time.Second, 6713 }, 6714 { 6715 Name: "bar", 6716 Type: "http", 6717 Command: "foo", 6718 Args: []string{"foo"}, 6719 Path: "foo", 6720 Protocol: "http", 6721 Interval: 1 * time.Second, 6722 Timeout: 1 * time.Second, 6723 CheckRestart: &CheckRestart{ 6724 Limit: 2, 6725 Grace: 2 * time.Second, 6726 }, 6727 }, 6728 { 6729 Name: "baz", 6730 Type: "http", 6731 Command: "foo", 6732 Args: []string{"foo"}, 6733 Path: "foo", 6734 Protocol: "http", 6735 Interval: 1 * time.Second, 6736 Timeout: 1 * time.Second, 6737 CheckRestart: &CheckRestart{ 6738 Limit: 3, 6739 Grace: 3 * time.Second, 6740 }, 6741 }, 6742 }, 6743 }, 6744 }, 6745 }, 6746 New: &Task{ 6747 Services: []*Service{ 6748 { 6749 Name: "foo", 6750 Checks: []*ServiceCheck{ 6751 { 6752 Name: "foo", 6753 Type: "http", 6754 Command: "foo", 6755 Args: []string{"foo"}, 6756 Path: "foo", 6757 Protocol: "http", 6758 Interval: 1 * time.Second, 6759 Timeout: 1 * time.Second, 6760 CheckRestart: &CheckRestart{ 6761 Limit: 1, 6762 Grace: 1 * time.Second, 6763 }, 6764 }, 6765 { 6766 Name: "bar", 6767 Type: "http", 6768 Command: "foo", 6769 Args: []string{"foo"}, 6770 Path: "foo", 6771 Protocol: "http", 6772 Interval: 1 * time.Second, 6773 Timeout: 1 * time.Second, 6774 }, 6775 { 6776 Name: "baz", 6777 Type: "http", 6778 Command: "foo", 6779 Args: []string{"foo"}, 6780 Path: "foo", 6781 Protocol: "http", 6782 Interval: 1 * time.Second, 6783 Timeout: 1 * time.Second, 6784 CheckRestart: &CheckRestart{ 6785 Limit: 4, 6786 Grace: 4 * time.Second, 6787 }, 6788 }, 6789 }, 6790 }, 6791 }, 6792 }, 6793 Expected: &TaskDiff{ 6794 Type: DiffTypeEdited, 6795 Objects: []*ObjectDiff{ 6796 { 6797 Type: DiffTypeEdited, 6798 Name: "Service", 6799 Objects: []*ObjectDiff{ 6800 { 6801 Type: DiffTypeEdited, 6802 Name: "Check", 6803 Objects: []*ObjectDiff{ 6804 { 6805 Type: DiffTypeEdited, 6806 Name: "CheckRestart", 6807 Fields: []*FieldDiff{ 6808 { 6809 Type: DiffTypeEdited, 6810 Name: "Grace", 6811 Old: "3000000000", 6812 New: "4000000000", 6813 }, 6814 { 6815 Type: DiffTypeEdited, 6816 Name: "Limit", 6817 Old: "3", 6818 New: "4", 6819 }, 6820 }, 6821 }, 6822 }, 6823 }, 6824 { 6825 Type: DiffTypeEdited, 6826 Name: "Check", 6827 Objects: []*ObjectDiff{ 6828 { 6829 Type: DiffTypeAdded, 6830 Name: "CheckRestart", 6831 Fields: []*FieldDiff{ 6832 { 6833 Type: DiffTypeAdded, 6834 Name: "Grace", 6835 New: "1000000000", 6836 }, 6837 { 6838 Type: DiffTypeAdded, 6839 Name: "IgnoreWarnings", 6840 New: "false", 6841 }, 6842 { 6843 Type: DiffTypeAdded, 6844 Name: "Limit", 6845 New: "1", 6846 }, 6847 }, 6848 }, 6849 }, 6850 }, 6851 { 6852 Type: DiffTypeEdited, 6853 Name: "Check", 6854 Objects: []*ObjectDiff{ 6855 { 6856 Type: DiffTypeDeleted, 6857 Name: "CheckRestart", 6858 Fields: []*FieldDiff{ 6859 { 6860 Type: DiffTypeDeleted, 6861 Name: "Grace", 6862 Old: "2000000000", 6863 }, 6864 { 6865 Type: DiffTypeDeleted, 6866 Name: "IgnoreWarnings", 6867 Old: "false", 6868 }, 6869 { 6870 Type: DiffTypeDeleted, 6871 Name: "Limit", 6872 Old: "2", 6873 }, 6874 }, 6875 }, 6876 }, 6877 }, 6878 }, 6879 }, 6880 }, 6881 }, 6882 }, 6883 { 6884 Name: "Vault added", 6885 Old: &Task{}, 6886 New: &Task{ 6887 Vault: &Vault{ 6888 Policies: []string{"foo", "bar"}, 6889 Env: true, 6890 DisableFile: true, 6891 ChangeMode: "signal", 6892 ChangeSignal: "SIGUSR1", 6893 }, 6894 }, 6895 Expected: &TaskDiff{ 6896 Type: DiffTypeEdited, 6897 Objects: []*ObjectDiff{ 6898 { 6899 Type: DiffTypeAdded, 6900 Name: "Vault", 6901 Fields: []*FieldDiff{ 6902 { 6903 Type: DiffTypeAdded, 6904 Name: "ChangeMode", 6905 Old: "", 6906 New: "signal", 6907 }, 6908 { 6909 Type: DiffTypeAdded, 6910 Name: "ChangeSignal", 6911 Old: "", 6912 New: "SIGUSR1", 6913 }, 6914 { 6915 Type: DiffTypeAdded, 6916 Name: "DisableFile", 6917 Old: "", 6918 New: "true", 6919 }, 6920 { 6921 Type: DiffTypeAdded, 6922 Name: "Env", 6923 Old: "", 6924 New: "true", 6925 }, 6926 }, 6927 Objects: []*ObjectDiff{ 6928 { 6929 Type: DiffTypeAdded, 6930 Name: "Policies", 6931 Fields: []*FieldDiff{ 6932 { 6933 Type: DiffTypeAdded, 6934 Name: "Policies", 6935 Old: "", 6936 New: "bar", 6937 }, 6938 { 6939 Type: DiffTypeAdded, 6940 Name: "Policies", 6941 Old: "", 6942 New: "foo", 6943 }, 6944 }, 6945 }, 6946 }, 6947 }, 6948 }, 6949 }, 6950 }, 6951 { 6952 Name: "Vault deleted", 6953 Old: &Task{ 6954 Vault: &Vault{ 6955 Policies: []string{"foo", "bar"}, 6956 Env: true, 6957 DisableFile: true, 6958 ChangeMode: "signal", 6959 ChangeSignal: "SIGUSR1", 6960 }, 6961 }, 6962 New: &Task{}, 6963 Expected: &TaskDiff{ 6964 Type: DiffTypeEdited, 6965 Objects: []*ObjectDiff{ 6966 { 6967 Type: DiffTypeDeleted, 6968 Name: "Vault", 6969 Fields: []*FieldDiff{ 6970 { 6971 Type: DiffTypeDeleted, 6972 Name: "ChangeMode", 6973 Old: "signal", 6974 New: "", 6975 }, 6976 { 6977 Type: DiffTypeDeleted, 6978 Name: "ChangeSignal", 6979 Old: "SIGUSR1", 6980 New: "", 6981 }, 6982 { 6983 Type: DiffTypeDeleted, 6984 Name: "DisableFile", 6985 Old: "true", 6986 New: "", 6987 }, 6988 { 6989 Type: DiffTypeDeleted, 6990 Name: "Env", 6991 Old: "true", 6992 New: "", 6993 }, 6994 }, 6995 Objects: []*ObjectDiff{ 6996 { 6997 Type: DiffTypeDeleted, 6998 Name: "Policies", 6999 Fields: []*FieldDiff{ 7000 { 7001 Type: DiffTypeDeleted, 7002 Name: "Policies", 7003 Old: "bar", 7004 New: "", 7005 }, 7006 { 7007 Type: DiffTypeDeleted, 7008 Name: "Policies", 7009 Old: "foo", 7010 New: "", 7011 }, 7012 }, 7013 }, 7014 }, 7015 }, 7016 }, 7017 }, 7018 }, 7019 { 7020 Name: "Vault edited", 7021 Old: &Task{ 7022 Vault: &Vault{ 7023 Namespace: "ns1", 7024 Policies: []string{"foo", "bar"}, 7025 Env: true, 7026 DisableFile: true, 7027 ChangeMode: "signal", 7028 ChangeSignal: "SIGUSR1", 7029 }, 7030 }, 7031 New: &Task{ 7032 Vault: &Vault{ 7033 Namespace: "ns2", 7034 Policies: []string{"bar", "baz"}, 7035 Env: false, 7036 DisableFile: false, 7037 ChangeMode: "restart", 7038 ChangeSignal: "foo", 7039 }, 7040 }, 7041 Expected: &TaskDiff{ 7042 Type: DiffTypeEdited, 7043 Objects: []*ObjectDiff{ 7044 { 7045 Type: DiffTypeEdited, 7046 Name: "Vault", 7047 Fields: []*FieldDiff{ 7048 { 7049 Type: DiffTypeEdited, 7050 Name: "ChangeMode", 7051 Old: "signal", 7052 New: "restart", 7053 }, 7054 { 7055 Type: DiffTypeEdited, 7056 Name: "ChangeSignal", 7057 Old: "SIGUSR1", 7058 New: "foo", 7059 }, 7060 { 7061 Type: DiffTypeEdited, 7062 Name: "DisableFile", 7063 Old: "true", 7064 New: "false", 7065 }, 7066 { 7067 Type: DiffTypeEdited, 7068 Name: "Env", 7069 Old: "true", 7070 New: "false", 7071 }, 7072 { 7073 Type: DiffTypeEdited, 7074 Name: "Namespace", 7075 Old: "ns1", 7076 New: "ns2", 7077 }, 7078 }, 7079 Objects: []*ObjectDiff{ 7080 { 7081 Type: DiffTypeEdited, 7082 Name: "Policies", 7083 Fields: []*FieldDiff{ 7084 { 7085 Type: DiffTypeAdded, 7086 Name: "Policies", 7087 Old: "", 7088 New: "baz", 7089 }, 7090 { 7091 Type: DiffTypeDeleted, 7092 Name: "Policies", 7093 Old: "foo", 7094 New: "", 7095 }, 7096 }, 7097 }, 7098 }, 7099 }, 7100 }, 7101 }, 7102 }, 7103 { 7104 Name: "Vault edited with context", 7105 Contextual: true, 7106 Old: &Task{ 7107 Vault: &Vault{ 7108 Namespace: "ns1", 7109 Policies: []string{"foo", "bar"}, 7110 Env: true, 7111 DisableFile: true, 7112 ChangeMode: "signal", 7113 ChangeSignal: "SIGUSR1", 7114 }, 7115 }, 7116 New: &Task{ 7117 Vault: &Vault{ 7118 Namespace: "ns1", 7119 Policies: []string{"bar", "baz"}, 7120 Env: true, 7121 DisableFile: true, 7122 ChangeMode: "signal", 7123 ChangeSignal: "SIGUSR1", 7124 }, 7125 }, 7126 Expected: &TaskDiff{ 7127 Type: DiffTypeEdited, 7128 Objects: []*ObjectDiff{ 7129 { 7130 Type: DiffTypeEdited, 7131 Name: "Vault", 7132 Fields: []*FieldDiff{ 7133 { 7134 Type: DiffTypeNone, 7135 Name: "ChangeMode", 7136 Old: "signal", 7137 New: "signal", 7138 }, 7139 { 7140 Type: DiffTypeNone, 7141 Name: "ChangeSignal", 7142 Old: "SIGUSR1", 7143 New: "SIGUSR1", 7144 }, 7145 { 7146 Type: DiffTypeNone, 7147 Name: "DisableFile", 7148 Old: "true", 7149 New: "true", 7150 }, 7151 { 7152 Type: DiffTypeNone, 7153 Name: "Env", 7154 Old: "true", 7155 New: "true", 7156 }, 7157 { 7158 Type: DiffTypeNone, 7159 Name: "Namespace", 7160 Old: "ns1", 7161 New: "ns1", 7162 }, 7163 }, 7164 Objects: []*ObjectDiff{ 7165 { 7166 Type: DiffTypeEdited, 7167 Name: "Policies", 7168 Fields: []*FieldDiff{ 7169 { 7170 Type: DiffTypeAdded, 7171 Name: "Policies", 7172 Old: "", 7173 New: "baz", 7174 }, 7175 { 7176 Type: DiffTypeNone, 7177 Name: "Policies", 7178 Old: "bar", 7179 New: "bar", 7180 }, 7181 { 7182 Type: DiffTypeDeleted, 7183 Name: "Policies", 7184 Old: "foo", 7185 New: "", 7186 }, 7187 }, 7188 }, 7189 }, 7190 }, 7191 }, 7192 }, 7193 }, 7194 { 7195 Name: "Template edited", 7196 Old: &Task{ 7197 Templates: []*Template{ 7198 { 7199 SourcePath: "foo", 7200 DestPath: "bar", 7201 EmbeddedTmpl: "baz", 7202 ChangeMode: "bam", 7203 ChangeSignal: "SIGHUP", 7204 ChangeScript: &ChangeScript{ 7205 Command: "/bin/foo", 7206 Args: []string{"-debug"}, 7207 Timeout: 5, 7208 FailOnError: false, 7209 }, 7210 Splay: 1, 7211 Perms: "0644", 7212 Uid: pointer.Of(1001), 7213 Gid: pointer.Of(21), 7214 Wait: &WaitConfig{ 7215 Min: pointer.Of(5 * time.Second), 7216 Max: pointer.Of(5 * time.Second), 7217 }, 7218 ErrMissingKey: false, 7219 }, 7220 { 7221 SourcePath: "foo2", 7222 DestPath: "bar2", 7223 EmbeddedTmpl: "baz2", 7224 ChangeMode: "bam2", 7225 ChangeSignal: "SIGHUP2", 7226 ChangeScript: &ChangeScript{ 7227 Command: "/bin/foo2", 7228 Args: []string{"-debugs"}, 7229 Timeout: 6, 7230 FailOnError: false, 7231 }, 7232 Splay: 2, 7233 Perms: "0666", 7234 Uid: pointer.Of(1000), 7235 Gid: pointer.Of(20), 7236 Envvars: true, 7237 }, 7238 }, 7239 }, 7240 New: &Task{ 7241 Templates: []*Template{ 7242 { 7243 SourcePath: "foo", 7244 DestPath: "bar", 7245 EmbeddedTmpl: "baz new", 7246 ChangeMode: "bam", 7247 ChangeSignal: "SIGHUP", 7248 ChangeScript: &ChangeScript{ 7249 Command: "/bin/foo", 7250 Args: []string{"-debug"}, 7251 Timeout: 5, 7252 FailOnError: false, 7253 }, 7254 Splay: 1, 7255 Perms: "0644", 7256 Uid: pointer.Of(1001), 7257 Gid: pointer.Of(21), 7258 Wait: &WaitConfig{ 7259 Min: pointer.Of(5 * time.Second), 7260 Max: pointer.Of(10 * time.Second), 7261 }, 7262 ErrMissingKey: true, 7263 }, 7264 { 7265 SourcePath: "foo3", 7266 DestPath: "bar3", 7267 EmbeddedTmpl: "baz3", 7268 ChangeMode: "bam3", 7269 ChangeSignal: "SIGHUP3", 7270 ChangeScript: &ChangeScript{ 7271 Command: "/bin/foo3", 7272 Args: []string{"-debugss"}, 7273 Timeout: 7, 7274 FailOnError: false, 7275 }, 7276 Splay: 3, 7277 Perms: "0776", 7278 Uid: pointer.Of(1002), 7279 Gid: pointer.Of(22), 7280 Wait: &WaitConfig{ 7281 Min: pointer.Of(5 * time.Second), 7282 Max: pointer.Of(10 * time.Second), 7283 }, 7284 ErrMissingKey: true, 7285 }, 7286 }, 7287 }, 7288 Expected: &TaskDiff{ 7289 Type: DiffTypeEdited, 7290 Objects: []*ObjectDiff{ 7291 { 7292 Type: DiffTypeEdited, 7293 Name: "Template", 7294 Fields: []*FieldDiff{ 7295 { 7296 Type: DiffTypeEdited, 7297 Name: "EmbeddedTmpl", 7298 Old: "baz", 7299 New: "baz new", 7300 }, 7301 { 7302 Type: DiffTypeEdited, 7303 Name: "ErrMissingKey", 7304 Old: "false", 7305 New: "true", 7306 }, 7307 }, 7308 Objects: []*ObjectDiff{ 7309 { 7310 Type: DiffTypeEdited, 7311 Name: "Template", 7312 Fields: []*FieldDiff{ 7313 { 7314 Type: DiffTypeEdited, 7315 Name: "Max", 7316 Old: "5000000000", 7317 New: "10000000000", 7318 }, 7319 }, 7320 }, 7321 }, 7322 }, 7323 { 7324 Type: DiffTypeAdded, 7325 Name: "Template", 7326 Fields: []*FieldDiff{ 7327 { 7328 Type: DiffTypeAdded, 7329 Name: "ChangeMode", 7330 Old: "", 7331 New: "bam3", 7332 }, 7333 { 7334 Type: DiffTypeAdded, 7335 Name: "ChangeSignal", 7336 Old: "", 7337 New: "SIGHUP3", 7338 }, 7339 { 7340 Type: DiffTypeAdded, 7341 Name: "DestPath", 7342 Old: "", 7343 New: "bar3", 7344 }, 7345 { 7346 Type: DiffTypeAdded, 7347 Name: "EmbeddedTmpl", 7348 Old: "", 7349 New: "baz3", 7350 }, 7351 { 7352 Type: DiffTypeAdded, 7353 Name: "Envvars", 7354 Old: "", 7355 New: "false", 7356 }, 7357 { 7358 Type: DiffTypeAdded, 7359 Name: "ErrMissingKey", 7360 Old: "", 7361 New: "true", 7362 }, 7363 { 7364 Type: DiffTypeAdded, 7365 Name: "Gid", 7366 Old: "", 7367 New: "22", 7368 }, 7369 { 7370 Type: DiffTypeAdded, 7371 Name: "Perms", 7372 Old: "", 7373 New: "0776", 7374 }, 7375 { 7376 Type: DiffTypeAdded, 7377 Name: "SourcePath", 7378 Old: "", 7379 New: "foo3", 7380 }, 7381 { 7382 Type: DiffTypeAdded, 7383 Name: "Splay", 7384 Old: "", 7385 New: "3", 7386 }, 7387 { 7388 Type: DiffTypeAdded, 7389 Name: "Uid", 7390 Old: "", 7391 New: "1002", 7392 }, 7393 { 7394 Type: DiffTypeAdded, 7395 Name: "VaultGrace", 7396 Old: "", 7397 New: "0", 7398 }, 7399 }, 7400 Objects: []*ObjectDiff{ 7401 { 7402 Type: DiffTypeAdded, 7403 Name: "Template", 7404 Fields: []*FieldDiff{ 7405 { 7406 Type: DiffTypeAdded, 7407 Name: "Max", 7408 Old: "", 7409 New: "10000000000", 7410 }, 7411 { 7412 Type: DiffTypeAdded, 7413 Name: "Min", 7414 Old: "", 7415 New: "5000000000", 7416 }, 7417 }, 7418 }, 7419 { 7420 Type: DiffTypeAdded, 7421 Name: "ChangeScript", 7422 Fields: []*FieldDiff{ 7423 { 7424 Type: DiffTypeAdded, 7425 Name: "Command", 7426 Old: "", 7427 New: "/bin/foo3", 7428 }, 7429 { 7430 Type: DiffTypeAdded, 7431 Name: "FailOnError", 7432 Old: "", 7433 New: "false", 7434 }, 7435 { 7436 Type: DiffTypeAdded, 7437 Name: "Timeout", 7438 Old: "", 7439 New: "7", 7440 }, 7441 }, 7442 Objects: []*ObjectDiff{ 7443 { 7444 Type: DiffTypeAdded, 7445 Name: "Args", 7446 Fields: []*FieldDiff{ 7447 { 7448 Type: DiffTypeAdded, 7449 Name: "Args", 7450 Old: "", 7451 New: "-debugss", 7452 }, 7453 }, 7454 }, 7455 }, 7456 }, 7457 }, 7458 }, 7459 { 7460 Type: DiffTypeDeleted, 7461 Name: "Template", 7462 Fields: []*FieldDiff{ 7463 { 7464 Type: DiffTypeDeleted, 7465 Name: "ChangeMode", 7466 Old: "bam2", 7467 New: "", 7468 }, 7469 { 7470 Type: DiffTypeDeleted, 7471 Name: "ChangeSignal", 7472 Old: "SIGHUP2", 7473 New: "", 7474 }, 7475 { 7476 Type: DiffTypeDeleted, 7477 Name: "DestPath", 7478 Old: "bar2", 7479 New: "", 7480 }, 7481 { 7482 Type: DiffTypeDeleted, 7483 Name: "EmbeddedTmpl", 7484 Old: "baz2", 7485 New: "", 7486 }, 7487 { 7488 Type: DiffTypeDeleted, 7489 Name: "Envvars", 7490 Old: "true", 7491 New: "", 7492 }, 7493 { 7494 Type: DiffTypeDeleted, 7495 Name: "ErrMissingKey", 7496 Old: "false", 7497 New: "", 7498 }, 7499 { 7500 Type: DiffTypeDeleted, 7501 Name: "Gid", 7502 Old: "20", 7503 New: "", 7504 }, 7505 { 7506 Type: DiffTypeDeleted, 7507 Name: "Perms", 7508 Old: "0666", 7509 New: "", 7510 }, 7511 { 7512 Type: DiffTypeDeleted, 7513 Name: "SourcePath", 7514 Old: "foo2", 7515 New: "", 7516 }, 7517 { 7518 Type: DiffTypeDeleted, 7519 Name: "Splay", 7520 Old: "2", 7521 New: "", 7522 }, 7523 { 7524 Type: DiffTypeDeleted, 7525 Name: "Uid", 7526 Old: "1000", 7527 New: "", 7528 }, 7529 { 7530 Type: DiffTypeDeleted, 7531 Name: "VaultGrace", 7532 Old: "0", 7533 New: "", 7534 }, 7535 }, 7536 Objects: []*ObjectDiff{ 7537 { 7538 Type: DiffTypeDeleted, 7539 Name: "ChangeScript", 7540 Fields: []*FieldDiff{ 7541 { 7542 Type: DiffTypeDeleted, 7543 Name: "Command", 7544 Old: "/bin/foo2", 7545 New: "", 7546 }, 7547 { 7548 Type: DiffTypeDeleted, 7549 Name: "FailOnError", 7550 Old: "false", 7551 New: "", 7552 }, 7553 { 7554 Type: DiffTypeDeleted, 7555 Name: "Timeout", 7556 Old: "6", 7557 New: "", 7558 }, 7559 }, 7560 Objects: []*ObjectDiff{ 7561 { 7562 Type: DiffTypeDeleted, 7563 Name: "Args", 7564 Fields: []*FieldDiff{ 7565 { 7566 Type: DiffTypeDeleted, 7567 Name: "Args", 7568 Old: "-debugs", 7569 New: "", 7570 }, 7571 }, 7572 }, 7573 }, 7574 }, 7575 }, 7576 }, 7577 }, 7578 }, 7579 }, 7580 { 7581 Name: "DispatchPayload added", 7582 Old: &Task{}, 7583 New: &Task{ 7584 DispatchPayload: &DispatchPayloadConfig{ 7585 File: "foo", 7586 }, 7587 }, 7588 Expected: &TaskDiff{ 7589 Type: DiffTypeEdited, 7590 Objects: []*ObjectDiff{ 7591 { 7592 Type: DiffTypeAdded, 7593 Name: "DispatchPayload", 7594 Fields: []*FieldDiff{ 7595 { 7596 Type: DiffTypeAdded, 7597 Name: "File", 7598 Old: "", 7599 New: "foo", 7600 }, 7601 }, 7602 }, 7603 }, 7604 }, 7605 }, 7606 { 7607 Name: "DispatchPayload deleted", 7608 Old: &Task{ 7609 DispatchPayload: &DispatchPayloadConfig{ 7610 File: "foo", 7611 }, 7612 }, 7613 New: &Task{}, 7614 Expected: &TaskDiff{ 7615 Type: DiffTypeEdited, 7616 Objects: []*ObjectDiff{ 7617 { 7618 Type: DiffTypeDeleted, 7619 Name: "DispatchPayload", 7620 Fields: []*FieldDiff{ 7621 { 7622 Type: DiffTypeDeleted, 7623 Name: "File", 7624 Old: "foo", 7625 New: "", 7626 }, 7627 }, 7628 }, 7629 }, 7630 }, 7631 }, 7632 { 7633 Name: "Dispatch payload edited", 7634 Old: &Task{ 7635 DispatchPayload: &DispatchPayloadConfig{ 7636 File: "foo", 7637 }, 7638 }, 7639 New: &Task{ 7640 DispatchPayload: &DispatchPayloadConfig{ 7641 File: "bar", 7642 }, 7643 }, 7644 Expected: &TaskDiff{ 7645 Type: DiffTypeEdited, 7646 Objects: []*ObjectDiff{ 7647 { 7648 Type: DiffTypeEdited, 7649 Name: "DispatchPayload", 7650 Fields: []*FieldDiff{ 7651 { 7652 Type: DiffTypeEdited, 7653 Name: "File", 7654 Old: "foo", 7655 New: "bar", 7656 }, 7657 }, 7658 }, 7659 }, 7660 }, 7661 }, 7662 { 7663 // Place holder for if more fields are added 7664 Name: "DispatchPayload edited with context", 7665 Contextual: true, 7666 Old: &Task{ 7667 DispatchPayload: &DispatchPayloadConfig{ 7668 File: "foo", 7669 }, 7670 }, 7671 New: &Task{ 7672 DispatchPayload: &DispatchPayloadConfig{ 7673 File: "bar", 7674 }, 7675 }, 7676 Expected: &TaskDiff{ 7677 Type: DiffTypeEdited, 7678 Objects: []*ObjectDiff{ 7679 { 7680 Type: DiffTypeEdited, 7681 Name: "DispatchPayload", 7682 Fields: []*FieldDiff{ 7683 { 7684 Type: DiffTypeEdited, 7685 Name: "File", 7686 Old: "foo", 7687 New: "bar", 7688 }, 7689 }, 7690 }, 7691 }, 7692 }, 7693 }, 7694 { 7695 Name: "Identity added", 7696 Old: &Task{}, 7697 New: &Task{ 7698 Identity: &WorkloadIdentity{ 7699 Env: true, 7700 }, 7701 }, 7702 Expected: &TaskDiff{ 7703 Type: DiffTypeEdited, 7704 Objects: []*ObjectDiff{ 7705 { 7706 Type: DiffTypeAdded, 7707 Name: "Identity", 7708 Fields: []*FieldDiff{ 7709 { 7710 Type: DiffTypeAdded, 7711 Name: "Env", 7712 Old: "", 7713 New: "true", 7714 }, 7715 { 7716 Type: DiffTypeAdded, 7717 Name: "File", 7718 Old: "", 7719 New: "false", 7720 }, 7721 }, 7722 }, 7723 }, 7724 }, 7725 }, 7726 { 7727 Name: "Identity removed", 7728 Old: &Task{ 7729 Identity: &WorkloadIdentity{ 7730 Env: true, 7731 }, 7732 }, 7733 New: &Task{}, 7734 Expected: &TaskDiff{ 7735 Type: DiffTypeEdited, 7736 Objects: []*ObjectDiff{ 7737 { 7738 Type: DiffTypeDeleted, 7739 Name: "Identity", 7740 Fields: []*FieldDiff{ 7741 { 7742 Type: DiffTypeDeleted, 7743 Name: "Env", 7744 Old: "true", 7745 }, 7746 { 7747 Type: DiffTypeDeleted, 7748 Name: "File", 7749 Old: "false", 7750 }, 7751 }, 7752 }, 7753 }, 7754 }, 7755 }, 7756 { 7757 Name: "Identity modified", 7758 Old: &Task{ 7759 Identity: &WorkloadIdentity{ 7760 Env: true, 7761 }, 7762 }, 7763 New: &Task{ 7764 Identity: &WorkloadIdentity{ 7765 Env: true, 7766 File: true, 7767 }, 7768 }, 7769 Expected: &TaskDiff{ 7770 Type: DiffTypeEdited, 7771 Objects: []*ObjectDiff{ 7772 { 7773 Type: DiffTypeEdited, 7774 Name: "Identity", 7775 Fields: []*FieldDiff{ 7776 { 7777 Type: DiffTypeEdited, 7778 Name: "File", 7779 Old: "false", 7780 New: "true", 7781 }, 7782 }, 7783 }, 7784 }, 7785 }, 7786 }, 7787 } 7788 7789 for _, c := range cases { 7790 t.Run(c.Name, func(t *testing.T) { 7791 actual, err := c.Old.Diff(c.New, c.Contextual) 7792 if c.Error { 7793 require.Error(t, err) 7794 } else { 7795 require.NoError(t, err) 7796 require.Equal(t, c.Expected, actual) 7797 } 7798 }) 7799 } 7800 } 7801 7802 func TestServicesDiff(t *testing.T) { 7803 ci.Parallel(t) 7804 7805 cases := []struct { 7806 Name string 7807 Old, New []*Service 7808 Expected []*ObjectDiff 7809 Contextual bool 7810 }{ 7811 { 7812 Name: "No changes - empty", 7813 Contextual: true, 7814 Old: []*Service{}, 7815 New: []*Service{}, 7816 Expected: nil, 7817 }, 7818 { 7819 Name: "No changes", 7820 Contextual: true, 7821 Old: []*Service{ 7822 { 7823 Name: "webapp", 7824 PortLabel: "http", 7825 }, 7826 }, 7827 New: []*Service{ 7828 { 7829 Name: "webapp", 7830 PortLabel: "http", 7831 }, 7832 }, 7833 Expected: nil, 7834 }, 7835 { 7836 Name: "Detect changes", 7837 Contextual: true, 7838 Old: []*Service{ 7839 { 7840 Name: "webapp", 7841 PortLabel: "http", 7842 AddressMode: "host", 7843 Address: "a.example.com", 7844 EnableTagOverride: true, 7845 Tags: []string{"prod"}, 7846 CanaryTags: []string{"canary"}, 7847 }, 7848 }, 7849 New: []*Service{ 7850 { 7851 Name: "webapp-2", 7852 PortLabel: "https", 7853 AddressMode: "alloc", 7854 Address: "b.example.com", 7855 EnableTagOverride: false, 7856 Tags: []string{"prod", "dev"}, 7857 CanaryTags: []string{"qa"}, 7858 }, 7859 }, 7860 Expected: []*ObjectDiff{ 7861 { 7862 Type: DiffTypeEdited, 7863 Name: "Service", 7864 Fields: []*FieldDiff{ 7865 { 7866 Type: DiffTypeEdited, 7867 Name: "Address", 7868 Old: "a.example.com", 7869 New: "b.example.com", 7870 }, 7871 { 7872 Type: DiffTypeEdited, 7873 Name: "AddressMode", 7874 Old: "host", 7875 New: "alloc", 7876 }, 7877 { 7878 Type: DiffTypeEdited, 7879 Name: "EnableTagOverride", 7880 Old: "true", 7881 New: "false", 7882 }, 7883 { 7884 Type: DiffTypeEdited, 7885 Name: "Name", 7886 Old: "webapp", 7887 New: "webapp-2", 7888 }, 7889 { 7890 Type: DiffTypeNone, 7891 Name: "Namespace", 7892 }, 7893 { 7894 Type: DiffTypeNone, 7895 Name: "OnUpdate", 7896 }, 7897 { 7898 Type: DiffTypeEdited, 7899 Name: "PortLabel", 7900 Old: "http", 7901 New: "https", 7902 }, 7903 { 7904 Type: DiffTypeNone, 7905 Name: "Provider", 7906 }, 7907 { 7908 Type: DiffTypeNone, 7909 Name: "TaskName", 7910 }, 7911 }, 7912 Objects: []*ObjectDiff{ 7913 { 7914 Type: DiffTypeEdited, 7915 Name: "CanaryTags", 7916 Fields: []*FieldDiff{ 7917 { 7918 Type: DiffTypeAdded, 7919 Name: "CanaryTags", 7920 New: "qa", 7921 }, 7922 { 7923 Type: DiffTypeDeleted, 7924 Name: "CanaryTags", 7925 Old: "canary", 7926 }, 7927 }, 7928 }, 7929 { 7930 Type: DiffTypeAdded, 7931 Name: "Tags", 7932 Fields: []*FieldDiff{ 7933 { 7934 Type: DiffTypeAdded, 7935 Name: "Tags", 7936 New: "dev", 7937 }, 7938 { 7939 Type: DiffTypeNone, 7940 Name: "Tags", 7941 Old: "prod", 7942 New: "prod", 7943 }, 7944 }, 7945 }, 7946 }, 7947 }, 7948 }, 7949 }, 7950 { 7951 Name: "Service added", 7952 Contextual: true, 7953 Old: []*Service{}, 7954 New: []*Service{ 7955 { 7956 Name: "webapp", 7957 PortLabel: "http", 7958 }, 7959 }, 7960 Expected: []*ObjectDiff{ 7961 { 7962 Type: DiffTypeAdded, 7963 Name: "Service", 7964 Fields: []*FieldDiff{ 7965 { 7966 Type: DiffTypeNone, 7967 Name: "Address", 7968 }, 7969 { 7970 Type: DiffTypeNone, 7971 Name: "AddressMode", 7972 }, 7973 { 7974 Type: DiffTypeAdded, 7975 Name: "EnableTagOverride", 7976 New: "false", 7977 }, 7978 { 7979 Type: DiffTypeAdded, 7980 Name: "Name", 7981 New: "webapp", 7982 }, 7983 { 7984 Type: DiffTypeNone, 7985 Name: "Namespace", 7986 }, 7987 { 7988 Type: DiffTypeNone, 7989 Name: "OnUpdate", 7990 }, 7991 { 7992 Type: DiffTypeAdded, 7993 Name: "PortLabel", 7994 New: "http", 7995 }, 7996 { 7997 Type: DiffTypeNone, 7998 Name: "Provider", 7999 }, 8000 { 8001 Type: DiffTypeNone, 8002 Name: "TaskName", 8003 }, 8004 }, 8005 }, 8006 }, 8007 }, 8008 { 8009 Name: "Service added with same name", 8010 Contextual: true, 8011 Old: []*Service{ 8012 { 8013 Name: "webapp", 8014 PortLabel: "http", 8015 }, 8016 }, 8017 New: []*Service{ 8018 { 8019 Name: "webapp", 8020 PortLabel: "https", 8021 }, 8022 { 8023 Name: "webapp", 8024 PortLabel: "http", 8025 }, 8026 }, 8027 Expected: []*ObjectDiff{ 8028 { 8029 Type: DiffTypeAdded, 8030 Name: "Service", 8031 Fields: []*FieldDiff{ 8032 { 8033 Type: DiffTypeNone, 8034 Name: "Address", 8035 }, 8036 { 8037 Type: DiffTypeNone, 8038 Name: "AddressMode", 8039 }, 8040 { 8041 Type: DiffTypeAdded, 8042 Name: "EnableTagOverride", 8043 New: "false", 8044 }, 8045 { 8046 Type: DiffTypeAdded, 8047 Name: "Name", 8048 New: "webapp", 8049 }, 8050 { 8051 Type: DiffTypeNone, 8052 Name: "Namespace", 8053 }, 8054 { 8055 Type: DiffTypeNone, 8056 Name: "OnUpdate", 8057 }, 8058 { 8059 Type: DiffTypeAdded, 8060 Name: "PortLabel", 8061 New: "https", 8062 }, 8063 { 8064 Type: DiffTypeNone, 8065 Name: "Provider", 8066 }, 8067 { 8068 Type: DiffTypeNone, 8069 Name: "TaskName", 8070 }, 8071 }, 8072 }, 8073 }, 8074 }, 8075 { 8076 Name: "Modify port label of service with same name", 8077 Contextual: true, 8078 Old: []*Service{ 8079 { 8080 Name: "webapp", 8081 PortLabel: "http", 8082 }, 8083 { 8084 Name: "webapp", 8085 PortLabel: "https", 8086 }, 8087 }, 8088 New: []*Service{ 8089 { 8090 Name: "webapp", 8091 PortLabel: "https-redirect", 8092 }, 8093 { 8094 Name: "webapp", 8095 PortLabel: "https", 8096 }, 8097 }, 8098 Expected: []*ObjectDiff{ 8099 { 8100 Type: DiffTypeEdited, 8101 Name: "Service", 8102 Fields: []*FieldDiff{ 8103 { 8104 Type: DiffTypeNone, 8105 Name: "Address", 8106 }, 8107 { 8108 Type: DiffTypeNone, 8109 Name: "AddressMode", 8110 }, 8111 { 8112 Type: DiffTypeNone, 8113 Name: "EnableTagOverride", 8114 Old: "false", 8115 New: "false", 8116 }, 8117 { 8118 Type: DiffTypeNone, 8119 Name: "Name", 8120 Old: "webapp", 8121 New: "webapp", 8122 }, 8123 { 8124 Type: DiffTypeNone, 8125 Name: "Namespace", 8126 }, 8127 { 8128 Type: DiffTypeNone, 8129 Name: "OnUpdate", 8130 }, 8131 { 8132 Type: DiffTypeEdited, 8133 Name: "PortLabel", 8134 Old: "http", 8135 New: "https-redirect", 8136 }, { 8137 Type: DiffTypeNone, 8138 Name: "Provider", 8139 }, 8140 { 8141 Type: DiffTypeNone, 8142 Name: "TaskName", 8143 }, 8144 }, 8145 }, 8146 }, 8147 }, 8148 { 8149 Name: "Modify similar services", 8150 Contextual: true, 8151 Old: []*Service{ 8152 { 8153 Name: "webapp", 8154 PortLabel: "http", 8155 Tags: []string{"prod"}, 8156 }, 8157 { 8158 Name: "webapp", 8159 PortLabel: "http", 8160 Tags: []string{"dev"}, 8161 }, 8162 }, 8163 New: []*Service{ 8164 { 8165 Name: "webapp", 8166 PortLabel: "http", 8167 Tags: []string{"prod", "qa"}, 8168 }, 8169 { 8170 Name: "webapp", 8171 PortLabel: "http", 8172 Tags: []string{"dev"}, 8173 }, 8174 }, 8175 Expected: []*ObjectDiff{ 8176 { 8177 Type: DiffTypeEdited, 8178 Name: "Service", 8179 Fields: []*FieldDiff{ 8180 { 8181 Type: DiffTypeNone, 8182 Name: "Address", 8183 }, 8184 { 8185 Type: DiffTypeNone, 8186 Name: "AddressMode", 8187 }, 8188 { 8189 Type: DiffTypeNone, 8190 Name: "EnableTagOverride", 8191 Old: "false", 8192 New: "false", 8193 }, 8194 { 8195 Type: DiffTypeNone, 8196 Name: "Name", 8197 Old: "webapp", 8198 New: "webapp", 8199 }, 8200 { 8201 Type: DiffTypeNone, 8202 Name: "Namespace", 8203 }, 8204 { 8205 Type: DiffTypeNone, 8206 Name: "OnUpdate", 8207 }, 8208 { 8209 Type: DiffTypeNone, 8210 Name: "PortLabel", 8211 Old: "http", 8212 New: "http", 8213 }, 8214 { 8215 Type: DiffTypeNone, 8216 Name: "Provider", 8217 }, 8218 { 8219 Type: DiffTypeNone, 8220 Name: "TaskName", 8221 }, 8222 }, 8223 Objects: []*ObjectDiff{ 8224 { 8225 Type: DiffTypeAdded, 8226 Name: "Tags", 8227 Fields: []*FieldDiff{ 8228 { 8229 Type: DiffTypeAdded, 8230 Name: "Tags", 8231 New: "qa", 8232 }, 8233 { 8234 Type: DiffTypeNone, 8235 Name: "Tags", 8236 Old: "prod", 8237 New: "prod", 8238 }, 8239 }, 8240 }, 8241 }, 8242 }, 8243 }, 8244 }, 8245 { 8246 Name: "Service with different provider", 8247 Contextual: true, 8248 Old: []*Service{ 8249 { 8250 Name: "webapp", 8251 Provider: "nomad", 8252 PortLabel: "http", 8253 }, 8254 }, 8255 New: []*Service{ 8256 { 8257 Name: "webapp", 8258 Provider: "consul", 8259 PortLabel: "http", 8260 }, 8261 }, 8262 Expected: []*ObjectDiff{ 8263 { 8264 Type: DiffTypeEdited, 8265 Name: "Service", 8266 Fields: []*FieldDiff{ 8267 { 8268 Type: DiffTypeNone, 8269 Name: "Address", 8270 }, 8271 { 8272 Type: DiffTypeNone, 8273 Name: "AddressMode", 8274 }, 8275 { 8276 Type: DiffTypeNone, 8277 Name: "EnableTagOverride", 8278 Old: "false", 8279 New: "false", 8280 }, 8281 { 8282 Type: DiffTypeNone, 8283 Name: "Name", 8284 Old: "webapp", 8285 New: "webapp", 8286 }, 8287 { 8288 Type: DiffTypeNone, 8289 Name: "Namespace", 8290 }, 8291 { 8292 Type: DiffTypeNone, 8293 Name: "OnUpdate", 8294 }, 8295 { 8296 Type: DiffTypeNone, 8297 Name: "PortLabel", 8298 Old: "http", 8299 New: "http", 8300 }, 8301 { 8302 Type: DiffTypeEdited, 8303 Name: "Provider", 8304 Old: "nomad", 8305 New: "consul", 8306 }, 8307 { 8308 Type: DiffTypeNone, 8309 Name: "TaskName", 8310 }, 8311 }, 8312 }, 8313 }, 8314 }, 8315 { 8316 Name: "Service with different ingress tls", 8317 Contextual: false, 8318 Old: []*Service{ 8319 { 8320 Name: "webapp", 8321 Provider: "consul", 8322 PortLabel: "http", 8323 Connect: &ConsulConnect{ 8324 Gateway: &ConsulGateway{ 8325 Ingress: &ConsulIngressConfigEntry{}, 8326 }, 8327 }, 8328 }, 8329 }, 8330 New: []*Service{ 8331 { 8332 Name: "webapp", 8333 Provider: "consul", 8334 PortLabel: "http", 8335 Connect: &ConsulConnect{ 8336 Gateway: &ConsulGateway{ 8337 Ingress: &ConsulIngressConfigEntry{ 8338 TLS: &ConsulGatewayTLSConfig{ 8339 Enabled: true, 8340 TLSMinVersion: "TLSv1_2", 8341 CipherSuites: []string{"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256"}, 8342 }, 8343 }, 8344 }, 8345 }, 8346 }, 8347 }, 8348 Expected: []*ObjectDiff{ 8349 { 8350 Type: DiffTypeEdited, 8351 Name: "Service", 8352 Objects: []*ObjectDiff{ 8353 { 8354 Type: DiffTypeEdited, 8355 Name: "ConsulConnect", 8356 Objects: []*ObjectDiff{ 8357 { 8358 Type: DiffTypeEdited, 8359 Name: "Gateway", 8360 Objects: []*ObjectDiff{ 8361 { 8362 Type: DiffTypeEdited, 8363 Name: "Ingress", 8364 Objects: []*ObjectDiff{ 8365 { 8366 Type: DiffTypeAdded, 8367 Name: "TLS", 8368 Fields: []*FieldDiff{ 8369 { 8370 Type: DiffTypeAdded, 8371 Name: "Enabled", 8372 New: "true", 8373 }, 8374 { 8375 Type: DiffTypeAdded, 8376 Name: "TLSMinVersion", 8377 New: "TLSv1_2", 8378 }, 8379 }, 8380 Objects: []*ObjectDiff{ 8381 { 8382 Type: DiffTypeAdded, 8383 Name: "CipherSuites", 8384 Fields: []*FieldDiff{ 8385 { 8386 Type: DiffTypeAdded, 8387 Name: "CipherSuites", 8388 New: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", 8389 }, 8390 { 8391 Type: DiffTypeAdded, 8392 Name: "CipherSuites", 8393 New: "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", 8394 }, 8395 }, 8396 }, 8397 }, 8398 }, 8399 }, 8400 }, 8401 }, 8402 }, 8403 }, 8404 }, 8405 }, 8406 }, 8407 }, 8408 }, { 8409 Name: "SidecarService with different meta", 8410 Contextual: false, 8411 Old: []*Service{ 8412 { 8413 Name: "webapp", 8414 Provider: "consul", 8415 PortLabel: "http", 8416 Connect: &ConsulConnect{ 8417 SidecarService: &ConsulSidecarService{ 8418 Port: "http", 8419 Proxy: &ConsulProxy{}, 8420 Meta: map[string]string{ 8421 "foo": "qux", 8422 }, 8423 }, 8424 Gateway: &ConsulGateway{ 8425 Ingress: &ConsulIngressConfigEntry{}, 8426 }, 8427 }, 8428 }, 8429 }, 8430 New: []*Service{ 8431 { 8432 Name: "webapp", 8433 Provider: "consul", 8434 PortLabel: "http", 8435 Connect: &ConsulConnect{ 8436 SidecarService: &ConsulSidecarService{ 8437 Port: "http", 8438 Proxy: &ConsulProxy{}, 8439 Meta: map[string]string{ 8440 "foo": "var", 8441 "testKey": "testValue", 8442 }, 8443 }, 8444 Gateway: &ConsulGateway{ 8445 Ingress: &ConsulIngressConfigEntry{}, 8446 }, 8447 }, 8448 }, 8449 }, 8450 Expected: []*ObjectDiff{ 8451 { 8452 Type: DiffTypeEdited, 8453 Name: "Service", 8454 Objects: []*ObjectDiff{ 8455 { 8456 Type: "Edited", 8457 Name: "ConsulConnect", 8458 Fields: nil, 8459 Objects: []*ObjectDiff{ 8460 { 8461 Type: "Edited", 8462 Name: "SidecarService", 8463 Fields: []*FieldDiff{ 8464 { 8465 Type: "Edited", 8466 Name: "Meta[foo]", 8467 Old: "qux", 8468 New: "var", 8469 Annotations: nil, 8470 }, 8471 { 8472 Type: "Added", 8473 Name: "Meta[testKey]", 8474 Old: "", 8475 New: "testValue", 8476 Annotations: nil, 8477 }, 8478 }, 8479 Objects: nil, 8480 }, 8481 }, 8482 }, 8483 }, 8484 }, 8485 }, 8486 }, 8487 } 8488 8489 for _, c := range cases { 8490 t.Run(c.Name, func(t *testing.T) { 8491 actual := serviceDiffs(c.Old, c.New, c.Contextual) 8492 require.Equal(t, c.Expected, actual) 8493 }) 8494 } 8495 }