k8s.io/test-infra@v0.0.0-20240520184403-27c6b4c223d8/releng/config-forker/main_test.go (about) 1 /* 2 Copyright 2019 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 main 18 19 import ( 20 "reflect" 21 "testing" 22 23 "github.com/google/go-cmp/cmp" 24 "github.com/google/go-cmp/cmp/cmpopts" 25 26 v1 "k8s.io/api/core/v1" 27 "k8s.io/apimachinery/pkg/util/diff" 28 prowapi "sigs.k8s.io/prow/pkg/apis/prowjobs/v1" 29 "sigs.k8s.io/prow/pkg/config" 30 ) 31 32 func TestCleanAnnotations(t *testing.T) { 33 tests := []struct { 34 name string 35 annotations map[string]string 36 expected map[string]string 37 }{ 38 { 39 name: "no annotations", 40 annotations: map[string]string{}, 41 expected: map[string]string{}, 42 }, 43 { 44 name: "only removable annotations", 45 annotations: map[string]string{ 46 forkAnnotation: "true", 47 replacementAnnotation: "foo -> bar", 48 }, 49 expected: map[string]string{}, 50 }, 51 { 52 name: "all our annotations", 53 annotations: map[string]string{ 54 forkAnnotation: "true", 55 replacementAnnotation: "foo -> bar", 56 periodicIntervalAnnotation: "2h", 57 }, 58 expected: map[string]string{ 59 periodicIntervalAnnotation: "2h", 60 }, 61 }, 62 { 63 name: "foreign annotations", 64 annotations: map[string]string{ 65 "someOtherAnnotation": "pony party", 66 }, 67 expected: map[string]string{ 68 "someOtherAnnotation": "pony party", 69 }, 70 }, 71 { 72 name: "blank periodic annotations", 73 annotations: map[string]string{ 74 periodicIntervalAnnotation: "", 75 cronAnnotation: "", 76 }, 77 expected: map[string]string{}, 78 }, 79 } 80 81 for _, tc := range tests { 82 t.Run(tc.name, func(t *testing.T) { 83 oldAnnotations := map[string]string{} 84 for k, v := range tc.annotations { 85 oldAnnotations[k] = v 86 } 87 result := cleanAnnotations(tc.annotations) 88 if !reflect.DeepEqual(result, tc.expected) { 89 t.Errorf("Expected result %#v', got %#v", tc.expected, result) 90 } 91 if !reflect.DeepEqual(oldAnnotations, tc.annotations) { 92 t.Errorf("Input annotations map changed: used to be %#v, now %#v", oldAnnotations, tc.annotations) 93 } 94 }) 95 } 96 } 97 98 func TestEvaluateTemplate(t *testing.T) { 99 const expected = "Foo Substitution! Baz" 100 result, err := evaluateTemplate("Foo {{.Bar}} Baz", map[string]string{"Bar": "Substitution!"}) 101 if err != nil { 102 t.Fatalf("Unexpected error: %v", err) 103 } 104 if result != expected { 105 t.Errorf("Expected result %q, got %q", expected, result) 106 } 107 } 108 109 func TestPerformArgReplacements(t *testing.T) { 110 tests := []struct { 111 name string 112 args []string 113 replacements string 114 expected []string 115 expectErr bool 116 }{ 117 { 118 name: "nil arguments remain nil", 119 args: nil, 120 replacements: "foo -> bar", 121 expected: nil, 122 }, 123 { 124 name: "empty arguments remain empty", 125 args: []string{}, 126 replacements: "foo -> bar", 127 expected: []string{}, 128 }, 129 { 130 name: "empty replacements do nothing", 131 args: []string{"foo", "bar"}, 132 replacements: "", 133 expected: []string{"foo", "bar"}, 134 }, 135 { 136 name: "simple replacement works", 137 args: []string{"foos", "bars", "bazzes"}, 138 replacements: "foo -> bar", 139 expected: []string{"bars", "bars", "bazzes"}, 140 }, 141 { 142 name: "multiple replacements work", 143 args: []string{"some foos", "bars", "bazzes"}, 144 replacements: "foo -> bar, bars -> bazzes", 145 expected: []string{"some bars", "bazzes", "bazzes"}, 146 }, 147 { 148 name: "template expansion works", 149 args: []string{"version: special one"}, 150 replacements: "special one -> {{.Version}}", 151 expected: []string{"version: 1.15"}, 152 }, 153 { 154 name: "invalid template is an error", 155 args: []string{"version: special one"}, 156 replacements: "special one -> {{Version}}", 157 expectErr: true, 158 }, 159 { 160 name: "unparseable replacements are an error", 161 args: []string{"foo"}, 162 replacements: "foo -> bar, baz", 163 expectErr: true, 164 }, 165 } 166 167 for _, tc := range tests { 168 t.Run(tc.name, func(t *testing.T) { 169 result, err := performReplacement(tc.args, templateVars{Version: "1.15"}, tc.replacements) 170 if err != nil { 171 if !tc.expectErr { 172 t.Fatalf("Unexpected error: %v", err) 173 } 174 return 175 } 176 if tc.expectErr { 177 t.Fatalf("Expected an error, but got %v", result) 178 } 179 if !reflect.DeepEqual(result, tc.expected) { 180 t.Errorf("Expected result %v, but got %v instead", tc.expected, result) 181 } 182 }) 183 } 184 } 185 186 func TestPerformArgDeletions(t *testing.T) { 187 tests := []struct { 188 name string 189 args map[string]string 190 deletions string 191 expected map[string]string 192 }{ 193 { 194 name: "nil arguments remain nil", 195 args: nil, 196 deletions: "", 197 expected: nil, 198 }, 199 { 200 name: "empty arguments remain empty", 201 args: map[string]string{}, 202 deletions: "", 203 expected: map[string]string{}, 204 }, 205 { 206 name: "empty deletions do nothing", 207 args: map[string]string{"foo": "bar"}, 208 deletions: "", 209 expected: map[string]string{"foo": "bar"}, 210 }, 211 { 212 name: "simple deletion works", 213 args: map[string]string{"foo": "bar", "baz": "baz2"}, 214 deletions: "foo", 215 expected: map[string]string{"baz": "baz2"}, 216 }, 217 { 218 name: "multiple deletions work", 219 args: map[string]string{"foo": "bar", "baz": "baz2", "hello": "world"}, 220 deletions: "foo, baz", 221 expected: map[string]string{"hello": "world"}, 222 }, 223 } 224 225 for _, tc := range tests { 226 t.Run(tc.name, func(t *testing.T) { 227 result := performDeletion(tc.args, tc.deletions) 228 if !reflect.DeepEqual(result, tc.expected) { 229 t.Errorf("Expected result %v, but got %v instead", tc.expected, result) 230 } 231 }) 232 } 233 } 234 235 func TestFixImage(t *testing.T) { 236 tests := []struct { 237 name string 238 image string 239 expected string 240 }{ 241 { 242 name: "replaces -master with -[version]", 243 image: "kubekins-e2e-blahblahblah-master", 244 expected: "kubekins-e2e-blahblahblah-1.15", 245 }, 246 { 247 name: "does nothing with non-master images", 248 image: "golang:1.12.2", 249 expected: "golang:1.12.2", 250 }, 251 } 252 253 for _, tc := range tests { 254 t.Run(tc.name, func(t *testing.T) { 255 if result := fixImage(tc.image, "1.15"); result != tc.expected { 256 t.Errorf("Expected %q, but got %q", tc.expected, result) 257 } 258 }) 259 } 260 } 261 262 func TestFixBootstrapArgs(t *testing.T) { 263 tests := []struct { 264 name string 265 args []string 266 expected []string 267 }{ 268 { 269 name: "replaces repo with no branch specified", 270 args: []string{"--repo=k8s.io/kubernetes"}, 271 expected: []string{"--repo=k8s.io/kubernetes=release-1.15"}, 272 }, 273 { 274 name: "replaces repo with master branch specified", 275 args: []string{"--repo=k8s.io/kubernetes=master"}, 276 expected: []string{"--repo=k8s.io/kubernetes=release-1.15"}, 277 }, 278 { 279 name: "replaces master branch with release branch", 280 args: []string{"--branch=master"}, 281 expected: []string{"--branch=release-1.15"}, 282 }, 283 { 284 name: "replaces both repo and branch", 285 args: []string{"--repo=k8s.io/kubernetes=master", "--branch=master"}, 286 expected: []string{"--repo=k8s.io/kubernetes=release-1.15", "--branch=release-1.15"}, 287 }, 288 { 289 name: "doesn't replace other repos", 290 args: []string{"--repo=k8s.io/test-infra"}, 291 expected: []string{"--repo=k8s.io/test-infra"}, 292 }, 293 { 294 name: "doesn't touch other flags", 295 args: []string{"--foo=bar", "--branch=master"}, 296 expected: []string{"--foo=bar", "--branch=release-1.15"}, 297 }, 298 { 299 name: "nil args are still nil", 300 args: nil, 301 expected: nil, 302 }, 303 } 304 305 for _, tc := range tests { 306 t.Run(tc.name, func(t *testing.T) { 307 if result := fixBootstrapArgs(tc.args, "1.15"); !reflect.DeepEqual(result, tc.expected) { 308 t.Errorf("Expected args %v, but got %v instead", tc.expected, result) 309 } 310 }) 311 } 312 } 313 314 func TestFixExtraRefs(t *testing.T) { 315 tests := []struct { 316 name string 317 refs []prowapi.Refs 318 expected []prowapi.Refs 319 }{ 320 { 321 name: "replaces kubernetes master with release branch", 322 refs: []prowapi.Refs{{Org: "kubernetes", Repo: "kubernetes", BaseRef: "master"}}, 323 expected: []prowapi.Refs{{Org: "kubernetes", Repo: "kubernetes", BaseRef: "release-1.15"}}, 324 }, 325 { 326 name: "ignores kubernetes repos other than kubernetes", 327 refs: []prowapi.Refs{{Org: "kubernetes", Repo: "test-infra", BaseRef: "master"}}, 328 expected: []prowapi.Refs{{Org: "kubernetes", Repo: "test-infra", BaseRef: "master"}}, 329 }, 330 { 331 name: "ignores repos called kubernetes in other orgs", 332 refs: []prowapi.Refs{{Org: "Katharine", Repo: "kubernetes", BaseRef: "master"}}, 333 expected: []prowapi.Refs{{Org: "Katharine", Repo: "kubernetes", BaseRef: "master"}}, 334 }, 335 { 336 name: "ignores non-master branches", 337 refs: []prowapi.Refs{{Org: "kubernetes", Repo: "kubernetes", BaseRef: "other-branch"}}, 338 expected: []prowapi.Refs{{Org: "kubernetes", Repo: "kubernetes", BaseRef: "other-branch"}}, 339 }, 340 { 341 name: "handles multiple refs", 342 refs: []prowapi.Refs{{Org: "kubernetes", Repo: "test-infra", BaseRef: "master"}, {Org: "kubernetes", Repo: "kubernetes", BaseRef: "master"}}, 343 expected: []prowapi.Refs{{Org: "kubernetes", Repo: "test-infra", BaseRef: "master"}, {Org: "kubernetes", Repo: "kubernetes", BaseRef: "release-1.15"}}, 344 }, 345 } 346 347 for _, tc := range tests { 348 t.Run(tc.name, func(t *testing.T) { 349 if result := fixExtraRefs(tc.refs, "1.15"); !reflect.DeepEqual(result, tc.expected) { 350 t.Errorf("Result does not match expected. Difference:\n%s", diff.ObjectDiff(tc.expected, result)) 351 } 352 }) 353 } 354 } 355 356 func TestFixEnvVars(t *testing.T) { 357 tests := []struct { 358 name string 359 vars []v1.EnvVar 360 expected []v1.EnvVar 361 }{ 362 { 363 name: "replaces BRANCH-like jobs referencing master", 364 vars: []v1.EnvVar{{Name: "KUBERNETES_BRANCH", Value: "master"}}, 365 expected: []v1.EnvVar{{Name: "KUBERNETES_BRANCH", Value: "release-1.15"}}, 366 }, 367 { 368 name: "ignores BRANCH-like jobs referencing something else", 369 vars: []v1.EnvVar{{Name: "KUBERNETES_BRANCH", Value: "something-else"}}, 370 expected: []v1.EnvVar{{Name: "KUBERNETES_BRANCH", Value: "something-else"}}, 371 }, 372 { 373 name: "names are case-insensitive", 374 vars: []v1.EnvVar{{Name: "branch", Value: "master"}}, 375 expected: []v1.EnvVar{{Name: "branch", Value: "release-1.15"}}, 376 }, 377 { 378 name: "other vars are not touched", 379 vars: []v1.EnvVar{{Name: "foo", Value: "bar"}, {Name: "baz", ValueFrom: &v1.EnvVarSource{SecretKeyRef: &v1.SecretKeySelector{Key: "baz-secret"}}}}, 380 expected: []v1.EnvVar{{Name: "foo", Value: "bar"}, {Name: "baz", ValueFrom: &v1.EnvVarSource{SecretKeyRef: &v1.SecretKeySelector{Key: "baz-secret"}}}}, 381 }, 382 } 383 384 for _, tc := range tests { 385 t.Run(tc.name, func(t *testing.T) { 386 if result := fixEnvVars(tc.vars, "1.15"); !reflect.DeepEqual(result, tc.expected) { 387 t.Errorf("Result does not match expected. Difference:\n%s", diff.ObjectDiff(tc.expected, result)) 388 } 389 }) 390 } 391 } 392 393 func TestFixTestgridAnnotations(t *testing.T) { 394 tests := []struct { 395 name string 396 annotations map[string]string 397 expected map[string]string 398 isPresubmit bool 399 }{ 400 { 401 name: "remove presubmit additions to dashboards", 402 annotations: map[string]string{testgridDashboardsAnnotation: "sig-release-master-blocking, google-unit"}, 403 expected: map[string]string{}, 404 isPresubmit: true, 405 }, 406 { 407 name: "periodic updates master-blocking to point at 1.15-blocking", 408 annotations: map[string]string{testgridDashboardsAnnotation: "sig-release-master-blocking"}, 409 expected: map[string]string{testgridDashboardsAnnotation: "sig-release-1.15-blocking"}, 410 isPresubmit: false, 411 }, 412 { 413 name: "periodic updates with no dashboard annotation points to job-config-errors", 414 annotations: map[string]string{}, 415 expected: map[string]string{testgridDashboardsAnnotation: "sig-release-job-config-errors"}, 416 isPresubmit: false, 417 }, 418 { 419 name: "drop 'description'", 420 annotations: map[string]string{descriptionAnnotation: "some description"}, 421 expected: map[string]string{}, 422 isPresubmit: true, 423 }, 424 { 425 name: "update tab names", 426 annotations: map[string]string{testgridTabNameAnnotation: "foo master"}, 427 expected: map[string]string{testgridDashboardsAnnotation: "sig-release-job-config-errors", testgridTabNameAnnotation: "foo 1.15"}, 428 isPresubmit: false, 429 }, 430 } 431 432 for _, tc := range tests { 433 t.Run(tc.name, func(t *testing.T) { 434 result := fixTestgridAnnotations(tc.annotations, "1.15", tc.isPresubmit) 435 if !reflect.DeepEqual(result, tc.expected) { 436 t.Errorf("Result does not match expected. Difference:\n%s", diff.ObjectDiff(tc.expected, result)) 437 } 438 }) 439 } 440 } 441 442 func TestGenerateNameVariant(t *testing.T) { 443 tests := []struct { 444 name string 445 testName string 446 genericSuffix bool 447 expected string 448 }{ 449 { 450 name: "jobs ending in -master have it replaced with a version", 451 testName: "ci-party-master", 452 expected: "ci-party-1-15", 453 }, 454 { 455 name: "generic jobs ending in -master have it replaced with -beta", 456 testName: "ci-party-master", 457 genericSuffix: true, 458 expected: "ci-party-beta", 459 }, 460 { 461 name: "jobs not ending in in -master have a number appended", 462 testName: "ci-party", 463 expected: "ci-party-1-15", 464 }, 465 { 466 name: "generic jobs not ending in in -master have 'beta' appended", 467 testName: "ci-party", 468 genericSuffix: true, 469 expected: "ci-party-beta", 470 }, 471 } 472 473 for _, tc := range tests { 474 t.Run(tc.name, func(t *testing.T) { 475 if result := generateNameVariant(tc.testName, "1.15", tc.genericSuffix); result != tc.expected { 476 t.Errorf("Expected name %q, but got name %q.", tc.expected, result) 477 } 478 }) 479 } 480 } 481 482 func TestGeneratePresubmits(t *testing.T) { 483 presubmits := map[string][]config.Presubmit{ 484 "kubernetes/kubernetes": { 485 { 486 JobBase: config.JobBase{ 487 Name: "pull-kubernetes-e2e", 488 Annotations: map[string]string{forkAnnotation: "true"}, 489 }, 490 Brancher: config.Brancher{ 491 SkipBranches: []string{`release-\d\.\d`}, 492 }, 493 }, 494 { 495 JobBase: config.JobBase{ 496 Name: "pull-kubernetes-e2e-branch-in-name-master", 497 Annotations: map[string]string{forkAnnotation: "true"}, 498 }, 499 Brancher: config.Brancher{ 500 SkipBranches: []string{`release-\d\.\d`}, 501 }, 502 }, 503 { 504 JobBase: config.JobBase{ 505 Name: "pull-kubernetes-e2e-keep-context", 506 Annotations: map[string]string{forkAnnotation: "true"}, 507 }, 508 Brancher: config.Brancher{ 509 SkipBranches: []string{`release-\d\.\d`}, 510 }, 511 Reporter: config.Reporter{ 512 Context: "mycontext", 513 }, 514 }, 515 { 516 JobBase: config.JobBase{ 517 Name: "pull-kubernetes-e2e-replace-context", 518 Annotations: map[string]string{forkAnnotation: "true"}, 519 }, 520 Brancher: config.Brancher{ 521 SkipBranches: []string{`release-\d\.\d`}, 522 }, 523 Reporter: config.Reporter{ 524 Context: "mycontext-master", 525 }, 526 }, 527 { 528 JobBase: config.JobBase{ 529 Name: "pull-replace-some-things", 530 Annotations: map[string]string{ 531 forkAnnotation: "true", 532 replacementAnnotation: "foo -> {{.Version}}, GO_VERSION= -> GO_VERSION={{.GoVersion}}", 533 "testgrid-generate-test-group": "true", 534 "some-annotation": "yup", 535 }, 536 Spec: &v1.PodSpec{ 537 Containers: []v1.Container{ 538 { 539 Image: "gcr.io/k8s-staging-test-infra/kubekins-e2e:blahblahblah-master", 540 Command: []string{"--arg1=test", "--something=foo"}, 541 Args: []string{"--repo=k8s.io/kubernetes", "--something=foo"}, 542 Env: []v1.EnvVar{{Name: "BRANCH", Value: "master"}, {Name: "GO_VERSION"}}, 543 }, 544 }, 545 }, 546 }, 547 Brancher: config.Brancher{ 548 SkipBranches: []string{`release-\d\.\d`}, 549 }, 550 }, 551 { 552 JobBase: config.JobBase{ 553 Name: "pull-not-forked", 554 Annotations: map[string]string{"foo": "bar"}, 555 }, 556 }, 557 }, 558 } 559 560 expected := map[string][]config.Presubmit{ 561 "kubernetes/kubernetes": { 562 { 563 JobBase: config.JobBase{ 564 Name: "pull-kubernetes-e2e", 565 Annotations: map[string]string{}, 566 }, 567 Brancher: config.Brancher{ 568 Branches: []string{"release-1.15"}, 569 }, 570 Reporter: config.Reporter{ 571 Context: "pull-kubernetes-e2e", 572 }, 573 }, 574 { 575 JobBase: config.JobBase{ 576 Name: "pull-kubernetes-e2e-branch-in-name-master", 577 Annotations: map[string]string{}, 578 }, 579 Brancher: config.Brancher{ 580 Branches: []string{"release-1.15"}, 581 }, 582 Reporter: config.Reporter{ 583 Context: "pull-kubernetes-e2e-branch-in-name-1.15", 584 }, 585 }, 586 { 587 JobBase: config.JobBase{ 588 Name: "pull-kubernetes-e2e-keep-context", 589 Annotations: map[string]string{}, 590 }, 591 Brancher: config.Brancher{ 592 Branches: []string{"release-1.15"}, 593 }, 594 Reporter: config.Reporter{ 595 Context: "mycontext", 596 }, 597 }, 598 { 599 JobBase: config.JobBase{ 600 Name: "pull-kubernetes-e2e-replace-context", 601 Annotations: map[string]string{}, 602 }, 603 Brancher: config.Brancher{ 604 Branches: []string{"release-1.15"}, 605 }, 606 Reporter: config.Reporter{ 607 Context: "mycontext-1.15", 608 }, 609 }, 610 { 611 JobBase: config.JobBase{ 612 Name: "pull-replace-some-things", 613 Annotations: map[string]string{ 614 "some-annotation": "yup", 615 }, 616 Spec: &v1.PodSpec{ 617 Containers: []v1.Container{ 618 { 619 Image: "gcr.io/k8s-staging-test-infra/kubekins-e2e:blahblahblah-1.15", 620 Command: []string{"--arg1=test", "--something=1.15"}, 621 Args: []string{"--repo=k8s.io/kubernetes", "--something=1.15"}, 622 Env: []v1.EnvVar{{Name: "BRANCH", Value: "release-1.15"}, {Name: "GO_VERSION", Value: "1.20.2"}}, 623 }, 624 }, 625 }, 626 }, 627 Brancher: config.Brancher{ 628 Branches: []string{"release-1.15"}, 629 }, 630 Reporter: config.Reporter{ 631 Context: "pull-replace-some-things", 632 }, 633 }, 634 }, 635 } 636 637 result, err := generatePresubmits(config.JobConfig{PresubmitsStatic: presubmits}, templateVars{Version: "1.15", GoVersion: "1.20.2"}) 638 if err != nil { 639 t.Fatalf("Unexpected error: %v", err) 640 } 641 642 if !reflect.DeepEqual(result, expected) { 643 t.Errorf("Result does not match expected. Difference:\n%s", cmp.Diff(expected, result, cmpopts.IgnoreUnexported(config.Brancher{}, config.RegexpChangeMatcher{}, config.Presubmit{}))) 644 } 645 } 646 647 func TestGeneratePeriodics(t *testing.T) { 648 yes := true 649 periodics := []config.Periodic{ 650 { 651 Cron: "0 * * * *", 652 JobBase: config.JobBase{ 653 Name: "some-forked-periodic-master", 654 Annotations: map[string]string{forkAnnotation: "true"}, 655 }, 656 }, 657 { 658 Cron: "0 * * * *", 659 JobBase: config.JobBase{ 660 Name: "some-generic-periodic-master", 661 Annotations: map[string]string{forkAnnotation: "true", suffixAnnotation: "true"}, 662 }, 663 }, 664 { 665 Cron: "0 * * * *", 666 JobBase: config.JobBase{ 667 Name: "generic-periodic-with-deletions-master", 668 Annotations: map[string]string{ 669 forkAnnotation: "true", 670 deletionAnnotation: "preset-e2e-scalability-periodics-master", 671 suffixAnnotation: "true", 672 }, 673 Labels: map[string]string{ 674 "preset-e2e-scalability-periodics": "true", 675 "preset-e2e-scalability-periodics-master": "true", 676 }, 677 }, 678 }, 679 { 680 Interval: "1h", 681 JobBase: config.JobBase{ 682 Name: "periodic-with-replacements", 683 Annotations: map[string]string{ 684 forkAnnotation: "true", 685 periodicIntervalAnnotation: "6h 12h 24h 24h", 686 replacementAnnotation: "stable -> {{.Version}}, GO_VERSION= -> GO_VERSION={{.GoVersion}}", 687 }, 688 Spec: &v1.PodSpec{ 689 Containers: []v1.Container{ 690 { 691 Image: "gcr.io/k8s-testinfra/kubekins-e2e:blahblahblah-master", 692 Command: []string{"--args1=test", "--version=stable"}, 693 Args: []string{"--repo=k8s.io/kubernetes", "--version=stable"}, 694 Env: []v1.EnvVar{{Name: "BRANCH", Value: "master"}, {Name: "GO_VERSION"}}, 695 }, 696 }, 697 }, 698 }, 699 Tags: []string{"ver: stable"}, 700 }, 701 { 702 Interval: "2h", 703 JobBase: config.JobBase{ 704 Name: "decorated-periodic", 705 Annotations: map[string]string{ 706 forkAnnotation: "true", 707 }, 708 UtilityConfig: config.UtilityConfig{ 709 Decorate: &yes, 710 ExtraRefs: []prowapi.Refs{{Org: "kubernetes", Repo: "kubernetes", BaseRef: "master"}}, 711 }, 712 }, 713 }, 714 { 715 JobBase: config.JobBase{ 716 Name: "not-forked", 717 }, 718 }, 719 } 720 721 expected := []config.Periodic{ 722 { 723 Cron: "0 * * * *", 724 JobBase: config.JobBase{ 725 Name: "some-forked-periodic-1-15", 726 Annotations: map[string]string{testgridDashboardsAnnotation: "sig-release-job-config-errors"}, 727 }, 728 }, 729 { 730 Cron: "0 * * * *", 731 JobBase: config.JobBase{ 732 Name: "some-generic-periodic-beta", 733 Annotations: map[string]string{suffixAnnotation: "true", testgridDashboardsAnnotation: "sig-release-job-config-errors"}, 734 }, 735 }, 736 { 737 Cron: "0 * * * *", 738 JobBase: config.JobBase{ 739 Name: "generic-periodic-with-deletions-beta", 740 Annotations: map[string]string{suffixAnnotation: "true", testgridDashboardsAnnotation: "sig-release-job-config-errors"}, 741 Labels: map[string]string{ 742 "preset-e2e-scalability-periodics": "true", 743 }, 744 }, 745 }, 746 { 747 Interval: "6h", 748 JobBase: config.JobBase{ 749 Name: "periodic-with-replacements-1-15", 750 Annotations: map[string]string{ 751 periodicIntervalAnnotation: "12h 24h 24h", 752 testgridDashboardsAnnotation: "sig-release-job-config-errors", 753 }, 754 Spec: &v1.PodSpec{ 755 Containers: []v1.Container{ 756 { 757 Image: "gcr.io/k8s-testinfra/kubekins-e2e:blahblahblah-1.15", 758 Command: []string{"--args1=test", "--version=1.15"}, 759 Args: []string{"--repo=k8s.io/kubernetes=release-1.15", "--version=1.15"}, 760 Env: []v1.EnvVar{{Name: "BRANCH", Value: "release-1.15"}, {Name: "GO_VERSION", Value: "1.20.2"}}, 761 }, 762 }, 763 }, 764 }, 765 Tags: []string{"ver: 1.15"}, 766 }, 767 { 768 Interval: "2h", 769 JobBase: config.JobBase{ 770 Name: "decorated-periodic-1-15", 771 Annotations: map[string]string{testgridDashboardsAnnotation: "sig-release-job-config-errors"}, 772 UtilityConfig: config.UtilityConfig{ 773 Decorate: &yes, 774 ExtraRefs: []prowapi.Refs{{Org: "kubernetes", Repo: "kubernetes", BaseRef: "release-1.15"}}, 775 }, 776 }, 777 }, 778 } 779 780 result, err := generatePeriodics(config.JobConfig{Periodics: periodics}, templateVars{Version: "1.15", GoVersion: "1.20.2"}) 781 if err != nil { 782 t.Fatalf("Unexpected error: %v", err) 783 } 784 785 if !reflect.DeepEqual(result, expected) { 786 t.Errorf("Result does not match expected. Difference:\n%s\n", cmp.Diff(expected, result, cmpopts.IgnoreUnexported(config.Periodic{}))) 787 } 788 } 789 790 func TestGeneratePostsubmits(t *testing.T) { 791 postsubmits := map[string][]config.Postsubmit{ 792 "kubernetes/kubernetes": { 793 { 794 JobBase: config.JobBase{ 795 Name: "post-kubernetes-e2e", 796 Annotations: map[string]string{forkAnnotation: "true"}, 797 }, 798 Brancher: config.Brancher{ 799 SkipBranches: []string{`release-\d\.\d`}, 800 }, 801 }, 802 { 803 JobBase: config.JobBase{ 804 Name: "post-kubernetes-generic", 805 Annotations: map[string]string{ 806 forkAnnotation: "true", 807 suffixAnnotation: "true", 808 testgridDashboardsAnnotation: "sig-release-master-blocking, google-unit", 809 }, 810 }, 811 Brancher: config.Brancher{ 812 SkipBranches: []string{`release-\d\.\d`}, 813 }, 814 }, 815 { 816 JobBase: config.JobBase{ 817 Name: "post-kubernetes-generic-will-end-up-in-all", 818 Annotations: map[string]string{ 819 forkAnnotation: "true", 820 suffixAnnotation: "true", 821 testgridDashboardsAnnotation: "google-unit", 822 }, 823 }, 824 Brancher: config.Brancher{ 825 SkipBranches: []string{`release-\d\.\d`}, 826 }, 827 }, 828 { 829 JobBase: config.JobBase{ 830 Name: "post-replace-some-things-master", 831 Annotations: map[string]string{ 832 forkAnnotation: "true", 833 replacementAnnotation: "foo -> {{.Version}}, GO_VERSION= -> GO_VERSION={{.GoVersion}}", 834 "some-annotation": "yup", 835 }, 836 Spec: &v1.PodSpec{ 837 Containers: []v1.Container{ 838 { 839 Image: "gcr.io/k8s-staging-test-infra/kubekins-e2e:blahblahblah-master", 840 Command: []string{"--args1=test", "--something=foo"}, 841 Args: []string{"--repo=k8s.io/kubernetes", "--something=foo"}, 842 Env: []v1.EnvVar{{Name: "BRANCH", Value: "master"}, {Name: "GO_VERSION"}}, 843 }, 844 }, 845 }, 846 }, 847 Brancher: config.Brancher{ 848 SkipBranches: []string{`release-\d\.\d`}, 849 }, 850 }, 851 { 852 JobBase: config.JobBase{ 853 Name: "post-not-forked", 854 Annotations: map[string]string{"foo": "bar"}, 855 }, 856 }, 857 }, 858 } 859 860 expected := map[string][]config.Postsubmit{ 861 "kubernetes/kubernetes": { 862 { 863 JobBase: config.JobBase{ 864 Name: "post-kubernetes-e2e-1-15", 865 Annotations: map[string]string{testgridDashboardsAnnotation: "sig-release-job-config-errors"}, 866 }, 867 Brancher: config.Brancher{ 868 Branches: []string{"release-1.15"}, 869 }, 870 }, 871 { 872 JobBase: config.JobBase{ 873 Name: "post-kubernetes-generic-beta", 874 Annotations: map[string]string{ 875 suffixAnnotation: "true", 876 testgridDashboardsAnnotation: "sig-release-1.15-blocking, google-unit", 877 }, 878 }, 879 Brancher: config.Brancher{ 880 Branches: []string{"release-1.15"}, 881 }, 882 }, 883 { 884 JobBase: config.JobBase{ 885 Name: "post-kubernetes-generic-will-end-up-in-all-beta", 886 Annotations: map[string]string{ 887 suffixAnnotation: "true", 888 testgridDashboardsAnnotation: "google-unit, sig-release-job-config-errors", 889 }, 890 }, 891 Brancher: config.Brancher{ 892 Branches: []string{"release-1.15"}, 893 }, 894 }, 895 { 896 JobBase: config.JobBase{ 897 Name: "post-replace-some-things-1-15", 898 Annotations: map[string]string{ 899 "some-annotation": "yup", 900 testgridDashboardsAnnotation: "sig-release-job-config-errors", 901 }, 902 Spec: &v1.PodSpec{ 903 Containers: []v1.Container{ 904 { 905 Image: "gcr.io/k8s-staging-test-infra/kubekins-e2e:blahblahblah-1.15", 906 Command: []string{"--args1=test", "--something=1.15"}, 907 Args: []string{"--repo=k8s.io/kubernetes", "--something=1.15"}, 908 Env: []v1.EnvVar{{Name: "BRANCH", Value: "release-1.15"}, {Name: "GO_VERSION", Value: "1.20.2"}}, 909 }, 910 }, 911 }, 912 }, 913 Brancher: config.Brancher{ 914 Branches: []string{"release-1.15"}, 915 }, 916 }, 917 }, 918 } 919 920 result, err := generatePostsubmits(config.JobConfig{PostsubmitsStatic: postsubmits}, templateVars{Version: "1.15", GoVersion: "1.20.2"}) 921 if err != nil { 922 t.Fatalf("Unexpected error: %v", err) 923 } 924 925 if !reflect.DeepEqual(result, expected) { 926 t.Errorf("Result does not match expected. Difference:\n%s", diff.ObjectDiff(expected, result)) 927 } 928 }