github.com/zppinho/prow@v0.0.0-20240510014325-1738badeb017/pkg/plugins/updateconfig/updateconfig_test.go (about) 1 /* 2 Copyright 2017 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package updateconfig 18 19 import ( 20 "context" 21 "strings" 22 "testing" 23 "testing/fstest" 24 25 "github.com/google/go-cmp/cmp" 26 "github.com/google/go-cmp/cmp/cmpopts" 27 "github.com/prometheus/client_golang/prometheus" 28 prometheus_model "github.com/prometheus/client_model/go" 29 "github.com/sirupsen/logrus" 30 coreapi "k8s.io/api/core/v1" 31 "k8s.io/apimachinery/pkg/api/equality" 32 "k8s.io/apimachinery/pkg/api/errors" 33 "k8s.io/apimachinery/pkg/api/meta" 34 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 35 "k8s.io/apimachinery/pkg/runtime" 36 "k8s.io/apimachinery/pkg/util/diff" 37 "k8s.io/apimachinery/pkg/util/sets" 38 "k8s.io/client-go/kubernetes/fake" 39 clienttesting "k8s.io/client-go/testing" 40 41 "sigs.k8s.io/prow/pkg/git/localgit" 42 "sigs.k8s.io/prow/pkg/git/v2" 43 "sigs.k8s.io/prow/pkg/github" 44 "sigs.k8s.io/prow/pkg/github/fakegithub" 45 "sigs.k8s.io/prow/pkg/kube" 46 "sigs.k8s.io/prow/pkg/plugins" 47 ) 48 49 const defaultNamespace = "default" 50 51 var defaultBranch = localgit.DefaultBranch("") 52 53 var remoteFiles = map[string]map[string]string{ 54 "prow/config.yaml": { 55 defaultBranch: "old-config", 56 "12345": "new-config", 57 }, 58 "prow/binary.yaml": { 59 defaultBranch: "old-binary\x00\xFF\xFF", 60 "12345": "new-binary\x00\xFF\xFF", 61 }, 62 "prow/binary.yml": { 63 defaultBranch: "old-binary\x00\xFF\xFF", 64 "12345": "new-binary\x00\xFF\xFF", 65 }, 66 "prow/becoming-binary.yaml": { 67 defaultBranch: "not-yet-binary", 68 "12345": "now-binary\x00\xFF\xFF", 69 }, 70 "prow/becoming-text.yaml": { 71 defaultBranch: "not-yet-text\x00\xFF\xFF", 72 "12345": "now-text", 73 }, 74 "prow/plugins.yaml": { 75 defaultBranch: "old-plugins", 76 "12345": "new-plugins", 77 }, 78 "boskos/resources.yaml": { 79 defaultBranch: "old-boskos-config", 80 "12345": "new-boskos-config", 81 }, 82 "config/foo.yaml": { 83 defaultBranch: "old-foo-config", 84 "12345": "new-foo-config", 85 }, 86 "config/bar.yaml": { 87 defaultBranch: "old-bar-config", 88 "12345": "new-bar-config", 89 }, 90 "dir/subdir/fejta.yaml": { 91 defaultBranch: "old-fejta-config", 92 "12345": "new-fejta-config", 93 }, 94 "dir/subdir/fejtaverse/krzyzacy.yaml": { 95 defaultBranch: "old-krzyzacy-config", 96 "12345": "new-krzyzacy-config", 97 }, 98 "dir/subdir/fejtaverse/fejtabot.yaml": { 99 "54321": "new-fejtabot-config", 100 }, 101 "dir/subdir/fejtaverse/sig-foo/added.yaml": { 102 "12345": "new-added-config", 103 }, 104 "dir/subdir/fejtaverse/sig-bar/removed.yaml": { 105 defaultBranch: "old-removed-config", 106 }, 107 "dir/subdir/even.yaml": { 108 "12345": "even SHA256", 109 }, 110 } 111 112 func setupLocalGitRepo(clients localgit.Clients, t *testing.T, org, repo string) git.ClientFactory { 113 lg, c, err := clients() 114 if err != nil { 115 t.Fatalf("Making local git repo: %v", err) 116 } 117 if err := lg.MakeFakeRepo(org, repo); err != nil { 118 t.Fatalf("Making fake repo: %v", err) 119 } 120 if err := lg.Checkout(org, repo, defaultBranch); err != nil { 121 t.Fatalf("Checkout new branch: %v", err) 122 } 123 if err := lg.AddCommit(org, repo, getFileMap(defaultBranch)); err != nil { 124 t.Fatalf("Add commit: %v", err) 125 } 126 if err := lg.CheckoutNewBranch(org, repo, "12345"); err != nil { 127 t.Fatalf("Checkout new branch: %v", err) 128 } 129 if err := lg.AddCommit(org, repo, getFileMap("12345")); err != nil { 130 t.Fatalf("Add commit: %v", err) 131 } 132 if err := lg.Checkout(org, repo, defaultBranch); err != nil { 133 t.Fatalf("Checkout new branch: %v", err) 134 } 135 if err := lg.CheckoutNewBranch(org, repo, "54321"); err != nil { 136 t.Fatalf("Checkout new branch: %v", err) 137 } 138 if err := lg.AddCommit(org, repo, getFileMap("54321")); err != nil { 139 t.Fatalf("Add commit: %v", err) 140 } 141 if err := lg.Checkout(org, repo, defaultBranch); err != nil { 142 t.Fatalf("Checkout new branch: %v", err) 143 } 144 return c 145 } 146 147 func TestUpdateConfigV2(t *testing.T) { 148 testUpdateConfig(localgit.NewV2, t) 149 } 150 151 func testUpdateConfig(clients localgit.Clients, t *testing.T) { 152 basicPR := github.PullRequest{ 153 Number: 1, 154 Base: github.PullRequestBranch{ 155 Repo: github.Repo{ 156 Owner: github.User{ 157 Login: "kubernetes", 158 }, 159 Name: "kubernetes", 160 }, 161 }, 162 User: github.User{ 163 Login: "foo", 164 }, 165 } 166 167 testcases := []struct { 168 name string 169 prAction github.PullRequestEventAction 170 merged bool 171 mergeCommit string 172 changes []github.PullRequestChange 173 existConfigMaps []runtime.Object 174 expectedConfigMaps []*coreapi.ConfigMap 175 config *plugins.ConfigUpdater 176 }{ 177 { 178 name: "Opened PR, no update", 179 prAction: github.PullRequestActionOpened, 180 merged: false, 181 changes: []github.PullRequestChange{ 182 { 183 Filename: "prow/config.yaml", 184 Additions: 1, 185 }, 186 }, 187 existConfigMaps: []runtime.Object{}, 188 }, 189 { 190 name: "Opened PR, not merged, no update", 191 merged: false, 192 changes: []github.PullRequestChange{ 193 { 194 Filename: "prow/config.yaml", 195 Additions: 1, 196 }, 197 }, 198 existConfigMaps: []runtime.Object{}, 199 }, 200 { 201 name: "Closed PR, no prow changes, no update", 202 prAction: github.PullRequestActionClosed, 203 merged: false, 204 changes: []github.PullRequestChange{ 205 { 206 Filename: "foo.txt", 207 Additions: 1, 208 }, 209 }, 210 existConfigMaps: []runtime.Object{}, 211 }, 212 { 213 name: "For whatever reason no merge commit SHA", 214 prAction: github.PullRequestActionClosed, 215 merged: true, 216 changes: []github.PullRequestChange{ 217 { 218 Filename: "prow/config.yaml", 219 Additions: 1, 220 }, 221 }, 222 existConfigMaps: []runtime.Object{}, 223 }, 224 { 225 name: "changed config.yaml, 1 update", 226 prAction: github.PullRequestActionClosed, 227 merged: true, 228 mergeCommit: "12345", 229 changes: []github.PullRequestChange{ 230 { 231 Filename: "prow/config.yaml", 232 Additions: 1, 233 }, 234 }, 235 existConfigMaps: []runtime.Object{ 236 &coreapi.ConfigMap{ 237 ObjectMeta: metav1.ObjectMeta{ 238 Name: "config", 239 Namespace: defaultNamespace, 240 Labels: map[string]string{ 241 "app.kubernetes.io/name": "prow", 242 "app.kubernetes.io/component": "updateconfig-plugin", 243 }, 244 }, 245 Data: map[string]string{ 246 "VERSION": "12345", 247 "config.yaml": "old-config", 248 }, 249 }, 250 }, 251 expectedConfigMaps: []*coreapi.ConfigMap{ 252 { 253 ObjectMeta: metav1.ObjectMeta{ 254 Name: "config", 255 Namespace: defaultNamespace, 256 Labels: map[string]string{ 257 "app.kubernetes.io/name": "prow", 258 "app.kubernetes.io/component": "updateconfig-plugin", 259 }, 260 }, 261 Data: map[string]string{ 262 "VERSION": "12345", 263 "config.yaml": "new-config", 264 }, 265 }, 266 }, 267 }, 268 { 269 name: "changed config.yaml, existed configmap, 1 update", 270 prAction: github.PullRequestActionClosed, 271 merged: true, 272 mergeCommit: "12345", 273 changes: []github.PullRequestChange{ 274 { 275 Filename: "prow/config.yaml", 276 Additions: 1, 277 }, 278 }, 279 existConfigMaps: []runtime.Object{ 280 &coreapi.ConfigMap{ 281 ObjectMeta: metav1.ObjectMeta{ 282 Name: "config", 283 Namespace: defaultNamespace, 284 Labels: map[string]string{ 285 "app.kubernetes.io/name": "prow", 286 "app.kubernetes.io/component": "updateconfig-plugin", 287 }, 288 }, 289 Data: map[string]string{ 290 "config.yaml": "old-config", 291 }, 292 }, 293 }, 294 expectedConfigMaps: []*coreapi.ConfigMap{ 295 { 296 ObjectMeta: metav1.ObjectMeta{ 297 Name: "config", 298 Namespace: defaultNamespace, 299 Labels: map[string]string{ 300 "app.kubernetes.io/name": "prow", 301 "app.kubernetes.io/component": "updateconfig-plugin", 302 }, 303 }, 304 Data: map[string]string{ 305 "config.yaml": "new-config", 306 "VERSION": "12345", 307 }, 308 }, 309 }, 310 }, 311 { 312 name: "changed plugins.yaml, 1 update with custom key", 313 prAction: github.PullRequestActionClosed, 314 merged: true, 315 mergeCommit: "12345", 316 changes: []github.PullRequestChange{ 317 { 318 Filename: "prow/plugins.yaml", 319 Additions: 1, 320 }, 321 }, 322 existConfigMaps: []runtime.Object{ 323 &coreapi.ConfigMap{ 324 ObjectMeta: metav1.ObjectMeta{ 325 Name: "plugins", 326 Namespace: defaultNamespace, 327 Labels: map[string]string{ 328 "app.kubernetes.io/name": "prow", 329 "app.kubernetes.io/component": "updateconfig-plugin", 330 }, 331 }, 332 Data: map[string]string{ 333 "test-key": "old-plugins", 334 }, 335 }, 336 }, 337 expectedConfigMaps: []*coreapi.ConfigMap{ 338 { 339 ObjectMeta: metav1.ObjectMeta{ 340 Name: "plugins", 341 Namespace: defaultNamespace, 342 Labels: map[string]string{ 343 "app.kubernetes.io/name": "prow", 344 "app.kubernetes.io/component": "updateconfig-plugin", 345 }, 346 }, 347 Data: map[string]string{ 348 "test-key": "new-plugins", 349 "VERSION": "12345", 350 }, 351 }, 352 }, 353 }, 354 { 355 name: "changed resources.yaml, 1 update with custom namespace", 356 prAction: github.PullRequestActionClosed, 357 merged: true, 358 mergeCommit: "12345", 359 changes: []github.PullRequestChange{ 360 { 361 Filename: "boskos/resources.yaml", 362 Additions: 1, 363 }, 364 }, 365 existConfigMaps: []runtime.Object{ 366 &coreapi.ConfigMap{ 367 ObjectMeta: metav1.ObjectMeta{ 368 Name: "boskos-config", 369 Namespace: "boskos", 370 Labels: map[string]string{ 371 "app.kubernetes.io/name": "prow", 372 "app.kubernetes.io/component": "updateconfig-plugin", 373 }, 374 }, 375 Data: map[string]string{ 376 "resources.yaml": "old-boskos-config", 377 }, 378 }, 379 }, 380 expectedConfigMaps: []*coreapi.ConfigMap{ 381 { 382 ObjectMeta: metav1.ObjectMeta{ 383 Name: "boskos-config", 384 Namespace: "boskos", 385 Labels: map[string]string{ 386 "app.kubernetes.io/name": "prow", 387 "app.kubernetes.io/component": "updateconfig-plugin", 388 }, 389 }, 390 Data: map[string]string{ 391 "resources.yaml": "new-boskos-config", 392 "VERSION": "12345", 393 }, 394 }, 395 }, 396 }, 397 { 398 name: "changed config.yaml, plugins.yaml and resources.yaml, 3 update", 399 prAction: github.PullRequestActionClosed, 400 merged: true, 401 mergeCommit: "12345", 402 changes: []github.PullRequestChange{ 403 { 404 Filename: "prow/plugins.yaml", 405 Additions: 1, 406 }, 407 { 408 Filename: "prow/config.yaml", 409 Additions: 1, 410 }, 411 { 412 Filename: "boskos/resources.yaml", 413 Additions: 1, 414 }, 415 }, 416 existConfigMaps: []runtime.Object{ 417 &coreapi.ConfigMap{ 418 ObjectMeta: metav1.ObjectMeta{ 419 Name: "config", 420 Namespace: defaultNamespace, 421 Labels: map[string]string{ 422 "app.kubernetes.io/name": "prow", 423 "app.kubernetes.io/component": "updateconfig-plugin", 424 }, 425 }, 426 Data: map[string]string{ 427 "config.yaml": "old-config", 428 }, 429 }, 430 &coreapi.ConfigMap{ 431 ObjectMeta: metav1.ObjectMeta{ 432 Name: "plugins", 433 Namespace: defaultNamespace, 434 Labels: map[string]string{ 435 "app.kubernetes.io/name": "prow", 436 "app.kubernetes.io/component": "updateconfig-plugin", 437 }, 438 }, 439 Data: map[string]string{ 440 "test-key": "old-plugins", 441 }, 442 }, 443 &coreapi.ConfigMap{ 444 ObjectMeta: metav1.ObjectMeta{ 445 Name: "boskos-config", 446 Namespace: "boskos", 447 }, 448 Data: map[string]string{ 449 "resources.yaml": "old-boskos-config", 450 }, 451 }, 452 }, 453 expectedConfigMaps: []*coreapi.ConfigMap{ 454 { 455 ObjectMeta: metav1.ObjectMeta{ 456 Name: "config", 457 Namespace: defaultNamespace, 458 Labels: map[string]string{ 459 "app.kubernetes.io/name": "prow", 460 "app.kubernetes.io/component": "updateconfig-plugin", 461 }, 462 }, 463 Data: map[string]string{ 464 "config.yaml": "new-config", 465 "VERSION": "12345", 466 }, 467 }, 468 { 469 ObjectMeta: metav1.ObjectMeta{ 470 Name: "plugins", 471 Namespace: defaultNamespace, 472 Labels: map[string]string{ 473 "app.kubernetes.io/name": "prow", 474 "app.kubernetes.io/component": "updateconfig-plugin", 475 }, 476 }, 477 Data: map[string]string{ 478 "test-key": "new-plugins", 479 "VERSION": "12345", 480 }, 481 }, 482 { 483 ObjectMeta: metav1.ObjectMeta{ 484 Name: "boskos-config", 485 Namespace: "boskos", 486 Labels: map[string]string{ 487 "app.kubernetes.io/name": "prow", 488 "app.kubernetes.io/component": "updateconfig-plugin", 489 }, 490 }, 491 Data: map[string]string{ 492 "resources.yaml": "new-boskos-config", 493 "VERSION": "12345", 494 }, 495 }, 496 }, 497 }, 498 { 499 name: "edited both config/foo.yaml and config/bar.yaml, 2 update", 500 prAction: github.PullRequestActionClosed, 501 merged: true, 502 mergeCommit: "12345", 503 changes: []github.PullRequestChange{ 504 { 505 Filename: "config/foo.yaml", 506 Additions: 1, 507 }, 508 { 509 Filename: "config/bar.yaml", 510 Additions: 1, 511 }, 512 }, 513 existConfigMaps: []runtime.Object{ 514 &coreapi.ConfigMap{ 515 ObjectMeta: metav1.ObjectMeta{ 516 Name: "multikey-config", 517 Namespace: defaultNamespace, 518 Labels: map[string]string{ 519 "app.kubernetes.io/name": "prow", 520 "app.kubernetes.io/component": "updateconfig-plugin", 521 }, 522 }, 523 Data: map[string]string{ 524 "foo.yaml": "old-foo-config", 525 "bar.yaml": "old-bar-config", 526 }, 527 }, 528 }, 529 expectedConfigMaps: []*coreapi.ConfigMap{ 530 { 531 ObjectMeta: metav1.ObjectMeta{ 532 Name: "multikey-config", 533 Namespace: defaultNamespace, 534 Labels: map[string]string{ 535 "app.kubernetes.io/name": "prow", 536 "app.kubernetes.io/component": "updateconfig-plugin", 537 }, 538 }, 539 Data: map[string]string{ 540 "foo.yaml": "new-foo-config", 541 "bar.yaml": "new-bar-config", 542 "VERSION": "12345", 543 }, 544 }, 545 }, 546 }, 547 { 548 name: "edited config/foo.yaml, 1 update", 549 prAction: github.PullRequestActionClosed, 550 merged: true, 551 mergeCommit: "12345", 552 changes: []github.PullRequestChange{ 553 { 554 Filename: "config/foo.yaml", 555 Status: "modified", 556 Additions: 1, 557 }, 558 }, 559 existConfigMaps: []runtime.Object{ 560 &coreapi.ConfigMap{ 561 ObjectMeta: metav1.ObjectMeta{ 562 Name: "multikey-config", 563 Namespace: defaultNamespace, 564 Labels: map[string]string{ 565 "app.kubernetes.io/name": "prow", 566 "app.kubernetes.io/component": "updateconfig-plugin", 567 }, 568 }, 569 Data: map[string]string{ 570 "foo.yaml": "old-foo-config", 571 "bar.yaml": "old-bar-config", 572 }, 573 }, 574 }, 575 expectedConfigMaps: []*coreapi.ConfigMap{ 576 { 577 ObjectMeta: metav1.ObjectMeta{ 578 Name: "multikey-config", 579 Namespace: defaultNamespace, 580 Labels: map[string]string{ 581 "app.kubernetes.io/name": "prow", 582 "app.kubernetes.io/component": "updateconfig-plugin", 583 }, 584 }, 585 Data: map[string]string{ 586 "foo.yaml": "new-foo-config", 587 "bar.yaml": "old-bar-config", 588 "VERSION": "12345", 589 }, 590 }, 591 }, 592 }, 593 { 594 name: "remove config/foo.yaml, 1 update", 595 prAction: github.PullRequestActionClosed, 596 merged: true, 597 mergeCommit: "12345", 598 changes: []github.PullRequestChange{ 599 { 600 Filename: "config/foo.yaml", 601 Status: "removed", 602 }, 603 }, 604 existConfigMaps: []runtime.Object{ 605 &coreapi.ConfigMap{ 606 ObjectMeta: metav1.ObjectMeta{ 607 Name: "multikey-config", 608 Namespace: defaultNamespace, 609 Labels: map[string]string{ 610 "app.kubernetes.io/name": "prow", 611 "app.kubernetes.io/component": "updateconfig-plugin", 612 }, 613 }, 614 Data: map[string]string{ 615 "foo.yaml": "old-foo-config", 616 "bar.yaml": "old-bar-config", 617 }, 618 }, 619 }, 620 expectedConfigMaps: []*coreapi.ConfigMap{ 621 { 622 ObjectMeta: metav1.ObjectMeta{ 623 Name: "multikey-config", 624 Namespace: defaultNamespace, 625 Labels: map[string]string{ 626 "app.kubernetes.io/name": "prow", 627 "app.kubernetes.io/component": "updateconfig-plugin", 628 }, 629 }, 630 Data: map[string]string{ 631 "bar.yaml": "old-bar-config", 632 "VERSION": "12345", 633 }, 634 }, 635 }, 636 }, 637 { 638 name: "edited dir/subdir/fejtaverse/krzyzacy.yaml, 1 update", 639 prAction: github.PullRequestActionClosed, 640 merged: true, 641 mergeCommit: "12345", 642 changes: []github.PullRequestChange{ 643 { 644 Filename: "dir/subdir/fejtaverse/krzyzacy.yaml", 645 Status: "modified", 646 Additions: 1, 647 }, 648 }, 649 existConfigMaps: []runtime.Object{ 650 &coreapi.ConfigMap{ 651 ObjectMeta: metav1.ObjectMeta{ 652 Name: "glob-config", 653 Namespace: defaultNamespace, 654 Labels: map[string]string{ 655 "app.kubernetes.io/name": "prow", 656 "app.kubernetes.io/component": "updateconfig-plugin", 657 }, 658 }, 659 Data: map[string]string{ 660 "fejta.yaml": "old-fejta-config", 661 "krzyzacy.yaml": "old-krzyzacy-config", 662 }, 663 }, 664 }, 665 expectedConfigMaps: []*coreapi.ConfigMap{ 666 { 667 ObjectMeta: metav1.ObjectMeta{ 668 Name: "glob-config", 669 Namespace: defaultNamespace, 670 Labels: map[string]string{ 671 "app.kubernetes.io/name": "prow", 672 "app.kubernetes.io/component": "updateconfig-plugin", 673 }, 674 }, 675 Data: map[string]string{ 676 "fejta.yaml": "old-fejta-config", 677 "krzyzacy.yaml": "new-krzyzacy-config", 678 "VERSION": "12345", 679 }, 680 }, 681 }, 682 }, 683 { 684 name: "renamed dir/subdir/fejtaverse/krzyzacy.yaml, 1 update", 685 prAction: github.PullRequestActionClosed, 686 merged: true, 687 mergeCommit: "54321", 688 changes: []github.PullRequestChange{ 689 { 690 Filename: "dir/subdir/fejtaverse/fejtabot.yaml", 691 PreviousFilename: "dir/subdir/fejtaverse/krzyzacy.yaml", 692 Status: "renamed", 693 Additions: 1, 694 }, 695 }, 696 existConfigMaps: []runtime.Object{ 697 &coreapi.ConfigMap{ 698 ObjectMeta: metav1.ObjectMeta{ 699 Name: "glob-config", 700 Namespace: defaultNamespace, 701 Labels: map[string]string{ 702 "app.kubernetes.io/name": "prow", 703 "app.kubernetes.io/component": "updateconfig-plugin", 704 }, 705 }, 706 Data: map[string]string{ 707 "krzyzacy.yaml": "old-krzyzacy-config", 708 }, 709 }, 710 }, 711 expectedConfigMaps: []*coreapi.ConfigMap{ 712 { 713 ObjectMeta: metav1.ObjectMeta{ 714 Name: "glob-config", 715 Namespace: defaultNamespace, 716 Labels: map[string]string{ 717 "app.kubernetes.io/name": "prow", 718 "app.kubernetes.io/component": "updateconfig-plugin", 719 }, 720 }, 721 Data: map[string]string{ 722 "fejtabot.yaml": "new-fejtabot-config", 723 "VERSION": "54321", 724 }, 725 }, 726 }, 727 }, 728 { 729 name: "Renamed with UseFullPathAsKey set, old entry gets deleted", 730 prAction: github.PullRequestActionClosed, 731 merged: true, 732 mergeCommit: "54321", 733 changes: []github.PullRequestChange{ 734 { 735 Filename: "dir/subdir/fejtaverse/fejtabot.yaml", 736 PreviousFilename: "dir/subdir/fejtaverse/krzyzacy.yaml", 737 Status: "renamed", 738 Additions: 1, 739 }, 740 }, 741 existConfigMaps: []runtime.Object{ 742 &coreapi.ConfigMap{ 743 ObjectMeta: metav1.ObjectMeta{ 744 Name: "glob-config", 745 Namespace: defaultNamespace, 746 Labels: map[string]string{ 747 "app.kubernetes.io/name": "prow", 748 "app.kubernetes.io/component": "updateconfig-plugin", 749 }, 750 }, 751 Data: map[string]string{ 752 "dir-subdir-fejtaverse-krzyzacy.yaml": "retired", 753 }, 754 }, 755 }, 756 expectedConfigMaps: []*coreapi.ConfigMap{ 757 { 758 ObjectMeta: metav1.ObjectMeta{ 759 Name: "config", 760 Namespace: defaultNamespace, 761 Labels: map[string]string{ 762 "app.kubernetes.io/name": "prow", 763 "app.kubernetes.io/component": "updateconfig-plugin", 764 }, 765 }, 766 Data: map[string]string{ 767 "dir-subdir-fejtaverse-fejtabot.yaml": "new-fejtabot-config", 768 "VERSION": "54321", 769 }, 770 }, 771 }, 772 config: &plugins.ConfigUpdater{ 773 Maps: map[string]plugins.ConfigMapSpec{ 774 "dir/subdir/**/*.yaml": { 775 Name: "config", 776 UseFullPathAsKey: true, 777 }, 778 }, 779 }, 780 }, 781 { 782 name: "add delete edit glob config, 3 update", 783 prAction: github.PullRequestActionClosed, 784 merged: true, 785 mergeCommit: "12345", 786 changes: []github.PullRequestChange{ 787 { 788 Filename: "dir/subdir/fejta.yaml", 789 Status: "modified", 790 Additions: 1, 791 }, 792 { 793 Filename: "dir/subdir/fejtaverse/sig-foo/added.yaml", 794 Status: "added", 795 Additions: 1, 796 }, 797 { 798 Filename: "dir/subdir/fejtaverse/sig-bar/removed.yaml", 799 Status: "removed", 800 }, 801 }, 802 existConfigMaps: []runtime.Object{ 803 &coreapi.ConfigMap{ 804 ObjectMeta: metav1.ObjectMeta{ 805 Name: "glob-config", 806 Namespace: defaultNamespace, 807 Labels: map[string]string{ 808 "app.kubernetes.io/name": "prow", 809 "app.kubernetes.io/component": "updateconfig-plugin", 810 }, 811 }, 812 Data: map[string]string{ 813 "fejta.yaml": "old-fejta-config", 814 "krzyzacy.yaml": "old-krzyzacy-config", 815 "removed.yaml": "old-removed-config", 816 }, 817 }, 818 }, 819 expectedConfigMaps: []*coreapi.ConfigMap{ 820 { 821 ObjectMeta: metav1.ObjectMeta{ 822 Name: "glob-config", 823 Namespace: defaultNamespace, 824 Labels: map[string]string{ 825 "app.kubernetes.io/name": "prow", 826 "app.kubernetes.io/component": "updateconfig-plugin", 827 }, 828 }, 829 Data: map[string]string{ 830 "fejta.yaml": "new-fejta-config", 831 "krzyzacy.yaml": "old-krzyzacy-config", 832 "added.yaml": "new-added-config", 833 "VERSION": "12345", 834 }, 835 }, 836 }, 837 }, 838 { 839 name: "config changes without a backing configmap causes creation", 840 prAction: github.PullRequestActionClosed, 841 merged: true, 842 mergeCommit: "12345", 843 changes: []github.PullRequestChange{ 844 { 845 Filename: "prow/config.yaml", 846 Status: "modified", 847 Additions: 1, 848 }, 849 }, 850 existConfigMaps: []runtime.Object{}, 851 expectedConfigMaps: []*coreapi.ConfigMap{ 852 { 853 ObjectMeta: metav1.ObjectMeta{ 854 Name: "config", 855 Namespace: defaultNamespace, 856 Labels: map[string]string{ 857 "app.kubernetes.io/name": "prow", 858 "app.kubernetes.io/component": "updateconfig-plugin", 859 }, 860 }, 861 Data: map[string]string{ 862 "config.yaml": "new-config", 863 "VERSION": "12345", 864 }, 865 }, 866 }, 867 }, 868 { 869 name: "gzips all content if the top level gzip flag is set", 870 prAction: github.PullRequestActionClosed, 871 merged: true, 872 mergeCommit: "12345", 873 changes: []github.PullRequestChange{ 874 { 875 Filename: "prow/config.yaml", 876 Status: "modified", 877 Additions: 1, 878 }, 879 }, 880 existConfigMaps: []runtime.Object{}, 881 expectedConfigMaps: []*coreapi.ConfigMap{ 882 { 883 ObjectMeta: metav1.ObjectMeta{ 884 Name: "config", 885 Namespace: defaultNamespace, 886 Labels: map[string]string{ 887 "app.kubernetes.io/name": "prow", 888 "app.kubernetes.io/component": "updateconfig-plugin", 889 }, 890 }, 891 BinaryData: map[string][]byte{ 892 "config.yaml": {31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 202, 75, 45, 215, 77, 206, 207, 75, 203, 76, 7, 4, 0, 0, 255, 255, 84, 214, 231, 87, 10, 0, 0, 0}, 893 }, 894 Data: map[string]string{ 895 "VERSION": "12345", 896 }, 897 }, 898 }, 899 config: &plugins.ConfigUpdater{ 900 GZIP: true, 901 Maps: map[string]plugins.ConfigMapSpec{ 902 "prow/config.yaml": { 903 Name: "config", 904 }, 905 "prow/plugins.yaml": { 906 Name: "plugins", 907 Key: "test-key", 908 }, 909 }, 910 }, 911 }, 912 { 913 name: "gzips all content except one marked false if the top level gzip flag is set", 914 prAction: github.PullRequestActionClosed, 915 merged: true, 916 mergeCommit: "12345", 917 changes: []github.PullRequestChange{ 918 { 919 Filename: "prow/config.yaml", 920 Status: "modified", 921 Additions: 1, 922 }, 923 { 924 Filename: "prow/plugins.yaml", 925 Status: "modified", 926 Additions: 1, 927 }, 928 }, 929 existConfigMaps: []runtime.Object{}, 930 expectedConfigMaps: []*coreapi.ConfigMap{ 931 { 932 ObjectMeta: metav1.ObjectMeta{ 933 Name: "config", 934 Namespace: defaultNamespace, 935 Labels: map[string]string{ 936 "app.kubernetes.io/name": "prow", 937 "app.kubernetes.io/component": "updateconfig-plugin", 938 }, 939 }, 940 BinaryData: map[string][]byte{ 941 "config.yaml": {31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 202, 75, 45, 215, 77, 206, 207, 75, 203, 76, 7, 4, 0, 0, 255, 255, 84, 214, 231, 87, 10, 0, 0, 0}, 942 }, 943 Data: map[string]string{ 944 "VERSION": "12345", 945 }, 946 }, 947 { 948 ObjectMeta: metav1.ObjectMeta{ 949 Name: "plugins", 950 Namespace: defaultNamespace, 951 Labels: map[string]string{ 952 "app.kubernetes.io/name": "prow", 953 "app.kubernetes.io/component": "updateconfig-plugin", 954 }, 955 }, 956 Data: map[string]string{ 957 "plugins.yaml": "new-plugins", 958 "VERSION": "12345", 959 }, 960 }, 961 }, 962 config: &plugins.ConfigUpdater{ 963 GZIP: true, 964 Maps: map[string]plugins.ConfigMapSpec{ 965 "prow/config.yaml": { 966 Name: "config", 967 }, 968 "prow/plugins.yaml": { 969 Name: "plugins", 970 GZIP: boolPtr(false), 971 }, 972 }, 973 }, 974 }, 975 { 976 name: "gzips only one marked file if the top level gzip flag is set to false", 977 prAction: github.PullRequestActionClosed, 978 merged: true, 979 mergeCommit: "12345", 980 changes: []github.PullRequestChange{ 981 { 982 Filename: "prow/config.yaml", 983 Status: "modified", 984 Additions: 1, 985 }, 986 { 987 Filename: "prow/plugins.yaml", 988 Status: "modified", 989 Additions: 1, 990 }, 991 }, 992 existConfigMaps: []runtime.Object{}, 993 expectedConfigMaps: []*coreapi.ConfigMap{ 994 { 995 ObjectMeta: metav1.ObjectMeta{ 996 Name: "config", 997 Namespace: defaultNamespace, 998 Labels: map[string]string{ 999 "app.kubernetes.io/name": "prow", 1000 "app.kubernetes.io/component": "updateconfig-plugin", 1001 }, 1002 }, 1003 BinaryData: map[string][]byte{ 1004 "config.yaml": {31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 202, 75, 45, 215, 77, 206, 207, 75, 203, 76, 7, 4, 0, 0, 255, 255, 84, 214, 231, 87, 10, 0, 0, 0}, 1005 }, 1006 Data: map[string]string{ 1007 "VERSION": "12345", 1008 }, 1009 }, 1010 { 1011 ObjectMeta: metav1.ObjectMeta{ 1012 Name: "plugins", 1013 Namespace: defaultNamespace, 1014 Labels: map[string]string{ 1015 "app.kubernetes.io/name": "prow", 1016 "app.kubernetes.io/component": "updateconfig-plugin", 1017 }, 1018 }, 1019 Data: map[string]string{ 1020 "plugins.yaml": "new-plugins", 1021 "VERSION": "12345", 1022 }, 1023 }, 1024 }, 1025 config: &plugins.ConfigUpdater{ 1026 GZIP: false, 1027 Maps: map[string]plugins.ConfigMapSpec{ 1028 "prow/config.yaml": { 1029 Name: "config", 1030 GZIP: boolPtr(true), 1031 }, 1032 "prow/plugins.yaml": { 1033 Name: "plugins", 1034 }, 1035 }, 1036 }, 1037 }, 1038 { 1039 name: "adds both binary and text keys for a single configmap", 1040 prAction: github.PullRequestActionClosed, 1041 merged: true, 1042 mergeCommit: "12345", 1043 changes: []github.PullRequestChange{ 1044 { 1045 Filename: "prow/config.yaml", 1046 Status: "modified", 1047 Additions: 1, 1048 }, 1049 { 1050 Filename: "prow/binary.yaml", 1051 Status: "modified", 1052 Additions: 1, 1053 }, 1054 }, 1055 existConfigMaps: []runtime.Object{}, 1056 expectedConfigMaps: []*coreapi.ConfigMap{ 1057 { 1058 ObjectMeta: metav1.ObjectMeta{ 1059 Name: "config", 1060 Namespace: defaultNamespace, 1061 Labels: map[string]string{ 1062 "app.kubernetes.io/name": "prow", 1063 "app.kubernetes.io/component": "updateconfig-plugin", 1064 }, 1065 }, 1066 Data: map[string]string{ 1067 "config.yaml": "new-config", 1068 "VERSION": "12345", 1069 }, 1070 BinaryData: map[string][]byte{ 1071 "binary.yaml": []byte("new-binary\x00\xFF\xFF"), 1072 }, 1073 }, 1074 }, 1075 config: &plugins.ConfigUpdater{ 1076 Maps: map[string]plugins.ConfigMapSpec{ 1077 "prow/*.yaml": { 1078 Name: "config", 1079 }, 1080 }, 1081 }, 1082 }, 1083 { 1084 name: "both yaml and yml", 1085 prAction: github.PullRequestActionClosed, 1086 merged: true, 1087 mergeCommit: "12345", 1088 changes: []github.PullRequestChange{ 1089 { 1090 Filename: "prow/config.yaml", 1091 Status: "modified", 1092 Additions: 1, 1093 }, 1094 { 1095 Filename: "prow/binary.yml", 1096 Status: "modified", 1097 Additions: 1, 1098 }, 1099 }, 1100 existConfigMaps: []runtime.Object{}, 1101 expectedConfigMaps: []*coreapi.ConfigMap{ 1102 { 1103 ObjectMeta: metav1.ObjectMeta{ 1104 Name: "config", 1105 Namespace: defaultNamespace, 1106 Labels: map[string]string{ 1107 "app.kubernetes.io/name": "prow", 1108 "app.kubernetes.io/component": "updateconfig-plugin", 1109 }, 1110 }, 1111 Data: map[string]string{ 1112 "config.yaml": "new-config", 1113 "VERSION": "12345", 1114 }, 1115 BinaryData: map[string][]byte{ 1116 "binary.yml": []byte("new-binary\x00\xFF\xFF"), 1117 }, 1118 }, 1119 }, 1120 config: &plugins.ConfigUpdater{ 1121 Maps: map[string]plugins.ConfigMapSpec{ 1122 "prow/*.{yaml,yml}": { 1123 Name: "config", 1124 }, 1125 }, 1126 }, 1127 }, 1128 { 1129 name: "converts a text key to a binary key when it becomes binary", 1130 prAction: github.PullRequestActionClosed, 1131 merged: true, 1132 mergeCommit: "12345", 1133 changes: []github.PullRequestChange{ 1134 { 1135 Filename: "prow/becoming-binary.yaml", 1136 Status: "modified", 1137 Additions: 1, 1138 }, 1139 }, 1140 existConfigMaps: []runtime.Object{ 1141 &coreapi.ConfigMap{ 1142 ObjectMeta: metav1.ObjectMeta{ 1143 Name: "config", 1144 Namespace: defaultNamespace, 1145 Labels: map[string]string{ 1146 "app.kubernetes.io/name": "prow", 1147 "app.kubernetes.io/component": "updateconfig-plugin", 1148 }, 1149 }, 1150 Data: map[string]string{ 1151 "becoming-binary.yaml": "not-yet-binary", 1152 }, 1153 }, 1154 }, 1155 expectedConfigMaps: []*coreapi.ConfigMap{ 1156 { 1157 ObjectMeta: metav1.ObjectMeta{ 1158 Name: "config", 1159 Namespace: defaultNamespace, 1160 Labels: map[string]string{ 1161 "app.kubernetes.io/name": "prow", 1162 "app.kubernetes.io/component": "updateconfig-plugin", 1163 }, 1164 }, 1165 BinaryData: map[string][]byte{ 1166 "becoming-binary.yaml": []byte("now-binary\x00\xFF\xFF"), 1167 }, 1168 Data: map[string]string{ 1169 "VERSION": "12345", 1170 }, 1171 }, 1172 }, 1173 config: &plugins.ConfigUpdater{ 1174 Maps: map[string]plugins.ConfigMapSpec{ 1175 "prow/*.yaml": { 1176 Name: "config", 1177 }, 1178 }, 1179 }, 1180 }, 1181 { 1182 name: "converts a binary key to a text key when it becomes text", 1183 prAction: github.PullRequestActionClosed, 1184 merged: true, 1185 mergeCommit: "12345", 1186 changes: []github.PullRequestChange{ 1187 { 1188 Filename: "prow/becoming-text.yaml", 1189 Status: "modified", 1190 Additions: 1, 1191 }, 1192 }, 1193 existConfigMaps: []runtime.Object{ 1194 &coreapi.ConfigMap{ 1195 ObjectMeta: metav1.ObjectMeta{ 1196 Name: "config", 1197 Namespace: defaultNamespace, 1198 Labels: map[string]string{ 1199 "app.kubernetes.io/name": "prow", 1200 "app.kubernetes.io/component": "updateconfig-plugin", 1201 }, 1202 }, 1203 BinaryData: map[string][]byte{ 1204 "becoming-text.yaml": []byte("not-yet-text\x00\xFF\xFF"), 1205 }, 1206 }, 1207 }, 1208 expectedConfigMaps: []*coreapi.ConfigMap{ 1209 { 1210 ObjectMeta: metav1.ObjectMeta{ 1211 Name: "config", 1212 Namespace: defaultNamespace, 1213 Labels: map[string]string{ 1214 "app.kubernetes.io/name": "prow", 1215 "app.kubernetes.io/component": "updateconfig-plugin", 1216 }, 1217 }, 1218 Data: map[string]string{ 1219 "becoming-text.yaml": "now-text", 1220 "VERSION": "12345", 1221 }, 1222 BinaryData: map[string][]uint8{}, 1223 }, 1224 }, 1225 config: &plugins.ConfigUpdater{ 1226 Maps: map[string]plugins.ConfigMapSpec{ 1227 "prow/*.yaml": { 1228 Name: "config", 1229 }, 1230 }, 1231 }, 1232 }, 1233 { 1234 name: "simultaneously converts text to binary and binary to text", 1235 prAction: github.PullRequestActionClosed, 1236 merged: true, 1237 mergeCommit: "12345", 1238 changes: []github.PullRequestChange{ 1239 { 1240 Filename: "prow/becoming-text.yaml", 1241 Status: "modified", 1242 Additions: 1, 1243 }, 1244 { 1245 Filename: "prow/becoming-binary.yaml", 1246 Status: "modified", 1247 Additions: 1, 1248 }, 1249 }, 1250 existConfigMaps: []runtime.Object{ 1251 &coreapi.ConfigMap{ 1252 ObjectMeta: metav1.ObjectMeta{ 1253 Name: "config", 1254 Namespace: defaultNamespace, 1255 Labels: map[string]string{ 1256 "app.kubernetes.io/name": "prow", 1257 "app.kubernetes.io/component": "updateconfig-plugin", 1258 }, 1259 }, 1260 BinaryData: map[string][]byte{ 1261 "becoming-text.yaml": []byte("not-yet-text\x00\xFF\xFF"), 1262 }, 1263 Data: map[string]string{ 1264 "becoming-binary.yaml": "not-yet-binary", 1265 }, 1266 }, 1267 }, 1268 expectedConfigMaps: []*coreapi.ConfigMap{ 1269 { 1270 ObjectMeta: metav1.ObjectMeta{ 1271 Name: "config", 1272 Namespace: defaultNamespace, 1273 Labels: map[string]string{ 1274 "app.kubernetes.io/name": "prow", 1275 "app.kubernetes.io/component": "updateconfig-plugin", 1276 }, 1277 }, 1278 BinaryData: map[string][]byte{ 1279 "becoming-binary.yaml": []byte("now-binary\x00\xFF\xFF"), 1280 }, 1281 Data: map[string]string{ 1282 "becoming-text.yaml": "now-text", 1283 "VERSION": "12345", 1284 }, 1285 }, 1286 }, 1287 config: &plugins.ConfigUpdater{ 1288 Maps: map[string]plugins.ConfigMapSpec{ 1289 "prow/*.yaml": { 1290 Name: "config", 1291 }, 1292 }, 1293 }, 1294 }, 1295 { 1296 name: "correctly converts to binary when gzipping", 1297 prAction: github.PullRequestActionClosed, 1298 merged: true, 1299 mergeCommit: "12345", 1300 changes: []github.PullRequestChange{ 1301 { 1302 Filename: "prow/config.yaml", 1303 Status: "modified", 1304 Additions: 1, 1305 }, 1306 }, 1307 existConfigMaps: []runtime.Object{ 1308 &coreapi.ConfigMap{ 1309 ObjectMeta: metav1.ObjectMeta{ 1310 Name: "config", 1311 Namespace: defaultNamespace, 1312 Labels: map[string]string{ 1313 "app.kubernetes.io/name": "prow", 1314 "app.kubernetes.io/component": "updateconfig-plugin", 1315 }, 1316 }, 1317 Data: map[string]string{ 1318 "config.yaml": "old-config", 1319 }, 1320 }, 1321 }, 1322 expectedConfigMaps: []*coreapi.ConfigMap{ 1323 { 1324 ObjectMeta: metav1.ObjectMeta{ 1325 Name: "config", 1326 Namespace: defaultNamespace, 1327 Labels: map[string]string{ 1328 "app.kubernetes.io/name": "prow", 1329 "app.kubernetes.io/component": "updateconfig-plugin", 1330 }, 1331 }, 1332 BinaryData: map[string][]byte{ 1333 "config.yaml": {31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 202, 75, 45, 215, 77, 206, 207, 75, 203, 76, 7, 4, 0, 0, 255, 255, 84, 214, 231, 87, 10, 0, 0, 0}, 1334 }, 1335 Data: map[string]string{ 1336 "VERSION": "12345", 1337 }, 1338 }, 1339 }, 1340 config: &plugins.ConfigUpdater{ 1341 GZIP: true, 1342 Maps: map[string]plugins.ConfigMapSpec{ 1343 "prow/*.yaml": { 1344 Name: "config", 1345 }, 1346 }, 1347 }, 1348 }, 1349 { 1350 name: "correctly converts to text when ungzipping", 1351 prAction: github.PullRequestActionClosed, 1352 merged: true, 1353 mergeCommit: "12345", 1354 changes: []github.PullRequestChange{ 1355 { 1356 Filename: "prow/config.yaml", 1357 Status: "modified", 1358 Additions: 1, 1359 }, 1360 }, 1361 existConfigMaps: []runtime.Object{ 1362 &coreapi.ConfigMap{ 1363 ObjectMeta: metav1.ObjectMeta{ 1364 Name: "config", 1365 Namespace: defaultNamespace, 1366 Labels: map[string]string{ 1367 "app.kubernetes.io/name": "prow", 1368 "app.kubernetes.io/component": "updateconfig-plugin", 1369 }, 1370 }, 1371 BinaryData: map[string][]byte{ 1372 "config.yaml": {31, 139, 8, 0, 0, 0, 0, 0, 0, 255, 202, 75, 45, 215, 77, 206, 207, 75, 203, 76, 7, 4, 0, 0, 255, 255, 84, 214, 231, 87, 10, 0, 0, 0}, 1373 }, 1374 }, 1375 }, 1376 expectedConfigMaps: []*coreapi.ConfigMap{ 1377 { 1378 ObjectMeta: metav1.ObjectMeta{ 1379 Name: "config", 1380 Namespace: defaultNamespace, 1381 Labels: map[string]string{ 1382 "app.kubernetes.io/name": "prow", 1383 "app.kubernetes.io/component": "updateconfig-plugin", 1384 }, 1385 }, 1386 Data: map[string]string{ 1387 "config.yaml": "new-config", 1388 "VERSION": "12345", 1389 }, 1390 }, 1391 }, 1392 config: &plugins.ConfigUpdater{ 1393 GZIP: false, 1394 Maps: map[string]plugins.ConfigMapSpec{ 1395 "prow/*.yaml": { 1396 Name: "config", 1397 }, 1398 }, 1399 }, 1400 }, 1401 { 1402 name: "Uses the full path slash-separated when UseFullPathAsKey is set", 1403 prAction: github.PullRequestActionClosed, 1404 merged: true, 1405 mergeCommit: "12345", 1406 changes: []github.PullRequestChange{ 1407 { 1408 Filename: "prow/config.yaml", 1409 Status: "modified", 1410 Additions: 1, 1411 }, 1412 }, 1413 expectedConfigMaps: []*coreapi.ConfigMap{ 1414 { 1415 ObjectMeta: metav1.ObjectMeta{ 1416 Name: "config", 1417 Namespace: defaultNamespace, 1418 Labels: map[string]string{ 1419 "app.kubernetes.io/name": "prow", 1420 "app.kubernetes.io/component": "updateconfig-plugin", 1421 }, 1422 }, 1423 Data: map[string]string{ 1424 "prow-config.yaml": "new-config", 1425 "VERSION": "12345", 1426 }, 1427 }, 1428 }, 1429 config: &plugins.ConfigUpdater{ 1430 GZIP: false, 1431 Maps: map[string]plugins.ConfigMapSpec{ 1432 "prow/*.yaml": { 1433 Name: "config", 1434 UseFullPathAsKey: true, 1435 }, 1436 }, 1437 }, 1438 }, 1439 { 1440 name: "Partitioned ConfigMaps actually partition", 1441 prAction: github.PullRequestActionClosed, 1442 merged: true, 1443 mergeCommit: "12345", 1444 changes: []github.PullRequestChange{ 1445 { 1446 Filename: "dir/subdir/fejta.yaml", 1447 Status: "added", 1448 Additions: 1, 1449 }, 1450 { 1451 Filename: "dir/subdir/fejtaverse/sig-foo/added.yaml", 1452 Status: "added", 1453 Additions: 1, 1454 }, 1455 { 1456 Filename: "dir/subdir/even.yaml", 1457 Status: "added", 1458 Additions: 1, 1459 }, 1460 }, 1461 expectedConfigMaps: []*coreapi.ConfigMap{ 1462 { 1463 ObjectMeta: metav1.ObjectMeta{ 1464 Name: "job-config-part-1", 1465 Namespace: defaultNamespace, 1466 Labels: map[string]string{ 1467 "app.kubernetes.io/name": "prow", 1468 "app.kubernetes.io/component": "updateconfig-plugin", 1469 }, 1470 }, 1471 Data: map[string]string{ 1472 "even.yaml": "even SHA256", 1473 "VERSION": "12345", 1474 }, 1475 }, 1476 { 1477 ObjectMeta: metav1.ObjectMeta{ 1478 Name: "job-config-part-2", 1479 Namespace: defaultNamespace, 1480 Labels: map[string]string{ 1481 "app.kubernetes.io/name": "prow", 1482 "app.kubernetes.io/component": "updateconfig-plugin", 1483 }, 1484 }, 1485 Data: map[string]string{ 1486 "fejta.yaml": "new-fejta-config", 1487 "added.yaml": "new-added-config", 1488 "VERSION": "12345", 1489 }, 1490 }, 1491 }, 1492 config: &plugins.ConfigUpdater{ 1493 Maps: map[string]plugins.ConfigMapSpec{ 1494 "dir/**/*.yaml": { 1495 PartitionedNames: []string{"job-config-part-1", "job-config-part-2"}, 1496 }, 1497 }, 1498 }, 1499 }, 1500 } 1501 1502 for _, tc := range testcases { 1503 log := logrus.WithField("plugin", pluginName) 1504 event := github.PullRequestEvent{ 1505 Action: tc.prAction, 1506 Number: basicPR.Number, 1507 PullRequest: basicPR, 1508 } 1509 event.PullRequest.Merged = tc.merged 1510 if tc.mergeCommit != "" { 1511 event.PullRequest.MergeSHA = &tc.mergeCommit 1512 } 1513 1514 fgc := fakegithub.NewFakeClient() 1515 fgc.PullRequests = map[int]*github.PullRequest{ 1516 basicPR.Number: &basicPR, 1517 } 1518 fgc.PullRequestChanges = map[int][]github.PullRequestChange{ 1519 basicPR.Number: tc.changes, 1520 } 1521 fgc.IssueComments = map[int][]github.IssueComment{} 1522 fkc := fake.NewSimpleClientset(tc.existConfigMaps...) 1523 1524 m := tc.config 1525 if m == nil { 1526 m = &plugins.ConfigUpdater{ 1527 Maps: map[string]plugins.ConfigMapSpec{ 1528 "prow/config.yaml": { 1529 Name: "config", 1530 }, 1531 "prow/plugins.yaml": { 1532 Name: "plugins", 1533 Key: "test-key", 1534 }, 1535 "boskos/resources.yaml": { 1536 Name: "boskos-config", 1537 Clusters: map[string][]string{"default": {"boskos"}}, 1538 }, 1539 "config/foo.yaml": { 1540 Name: "multikey-config", 1541 }, 1542 "config/bar.yaml": { 1543 Name: "multikey-config", 1544 }, 1545 "dir/subdir/**/*.yaml": { 1546 Name: "glob-config", 1547 }, 1548 }, 1549 } 1550 } 1551 m.SetDefaults() 1552 1553 org := event.PullRequest.Base.Repo.Owner.Login 1554 repo := event.PullRequest.Base.Repo.Name 1555 c := setupLocalGitRepo(clients, t, org, repo) 1556 1557 if err := handle(fgc, c, fkc.CoreV1(), nil, defaultNamespace, log, event, *m, nil); err != nil { 1558 t.Errorf("%s: unexpected error handling: %s", tc.name, err) 1559 continue 1560 } 1561 1562 modifiedConfigMaps := sets.New[string]() 1563 for _, action := range fkc.Fake.Actions() { 1564 var obj runtime.Object 1565 switch action := action.(type) { 1566 case clienttesting.CreateActionImpl: 1567 obj = action.Object 1568 case clienttesting.UpdateActionImpl: 1569 obj = action.Object 1570 default: 1571 continue 1572 } 1573 objectMeta, err := meta.Accessor(obj) 1574 if err != nil { 1575 t.Fatalf("%s: client saw an action for something that wasn't an object: %v", tc.name, err) 1576 } 1577 modifiedConfigMaps.Insert(objectMeta.GetName()) 1578 } 1579 1580 if tc.expectedConfigMaps != nil { 1581 if len(fgc.IssueComments[basicPR.Number]) != 1 { 1582 t.Errorf("%s: Expect 1 comment, actually got %d", tc.name, len(fgc.IssueComments[basicPR.Number])) 1583 } else { 1584 comment := fgc.IssueComments[basicPR.Number][0].Body 1585 if !strings.Contains(comment, "Updated the") { 1586 t.Errorf("%s: missing Updated the from %s", tc.name, comment) 1587 } 1588 for _, configMap := range tc.expectedConfigMaps { 1589 if modifiedConfigMaps.Has(configMap.Name) { 1590 if !strings.Contains(comment, configMap.Name) { 1591 t.Errorf("%s: missing %s from %s", tc.name, configMap.Name, comment) 1592 } 1593 } else if strings.Contains(comment, configMap.Name) { 1594 t.Errorf("%s: should not contain %s in %s", tc.name, configMap.Name, comment) 1595 } 1596 } 1597 } 1598 } 1599 1600 expectedConfigMaps := sets.New[string]() 1601 for _, configMap := range tc.expectedConfigMaps { 1602 expectedConfigMaps.Insert(configMap.Name) 1603 } 1604 if missing := expectedConfigMaps.Difference(modifiedConfigMaps); missing.Len() > 0 { 1605 t.Errorf("%s: did not update expected configmaps: %v", tc.name, sets.List(missing)) 1606 } 1607 if extra := modifiedConfigMaps.Difference(expectedConfigMaps); extra.Len() > 0 { 1608 t.Errorf("%s: found unexpectedly updated configmaps: %v", tc.name, sets.List(extra)) 1609 } 1610 1611 for _, expected := range tc.expectedConfigMaps { 1612 actual, err := fkc.CoreV1().ConfigMaps(expected.Namespace).Get(context.TODO(), expected.Name, metav1.GetOptions{}) 1613 if err != nil && errors.IsNotFound(err) { 1614 t.Errorf("%s: Should have updated or created configmap for '%s'", tc.name, expected) 1615 } else if !equality.Semantic.DeepEqual(expected, actual) { 1616 t.Errorf("%s: incorrect ConfigMap state after update: %v", tc.name, diff.ObjectReflectDiff(expected, actual)) 1617 } 1618 } 1619 } 1620 } 1621 1622 func TestHandleDefaultNamespace(t *testing.T) { 1623 testcases := []struct { 1624 name string 1625 given map[plugins.ConfigMapID][]ConfigMapUpdate 1626 expected map[plugins.ConfigMapID][]ConfigMapUpdate 1627 }{ 1628 { 1629 name: "nil map", 1630 given: nil, 1631 expected: map[plugins.ConfigMapID][]ConfigMapUpdate{}, 1632 }, 1633 { 1634 name: "empty map", 1635 given: map[plugins.ConfigMapID][]ConfigMapUpdate{}, 1636 expected: map[plugins.ConfigMapID][]ConfigMapUpdate{}, 1637 }, 1638 { 1639 name: "no empty string as namespace", 1640 given: map[plugins.ConfigMapID][]ConfigMapUpdate{ 1641 {Name: "some-config", Namespace: "ns1", Cluster: "build01"}: { 1642 {Key: "foo.yaml", Filename: "config/foo.yaml"}, 1643 }, 1644 {Name: "other-config", Namespace: "default", Cluster: "default"}: { 1645 {Key: "foo.yaml", Filename: "config/foo.yaml"}, 1646 {Key: "bar.yaml", Filename: "config/bar.yaml"}, 1647 }, 1648 }, 1649 expected: map[plugins.ConfigMapID][]ConfigMapUpdate{ 1650 {Name: "some-config", Namespace: "ns1", Cluster: "build01"}: { 1651 {Key: "foo.yaml", Filename: "config/foo.yaml"}, 1652 }, 1653 {Name: "other-config", Namespace: "default", Cluster: "default"}: { 1654 {Key: "foo.yaml", Filename: "config/foo.yaml"}, 1655 {Key: "bar.yaml", Filename: "config/bar.yaml"}, 1656 }, 1657 }, 1658 }, 1659 { 1660 name: "some empty string as namespace", 1661 given: map[plugins.ConfigMapID][]ConfigMapUpdate{ 1662 {Name: "some-config", Namespace: "ns1", Cluster: "build01"}: { 1663 {Key: "foo.yaml", Filename: "config/foo.yaml"}, 1664 }, 1665 {Name: "other-config", Cluster: "default"}: { 1666 {Key: "foo.yaml", Filename: "config/foo.yaml"}, 1667 {Key: "bar.yaml", Filename: "config/bar.yaml"}, 1668 }, 1669 }, 1670 expected: map[plugins.ConfigMapID][]ConfigMapUpdate{ 1671 {Name: "some-config", Namespace: "ns1", Cluster: "build01"}: { 1672 {Key: "foo.yaml", Filename: "config/foo.yaml"}, 1673 }, 1674 {Name: "other-config", Namespace: "default", Cluster: "default"}: { 1675 {Key: "foo.yaml", Filename: "config/foo.yaml"}, 1676 {Key: "bar.yaml", Filename: "config/bar.yaml"}, 1677 }, 1678 }, 1679 }, 1680 { 1681 name: "some empty string as namespace with potential conflicting id", 1682 given: map[plugins.ConfigMapID][]ConfigMapUpdate{ 1683 {Name: "some-config", Namespace: "ns1", Cluster: "build01"}: { 1684 {Key: "foo.yaml", Filename: "config/foo.yaml"}, 1685 }, 1686 {Name: "multikey-config", Cluster: "default"}: { 1687 {Key: "foo.yaml", Filename: "config/foo.yaml"}, 1688 }, 1689 {Name: "multikey-config", Namespace: "default", Cluster: "default"}: { 1690 {Key: "bar.yaml", Filename: "config/bar.yaml"}, 1691 }, 1692 }, 1693 expected: map[plugins.ConfigMapID][]ConfigMapUpdate{ 1694 {Name: "some-config", Namespace: "ns1", Cluster: "build01"}: { 1695 {Key: "foo.yaml", Filename: "config/foo.yaml"}, 1696 }, 1697 {Name: "multikey-config", Namespace: "default", Cluster: "default"}: { 1698 {Key: "bar.yaml", Filename: "config/bar.yaml"}, 1699 {Key: "foo.yaml", Filename: "config/foo.yaml"}, 1700 }, 1701 }, 1702 }, 1703 } 1704 1705 for _, tc := range testcases { 1706 actual := handleDefaultNamespace(tc.given, defaultNamespace) 1707 if !equality.Semantic.DeepEqual(tc.expected, actual) { 1708 t.Errorf("%s: incorrect changes: %v", tc.name, diff.ObjectReflectDiff(tc.expected, actual)) 1709 } 1710 } 1711 } 1712 1713 func TestUpdateV2(t *testing.T) { 1714 testUpdate(localgit.NewV2, t) 1715 } 1716 1717 func testUpdate(clients localgit.Clients, t *testing.T) { 1718 testcases := []struct { 1719 name string 1720 updates []ConfigMapUpdate 1721 existConfigMap runtime.Object 1722 expectedConfigMap *coreapi.ConfigMap 1723 config *plugins.ConfigUpdater 1724 bootstrap bool 1725 }{ 1726 { 1727 name: "stale key removed in bootstrap mode", 1728 bootstrap: true, 1729 updates: []ConfigMapUpdate{ 1730 { 1731 Filename: "config/foo.yaml", 1732 Key: "foo.yaml", 1733 }, 1734 }, 1735 existConfigMap: runtime.Object( 1736 &coreapi.ConfigMap{ 1737 ObjectMeta: metav1.ObjectMeta{ 1738 Name: "multikey-config", 1739 Namespace: defaultNamespace, 1740 Labels: map[string]string{ 1741 "app.kubernetes.io/name": "prow", 1742 "app.kubernetes.io/component": "updateconfig-plugin", 1743 }, 1744 }, 1745 Data: map[string]string{ 1746 "foo.yaml": "old-foo-config", 1747 "bar.yaml": "old-bar-config", 1748 }, 1749 }, 1750 ), 1751 expectedConfigMap: &coreapi.ConfigMap{ 1752 ObjectMeta: metav1.ObjectMeta{ 1753 Name: "multikey-config", 1754 Namespace: defaultNamespace, 1755 Labels: map[string]string{ 1756 "app.kubernetes.io/name": "prow", 1757 "app.kubernetes.io/component": "updateconfig-plugin", 1758 }, 1759 }, 1760 Data: map[string]string{ 1761 "foo.yaml": "new-foo-config", 1762 "VERSION": "12345", 1763 }, 1764 }, 1765 }, 1766 { 1767 name: "stale key kept when not in bootstrap mode", 1768 bootstrap: false, 1769 updates: []ConfigMapUpdate{ 1770 { 1771 Filename: "config/foo.yaml", 1772 Key: "foo.yaml", 1773 }, 1774 }, 1775 existConfigMap: runtime.Object( 1776 &coreapi.ConfigMap{ 1777 ObjectMeta: metav1.ObjectMeta{ 1778 Name: "multikey-config", 1779 Namespace: defaultNamespace, 1780 Labels: map[string]string{ 1781 "app.kubernetes.io/name": "prow", 1782 "app.kubernetes.io/component": "updateconfig-plugin", 1783 }, 1784 }, 1785 Data: map[string]string{ 1786 "foo.yaml": "old-foo-config", 1787 "bar.yaml": "old-bar-config", 1788 }, 1789 }, 1790 ), 1791 expectedConfigMap: &coreapi.ConfigMap{ 1792 ObjectMeta: metav1.ObjectMeta{ 1793 Name: "multikey-config", 1794 Namespace: defaultNamespace, 1795 Labels: map[string]string{ 1796 "app.kubernetes.io/name": "prow", 1797 "app.kubernetes.io/component": "updateconfig-plugin", 1798 }, 1799 }, 1800 Data: map[string]string{ 1801 "VERSION": "12345", 1802 "foo.yaml": "new-foo-config", 1803 "bar.yaml": "old-bar-config", 1804 }, 1805 }, 1806 }, 1807 } 1808 1809 for _, tc := range testcases { 1810 log := logrus.WithField("plugin", pluginName) 1811 fkc := fake.NewSimpleClientset(tc.existConfigMap) 1812 configMapClient, err := GetConfigMapClient(fkc.CoreV1(), tc.expectedConfigMap.Namespace, nil, kube.DefaultClusterAlias) 1813 if err != nil { 1814 log.WithError(err).Errorf("Failed to find configMap client") 1815 continue 1816 } 1817 1818 m := tc.config 1819 if m == nil { 1820 m = &plugins.ConfigUpdater{ 1821 Maps: map[string]plugins.ConfigMapSpec{ 1822 "prow/config.yaml": { 1823 Name: "config", 1824 }, 1825 "prow/plugins.yaml": { 1826 Name: "plugins", 1827 Key: "test-key", 1828 }, 1829 "boskos/resources.yaml": { 1830 Name: "boskos-config", 1831 Clusters: map[string][]string{"default": {"boskos"}}, 1832 }, 1833 "config/foo.yaml": { 1834 Name: "multikey-config", 1835 }, 1836 "config/bar.yaml": { 1837 Name: "multikey-config", 1838 }, 1839 "dir/subdir/**/*.yaml": { 1840 Name: "glob-config", 1841 }, 1842 }, 1843 } 1844 } 1845 m.SetDefaults() 1846 1847 org := "org" 1848 repo := "repo" 1849 c := setupLocalGitRepo(clients, t, org, repo) 1850 1851 gitRepo, err := c.ClientFor(org, repo) 1852 if err != nil { 1853 t.Fatalf("Failed to clone: %v.", err) 1854 } 1855 defer func() { 1856 if err := c.Clean(); err != nil { 1857 t.Errorf("Could not clean up git client cache: %v.", err) 1858 } 1859 }() 1860 if err := gitRepo.Checkout("12345"); err != nil { 1861 t.Errorf("Failed to checkout 12345: %v.", err) 1862 continue 1863 } 1864 if err := Update(&OSFileGetter{Root: gitRepo.Directory()}, configMapClient, tc.expectedConfigMap.Name, tc.expectedConfigMap.Namespace, tc.updates, tc.bootstrap, nil, log, "12345"); err != nil { 1865 t.Errorf("%s: unexpected error updating: %s", tc.name, err) 1866 continue 1867 } 1868 1869 modifiedConfigMaps := sets.New[string]() 1870 for _, action := range fkc.Fake.Actions() { 1871 var obj runtime.Object 1872 switch action := action.(type) { 1873 case clienttesting.CreateActionImpl: 1874 obj = action.Object 1875 case clienttesting.UpdateActionImpl: 1876 obj = action.Object 1877 default: 1878 continue 1879 } 1880 objectMeta, err := meta.Accessor(obj) 1881 if err != nil { 1882 t.Fatalf("%s: client saw an action for something that wasn't an object: %v", tc.name, err) 1883 } 1884 modifiedConfigMaps.Insert(objectMeta.GetName()) 1885 } 1886 1887 expected := tc.expectedConfigMap 1888 actual, err := fkc.CoreV1().ConfigMaps(expected.Namespace).Get(context.TODO(), expected.Name, metav1.GetOptions{}) 1889 if err != nil && errors.IsNotFound(err) { 1890 t.Errorf("%s: Should have updated or created configmap for '%s'", tc.name, expected) 1891 } else if !equality.Semantic.DeepEqual(expected, actual) { 1892 t.Errorf("%s: incorrect ConfigMap state after update: %v", tc.name, diff.ObjectReflectDiff(expected, actual)) 1893 } 1894 } 1895 } 1896 1897 func getFileMap(s string) map[string][]byte { 1898 result := map[string][]byte{} 1899 for file, v := range remoteFiles { 1900 for sha, content := range v { 1901 if sha == s { 1902 result[file] = []byte(content) 1903 } 1904 } 1905 } 1906 return result 1907 } 1908 1909 func boolPtr(b bool) *bool { 1910 return &b 1911 } 1912 1913 type MapFS fstest.MapFS 1914 1915 func (m MapFS) GetFile(name string) ([]byte, error) { 1916 return fstest.MapFS(m).ReadFile(name) 1917 } 1918 1919 func TestUpdateSize(t *testing.T) { 1920 t.Parallel() 1921 ns, name, commit := "ns", "name", "da28634f10160f8c746c387cd33b488909036e1f" 1922 log := logrus.NewEntry(logrus.New()) 1923 fs := MapFS{ 1924 "s": {Data: []byte("string data"), Mode: 0777}, 1925 "c": { 1926 // $ printf 'string data' | gzip | hexdump -ve '1/1 "0x%02x, "' 1927 Data: []byte{ 1928 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 1929 0x2b, 0x2e, 0x29, 0xca, 0xcc, 0x4b, 0x57, 0x48, 0x49, 0x2c, 1930 0x49, 0x04, 0x00, 0x1e, 0xfb, 0x1a, 0x61, 0x0b, 0x00, 0x00, 1931 0x00, 1932 }, 1933 Mode: 0777, 1934 }, 1935 } 1936 testCases := []struct { 1937 name string 1938 updates []ConfigMapUpdate 1939 expected float64 1940 }{ 1941 { 1942 name: "empty", 1943 expected: 40, 1944 }, 1945 { 1946 name: "string data", 1947 updates: []ConfigMapUpdate{ 1948 {Key: "k0", Filename: "s"}, 1949 {Key: "k1", Filename: "s"}, 1950 {Key: "k2", Filename: "s"}, 1951 }, 1952 expected: 73, 1953 }, 1954 { 1955 name: "compressed data", 1956 updates: []ConfigMapUpdate{ 1957 {Key: "k0", Filename: "c"}, 1958 {Key: "k1", Filename: "c"}, 1959 {Key: "k2", Filename: "c"}, 1960 }, 1961 expected: 133, 1962 }, 1963 { 1964 name: "combined data", 1965 updates: []ConfigMapUpdate{ 1966 {Key: "k0", Filename: "s"}, 1967 {Key: "k1", Filename: "s"}, 1968 {Key: "k2", Filename: "s"}, 1969 {Key: "k3", Filename: "c"}, 1970 {Key: "k4", Filename: "c"}, 1971 {Key: "k5", Filename: "c"}, 1972 }, 1973 expected: 166, 1974 }, 1975 } 1976 for i := range testCases { 1977 tc := testCases[i] 1978 t.Run(tc.name, func(t *testing.T) { 1979 t.Parallel() 1980 client, err := GetConfigMapClient(fake.NewSimpleClientset().CoreV1(), ns, nil, kube.DefaultClusterAlias) 1981 if err != nil { 1982 t.Fatalf("failed to create fake client: %v", err) 1983 } 1984 metrics := prometheus.NewGaugeVec(prometheus.GaugeOpts{}, []string{name, ns}) 1985 if err := Update(fs, client, name, ns, tc.updates, true, metrics, log, commit); err != nil { 1986 t.Fatalf("unexpected error updating: %v", err) 1987 } 1988 var metric prometheus_model.Metric 1989 metrics.WithLabelValues(name, ns).Write(&metric) 1990 if n := *metric.Gauge.Value; n != tc.expected { 1991 t.Fatalf("unexpected total, want %v, got %v", tc.expected, n) 1992 } 1993 }) 1994 } 1995 } 1996 1997 func TestMarkStaleKeysForDeletion(t *testing.T) { 1998 t.Parallel() 1999 testCases := []struct { 2000 name string 2001 configMap *coreapi.ConfigMap 2002 updates []ConfigMapUpdate 2003 expected []ConfigMapUpdate 2004 }{ 2005 { 2006 name: "empty", 2007 configMap: &coreapi.ConfigMap{ 2008 ObjectMeta: metav1.ObjectMeta{ 2009 Name: "config", 2010 }, 2011 }, 2012 updates: []ConfigMapUpdate{ 2013 {Key: "foo.yaml", Filename: "config/foo.yaml"}, 2014 }, 2015 expected: []ConfigMapUpdate{}, // nothing to delete 2016 }, 2017 { 2018 name: "delete one key", 2019 configMap: &coreapi.ConfigMap{ 2020 ObjectMeta: metav1.ObjectMeta{ 2021 Name: "config", 2022 }, 2023 Data: map[string]string{ 2024 "foo.yaml": "old-foo-config", 2025 "bar.yaml": "old-bar-config", 2026 }, 2027 }, 2028 updates: []ConfigMapUpdate{ 2029 {Key: "foo.yaml", Filename: "config/foo.yaml"}, 2030 }, 2031 expected: []ConfigMapUpdate{ 2032 {Key: "bar.yaml"}, // delete this one 2033 }, 2034 }, 2035 { 2036 name: "delete 3 keys", 2037 configMap: &coreapi.ConfigMap{ 2038 ObjectMeta: metav1.ObjectMeta{ 2039 Name: "config", 2040 }, 2041 Data: map[string]string{ 2042 "foo.yaml": "old-foo-config", 2043 "bar.yaml": "old-bar-config", 2044 "baz.yaml": "old-baz-config", 2045 "qux.yaml": "old-qux-config", 2046 }, 2047 }, 2048 updates: []ConfigMapUpdate{ 2049 {Key: "foo.yaml", Filename: "config/foo.yaml"}, 2050 }, 2051 expected: []ConfigMapUpdate{ 2052 {Key: "bar.yaml"}, // delete this one 2053 {Key: "baz.yaml"}, // delete this one 2054 {Key: "qux.yaml"}, // delete this one 2055 }, 2056 }, 2057 { 2058 // Potential callers of MarkStaleKeysForDeletion() may avoid calling 2059 // us if there are no updates for safety, but we can't rely on 2060 // callers being safe all the time. So make sure that we do a NOP if 2061 // there are no updates (don't try to do a mass deletion if an empty 2062 // slice is passed in somehow). 2063 name: "for safety, delete nothing if there are no updates", 2064 configMap: &coreapi.ConfigMap{ 2065 ObjectMeta: metav1.ObjectMeta{ 2066 Name: "config", 2067 }, 2068 Data: map[string]string{ 2069 "foo.yaml": "old-foo-config", 2070 "bar.yaml": "old-bar-config", 2071 "baz.yaml": "old-baz-config", 2072 "qux.yaml": "old-qux-config", 2073 }, 2074 }, 2075 updates: []ConfigMapUpdate{}, 2076 expected: nil, 2077 }, 2078 } 2079 for i := range testCases { 2080 tc := testCases[i] 2081 t.Run(tc.name, func(t *testing.T) { 2082 t.Parallel() 2083 actual := MarkStaleKeysForDeletion(tc.configMap, tc.updates) 2084 if diff := cmp.Diff(tc.expected, actual, cmpopts.SortSlices(func(a, b ConfigMapUpdate) bool { 2085 return a.Key < b.Key 2086 })); diff != "" { 2087 t.Fatalf("ConfigMapUpdate slice mismatch. want(-), got(+):\n%s", diff) 2088 } 2089 }) 2090 } 2091 }