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