From 5be97255830d41518345e70799414c5e4a47c287 Mon Sep 17 00:00:00 2001 From: Cole Wagner Date: Thu, 28 Jan 2021 21:33:40 -0800 Subject: [PATCH] Add support for alternate default_decoration_configs format that allows defaulting by cluster. --- config/tests/jobs/jobs_test.go | 12 +- prow/cmd/checkconfig/main.go | 6 +- prow/cmd/deck/pr_history.go | 6 +- prow/cmd/deck/pr_history_test.go | 36 +- prow/config/config.go | 224 +++-- prow/config/config_test.go | 906 +++++++++--------- prow/config/prow-config-documented.yaml | 137 +-- .../crier/reporters/gcs/internal/util/util.go | 15 +- .../reporters/gcs/internal/util/util_test.go | 2 +- .../reporters/gcs/kubernetes/reporter_test.go | 19 +- prow/crier/reporters/gcs/reporter_test.go | 57 +- prow/spyglass/spyglass.go | 5 +- prow/spyglass/spyglass_test.go | 34 +- prow/test/BUILD.bazel | 2 + .../test/integration/fakeghserver/BUILD.bazel | 5 +- releng/config-forker/BUILD.bazel | 2 + releng/config-forker/main.go | 11 +- releng/config-forker/main_test.go | 4 +- testgrid/cmd/configurator/prow.go | 4 +- testgrid/cmd/configurator/prow_test.go | 13 +- 20 files changed, 760 insertions(+), 740 deletions(-) diff --git a/config/tests/jobs/jobs_test.go b/config/tests/jobs/jobs_test.go index 2447a4b98740f..d5524b1a5747e 100644 --- a/config/tests/jobs/jobs_test.go +++ b/config/tests/jobs/jobs_test.go @@ -700,7 +700,7 @@ func TestValidPresets(t *testing.T) { } for _, presubmit := range c.AllStaticPresubmits(nil) { - if presubmit.Spec != nil && !cfg.ShouldDecorate(&c.JobConfig, presubmit.JobBase.UtilityConfig) { + if presubmit.Spec != nil && !*presubmit.Decorate { if err := checkKubekinsPresets(presubmit.Name, presubmit.Spec, presubmit.Labels, validLabels); err != nil { t.Errorf("Error in presubmit %q: %v", presubmit.Name, err) } @@ -708,7 +708,7 @@ func TestValidPresets(t *testing.T) { } for _, postsubmit := range c.AllStaticPostsubmits(nil) { - if postsubmit.Spec != nil && !cfg.ShouldDecorate(&c.JobConfig, postsubmit.JobBase.UtilityConfig) { + if postsubmit.Spec != nil && !*postsubmit.Decorate { if err := checkKubekinsPresets(postsubmit.Name, postsubmit.Spec, postsubmit.Labels, validLabels); err != nil { t.Errorf("Error in postsubmit %q: %v", postsubmit.Name, err) } @@ -716,7 +716,7 @@ func TestValidPresets(t *testing.T) { } for _, periodic := range c.AllPeriodics() { - if periodic.Spec != nil && !cfg.ShouldDecorate(&c.JobConfig, periodic.JobBase.UtilityConfig) { + if periodic.Spec != nil && !*periodic.Decorate { if err := checkKubekinsPresets(periodic.Name, periodic.Spec, periodic.Labels, validLabels); err != nil { t.Errorf("Error in periodic %q: %v", periodic.Name, err) } @@ -902,7 +902,7 @@ func checkScenarioArgs(jobName, imageName string, args []string) error { // TestValidScenarioArgs makes sure all scenario args in job configs are valid func TestValidScenarioArgs(t *testing.T) { for _, job := range c.AllStaticPresubmits(nil) { - if job.Spec != nil && !cfg.ShouldDecorate(&c.JobConfig, job.JobBase.UtilityConfig) { + if job.Spec != nil && !*job.Decorate { if err := checkScenarioArgs(job.Name, job.Spec.Containers[0].Image, job.Spec.Containers[0].Args); err != nil { t.Errorf("Invalid Scenario Args : %s", err) } @@ -910,7 +910,7 @@ func TestValidScenarioArgs(t *testing.T) { } for _, job := range c.AllStaticPostsubmits(nil) { - if job.Spec != nil && !cfg.ShouldDecorate(&c.JobConfig, job.JobBase.UtilityConfig) { + if job.Spec != nil && !*job.Decorate { if err := checkScenarioArgs(job.Name, job.Spec.Containers[0].Image, job.Spec.Containers[0].Args); err != nil { t.Errorf("Invalid Scenario Args : %s", err) } @@ -918,7 +918,7 @@ func TestValidScenarioArgs(t *testing.T) { } for _, job := range c.AllPeriodics() { - if job.Spec != nil && !cfg.ShouldDecorate(&c.JobConfig, job.JobBase.UtilityConfig) { + if job.Spec != nil && !*job.Decorate { if err := checkScenarioArgs(job.Name, job.Spec.Containers[0].Image, job.Spec.Containers[0].Args); err != nil { t.Errorf("Invalid Scenario Args : %s", err) } diff --git a/prow/cmd/checkconfig/main.go b/prow/cmd/checkconfig/main.go index 83bc8e4739e89..6e5f1479d5bdc 100644 --- a/prow/cmd/checkconfig/main.go +++ b/prow/cmd/checkconfig/main.go @@ -805,19 +805,19 @@ func ensureValidConfiguration(plugin, label, verb string, tideSubSet, tideSuperS func validateDecoratedJobs(cfg *config.Config) error { var nonDecoratedJobs []string for _, presubmit := range cfg.AllStaticPresubmits([]string{}) { - if presubmit.Agent == string(v1.KubernetesAgent) && !config.ShouldDecorate(&cfg.JobConfig, presubmit.JobBase.UtilityConfig) { + if presubmit.Agent == string(v1.KubernetesAgent) && !*presubmit.JobBase.UtilityConfig.Decorate { nonDecoratedJobs = append(nonDecoratedJobs, presubmit.Name) } } for _, postsubmit := range cfg.AllStaticPostsubmits([]string{}) { - if postsubmit.Agent == string(v1.KubernetesAgent) && !config.ShouldDecorate(&cfg.JobConfig, postsubmit.JobBase.UtilityConfig) { + if postsubmit.Agent == string(v1.KubernetesAgent) && !*postsubmit.JobBase.UtilityConfig.Decorate { nonDecoratedJobs = append(nonDecoratedJobs, postsubmit.Name) } } for _, periodic := range cfg.AllPeriodics() { - if periodic.Agent == string(v1.KubernetesAgent) && !config.ShouldDecorate(&cfg.JobConfig, periodic.JobBase.UtilityConfig) { + if periodic.Agent == string(v1.KubernetesAgent) && !*periodic.JobBase.UtilityConfig.Decorate { nonDecoratedJobs = append(nonDecoratedJobs, periodic.Name) } } diff --git a/prow/cmd/deck/pr_history.go b/prow/cmd/deck/pr_history.go index 4a8be66e6a0da..07eb040a458e3 100644 --- a/prow/cmd/deck/pr_history.go +++ b/prow/cmd/deck/pr_history.go @@ -227,7 +227,11 @@ func getStorageDirsForPR(c *config.Config, gitHubClient deckGitHubClient, gitCli gcsConfig = presubmit.DecorationConfig.GCSConfiguration } else { // for undecorated jobs assume the default - gcsConfig = c.Plank.GetDefaultDecorationConfigs(fullRepo).GCSConfiguration + def := c.Plank.MergeDefaultDecorationConfig(fullRepo, presubmit.Cluster, nil) + if def == nil || def.GCSConfiguration == nil { + return toSearch, fmt.Errorf("failed to guess gcs config based on default decoration config: %w", err) + } + gcsConfig = def.GCSConfiguration } gcsPath, _, _ := gcsupload.PathsForJob(gcsConfig, &downwardapi.JobSpec{ diff --git a/prow/cmd/deck/pr_history_test.go b/prow/cmd/deck/pr_history_test.go index 8d7e6645c0f8a..630b8136636b2 100644 --- a/prow/cmd/deck/pr_history_test.go +++ b/prow/cmd/deck/pr_history_test.go @@ -435,16 +435,17 @@ func TestGetGCSDirsForPR(t *testing.T) { config: &config.Config{ ProwConfig: config.ProwConfig{ Plank: config.Plank{ - DefaultDecorationConfigs: map[string]*prowapi.DecorationConfig{ - "*": { - GCSConfiguration: &prowapi.GCSConfiguration{ - Bucket: "krusty-krab", - PathStrategy: "legacy", - DefaultOrg: "kubernetes", - DefaultRepo: "kubernetes", + DefaultDecorationConfigs: config.DefaultDecorationMapToSliceTesting( + map[string]*prowapi.DecorationConfig{ + "*": { + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "krusty-krab", + PathStrategy: "legacy", + DefaultOrg: "kubernetes", + DefaultRepo: "kubernetes", + }, }, - }, - }, + }), }, }, JobConfig: config.JobConfig{ @@ -532,15 +533,16 @@ func Test_getPRHistory(t *testing.T) { }, ProwConfig: config.ProwConfig{ Plank: config.Plank{ - DefaultDecorationConfigs: map[string]*prowapi.DecorationConfig{ - "*": { - GCSConfiguration: &prowapi.GCSConfiguration{ - Bucket: "gs://kubernetes-jenkins", - PathStrategy: prowapi.PathStrategyLegacy, - DefaultOrg: "kubernetes", + DefaultDecorationConfigs: config.DefaultDecorationMapToSliceTesting( + map[string]*prowapi.DecorationConfig{ + "*": { + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "gs://kubernetes-jenkins", + PathStrategy: prowapi.PathStrategyLegacy, + DefaultOrg: "kubernetes", + }, }, - }, - }, + }), }, Deck: config.Deck{ AllKnownStorageBuckets: sets.NewString("kubernetes-jenkins"), diff --git a/prow/config/config.go b/prow/config/config.go index fe2cdf1c446f7..90c500cbe4fd7 100644 --- a/prow/config/config.go +++ b/prow/config/config.go @@ -484,11 +484,20 @@ type Plank struct { // PodUnscheduledTimeout is after how long the controller will abort a prowjob // stuck in an unscheduled state. Defaults to one day. PodUnscheduledTimeout *metav1.Duration `json:"pod_unscheduled_timeout,omitempty"` + // DefaultDecorationConfigs holds the default decoration config for specific values. - // This config will be used on each Presubmit and Postsubmit's corresponding org/repo, and on Periodics - // if extraRefs[0] exists. - // Use `org/repo`, `org` or `*` as a key. - DefaultDecorationConfigs map[string]*prowapi.DecorationConfig `json:"default_decoration_configs,omitempty"` + // Each entry in the slice specifies Repo and Cluster regexp filter fields to + // match against jobs and a corresponding DecorationConfig. All entries that + // match a job are used. Later matching entries override the fields of earlier + // matching entries. + // Alternatively this field may be type `map[string]*prowapi.DecorationConfig` + // Use `org/repo`, `org` or `*` as a key to match against jobs. (Periodics + // use extra_refs[0] for matching if present.) + DefaultDecorationConfigs []*DefaultDecorationConfigEntry `json:"-"` + // DefaultDecorationConfigsRaw compiles into DefaultDecorationConfigs. + // It may represent either `[]*DefaultDecorationConfigEntry` or + // `map[string]*prowapi.DecorationConfig`. + DefaultDecorationConfigsRaw *json.RawMessage `json:"default_decoration_configs,omitempty"` // JobURLPrefixConfig is the host and path prefix under which job details // will be viewable. Use `org/repo`, `org` or `*`as key and an url as value @@ -499,16 +508,123 @@ type Plank struct { JobURLPrefixDisableAppendStorageProvider bool `json:"jobURLPrefixDisableAppendStorageProvider,omitempty"` } -func (p Plank) GetDefaultDecorationConfigs(repo string) *prowapi.DecorationConfig { - def := p.DefaultDecorationConfigs["*"] - if dcByRepo, ok := p.DefaultDecorationConfigs[repo]; ok { - return dcByRepo.ApplyDefault(def) +type DefaultDecorationConfigEntry struct { + // Matching/filtering fields + + // Repo matches against the "org/repo" that the presubmit or postsubmit is + // associated with. If the job is a periodic, extra_refs[0] is used. If the + // job is a periodic without extra_refs, the empty string will be used. + Repo *regexp.Regexp `json:"-"` + // OrgRepoRaw is the string field that compiles into the Repo regexp field. + RepoRaw string `json:"repo,omitempty"` + // Cluster matches against the cluster alias of the build cluster that the + // ProwJob is configured to run on. Recall that ProwJobs default to running on + // the "default" build cluster if they omit the "cluster" field in config. + Cluster *regexp.Regexp `json:"-"` + // ClusterRaw is the string field that compiles into the Cluster regexp field. + ClusterRaw string `json:"cluster,omitempty"` + + // Config is the DecorationConfig to apply if the filter fields all match the + // ProwJob. Note that when multiple entries match a ProwJob they are all used + // by sequentially merging with later entries overriding fields from earlier + // entries. + Config *prowapi.DecorationConfig `json:"config,omitempty"` +} + +func (d *DefaultDecorationConfigEntry) Matches(repo, cluster string) bool { + return d.Repo.MatchString(repo) && d.Cluster.MatchString(cluster) +} + +func (p *Plank) MergeDefaultDecorationConfig(repo, cluster string, jobDC *prowapi.DecorationConfig) *prowapi.DecorationConfig { + var merged *prowapi.DecorationConfig + for _, entry := range p.DefaultDecorationConfigs { + if entry.Matches(repo, cluster) { + merged = entry.Config.ApplyDefault(merged) + } } - org := strings.Split(repo, "/")[0] - if dcByOrg, ok := p.DefaultDecorationConfigs[org]; ok { - return dcByOrg.ApplyDefault(def) + merged = jobDC.ApplyDefault(merged) + if merged == nil { + merged = &prowapi.DecorationConfig{} } - return def + return merged +} + +// defaultDecorationMapToSlice converts the old DefaultDecorationConfigs format: +// map[string]*prowapi.DecorationConfig) to the new format: []*DefaultDecorationConfigEntry +func defaultDecorationMapToSlice(m map[string]*prowapi.DecorationConfig) []*DefaultDecorationConfigEntry { + var entries []*DefaultDecorationConfigEntry + add := func(repo string, dc *prowapi.DecorationConfig) { + entries = append(entries, &DefaultDecorationConfigEntry{ + RepoRaw: repo, + ClusterRaw: ".*", + Config: dc, + }) + } + // Ensure "*" comes first... + if dc, exists := m["*"]; exists { + add(".*", dc) + } + // then orgs... + for key, dc := range m { + if key == "*" || strings.Contains(key, "/") { + continue + } + add(fmt.Sprintf("^%s/.*", key), dc) + } + // then repos. + for key, dc := range m { + if key == "*" || !strings.Contains(key, "/") { + continue + } + add(fmt.Sprintf("^%s$", key), dc) + } + return entries +} + +func compileDefaultDecorationRegex(entries []*DefaultDecorationConfigEntry) error { + var errs []error + for i, entry := range entries { + var err error + if entry.Repo, err = regexp.Compile(entry.RepoRaw); err != nil { + err = fmt.Errorf("compiling repo regex for plank.default_decoration_configs[%d]: %w", i, err) + errs = append(errs, err) + } + if entry.Cluster, err = regexp.Compile(entry.ClusterRaw); err != nil { + err = fmt.Errorf("compiling cluster regex for plank.default_decoration_configs[%d]: %w", i, err) + errs = append(errs, err) + } + } + return utilerrors.NewAggregate(errs) +} + +// DefaultDecorationMapToSliceTesting is a convenience function that is exposed +// to allow unit tests to convert the old map format to the new slice format. +// It should only be used in testing. +func DefaultDecorationMapToSliceTesting(m map[string]*prowapi.DecorationConfig) []*DefaultDecorationConfigEntry { + slice := defaultDecorationMapToSlice(m) + if err := compileDefaultDecorationRegex(slice); err != nil { + panic(err) + } + return slice +} + +func (p *Plank) FinalizeDefaultDecorationConfigs() error { + if p.DefaultDecorationConfigsRaw == nil { + return nil + } + // Try parsing either accepted config format. + // Old format: map[string]*prowapi.DecorationConfig where the key is org, + // org/repo, or "*". + // New format: []*DefaultDecorationConfigEntry + var old map[string]*prowapi.DecorationConfig + if oldErr := yaml.Unmarshal(*p.DefaultDecorationConfigsRaw, &old); oldErr != nil { + if newErr := yaml.Unmarshal(*p.DefaultDecorationConfigsRaw, &p.DefaultDecorationConfigs); newErr != nil { + return fmt.Errorf("failed to parse plank.default_decoration_configs in either accepted format: %w", utilerrors.NewAggregate([]error{newErr, oldErr})) + } + } else { + p.DefaultDecorationConfigs = defaultDecorationMapToSlice(old) + } + return compileDefaultDecorationRegex(p.DefaultDecorationConfigs) } // GetJobURLPrefix gets the job url prefix from the config @@ -802,7 +918,7 @@ func (d *Deck) ShouldValidateStorageBuckets() bool { func calculateStorageBuckets(c *Config) sets.String { knownBuckets := sets.NewString(c.Deck.AdditionalAllowedBuckets...) for _, dc := range c.Plank.DefaultDecorationConfigs { - knownBuckets.Insert(dc.GCSConfiguration.Bucket) + knownBuckets.Insert(dc.Config.GCSConfiguration.Bucket) } for _, j := range c.Periodics { if j.DecorationConfig != nil && j.DecorationConfig.GCSConfiguration != nil { @@ -1241,36 +1357,36 @@ func mergeJobConfigs(a, b JobConfig) (JobConfig, error) { return c, nil } -func ShouldDecorate(c *JobConfig, util UtilityConfig) bool { +func shouldDecorate(c *JobConfig, util *UtilityConfig) bool { if util.Decorate != nil { return *util.Decorate + } else { + b := c.DecorateAllJobs + util.Decorate = &b } return c.DecorateAllJobs } func setPresubmitDecorationDefaults(c *Config, ps *Presubmit, repo string) { - if ShouldDecorate(&c.JobConfig, ps.JobBase.UtilityConfig) { - def := c.Plank.GetDefaultDecorationConfigs(repo) - ps.DecorationConfig = ps.DecorationConfig.ApplyDefault(def) + if shouldDecorate(&c.JobConfig, &ps.JobBase.UtilityConfig) { + ps.DecorationConfig = c.Plank.MergeDefaultDecorationConfig(repo, ps.Cluster, ps.DecorationConfig) } } func setPostsubmitDecorationDefaults(c *Config, ps *Postsubmit, repo string) { - if ShouldDecorate(&c.JobConfig, ps.JobBase.UtilityConfig) { - def := c.Plank.GetDefaultDecorationConfigs(repo) - ps.DecorationConfig = ps.DecorationConfig.ApplyDefault(def) + if shouldDecorate(&c.JobConfig, &ps.JobBase.UtilityConfig) { + ps.DecorationConfig = c.Plank.MergeDefaultDecorationConfig(repo, ps.Cluster, ps.DecorationConfig) } } func setPeriodicDecorationDefaults(c *Config, ps *Periodic) { - if ShouldDecorate(&c.JobConfig, ps.JobBase.UtilityConfig) { - var orgRepo string + if shouldDecorate(&c.JobConfig, &ps.JobBase.UtilityConfig) { + var repo string if len(ps.UtilityConfig.ExtraRefs) > 0 { - orgRepo = fmt.Sprintf("%s/%s", ps.UtilityConfig.ExtraRefs[0].Org, ps.UtilityConfig.ExtraRefs[0].Repo) + repo = fmt.Sprintf("%s/%s", ps.UtilityConfig.ExtraRefs[0].Org, ps.UtilityConfig.ExtraRefs[0].Repo) } - def := c.Plank.GetDefaultDecorationConfigs(orgRepo) - ps.DecorationConfig = ps.DecorationConfig.ApplyDefault(def) + ps.DecorationConfig = c.Plank.MergeDefaultDecorationConfig(repo, ps.Cluster, ps.DecorationConfig) } } @@ -1307,36 +1423,24 @@ func defaultPostsubmits(postsubmits []Postsubmit, c *Config, repo string) error return utilerrors.NewAggregate(errs) } -// defaultPeriodics defaults periodics -func defaultPeriodics(periodics []Periodic, c *Config) error { +// defaultPeriodics defaults c.Periodics +func defaultPeriodics(c *Config) error { var errs []error - c.defaultPeriodicFields(periodics) - for _, periodic := range periodics { - if err := resolvePresets(periodic.Name, periodic.Labels, periodic.Spec, c.Presets); err != nil { + + for i := range c.Periodics { + setPeriodicDecorationDefaults(c, &c.Periodics[i]) + if err := resolvePresets(c.Periodics[i].Name, c.Periodics[i].Labels, c.Periodics[i].Spec, c.Presets); err != nil { errs = append(errs, err) } } + c.defaultPeriodicFields(c.Periodics) return utilerrors.NewAggregate(errs) } // finalizeJobConfig mutates and fixes entries for jobspecs func (c *Config) finalizeJobConfig() error { - if c.decorationRequested() { - - def, ok := c.Plank.DefaultDecorationConfigs["*"] - if !ok { - return errors.New("default_decoration_configs['*'] is missing") - } - - for key, valCfg := range c.Plank.DefaultDecorationConfigs { - if err := valCfg.ApplyDefault(def).Validate(); err != nil { - return fmt.Errorf("default_decoration_configs[%q]: validation error: %v", key, err) - } - } - - for i := range c.Periodics { - setPeriodicDecorationDefaults(c, &c.Periodics[i]) - } + if err := c.Plank.FinalizeDefaultDecorationConfigs(); err != nil { + return err } for repo, jobs := range c.PresubmitsStatic { @@ -1353,7 +1457,7 @@ func (c *Config) finalizeJobConfig() error { c.AllRepos.Insert(repo) } - if err := defaultPeriodics(c.Periodics, c); err != nil { + if err := defaultPeriodics(c); err != nil { return err } @@ -1891,32 +1995,6 @@ func parseProwConfig(c *Config) error { return nil } -func (c *JobConfig) decorationRequested() bool { - for _, vs := range c.PresubmitsStatic { - for i := range vs { - if ShouldDecorate(c, vs[i].JobBase.UtilityConfig) { - return true - } - } - } - - for _, js := range c.PostsubmitsStatic { - for i := range js { - if ShouldDecorate(c, js[i].JobBase.UtilityConfig) { - return true - } - } - } - - for i := range c.Periodics { - if ShouldDecorate(c, c.Periodics[i].JobBase.UtilityConfig) { - return true - } - } - - return false -} - func validateLabels(labels map[string]string) error { for label, value := range labels { for _, prowLabel := range decorate.Labels() { diff --git a/prow/config/config_test.go b/prow/config/config_test.go index ed7062575e7f2..9e83371de2c15 100644 --- a/prow/config/config_test.go +++ b/prow/config/config_test.go @@ -23,6 +23,7 @@ import ( "os" "path/filepath" "reflect" + "regexp" "strings" "sync" "testing" @@ -3598,7 +3599,7 @@ func TestSetDecorationDefaults(t *testing.T) { id: "no dc in presubmit or in plank's config, expect no changes", utilityConfig: UtilityConfig{Decorate: &yes}, config: &Config{ProwConfig: ProwConfig{}}, - expected: nil, + expected: &prowapi.DecorationConfig{}, }, { id: "no dc in presubmit or in plank's by repo config, expect plank's defaults", @@ -3606,21 +3607,25 @@ func TestSetDecorationDefaults(t *testing.T) { config: &Config{ ProwConfig: ProwConfig{ Plank: Plank{ - DefaultDecorationConfigs: map[string]*prowapi.DecorationConfig{ - "*": { - UtilityImages: &prowapi.UtilityImages{ - CloneRefs: "clonerefs:test", - InitUpload: "initupload:test", - Entrypoint: "entrypoint:test", - Sidecar: "sidecar:test", + DefaultDecorationConfigs: []*DefaultDecorationConfigEntry{ + { + Repo: regexp.MustCompile(".*"), + Cluster: regexp.MustCompile(""), + Config: &prowapi.DecorationConfig{ + UtilityImages: &prowapi.UtilityImages{ + CloneRefs: "clonerefs:test", + InitUpload: "initupload:test", + Entrypoint: "entrypoint:test", + Sidecar: "sidecar:test", + }, + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "test-bucket", + PathStrategy: "single", + DefaultOrg: "org", + DefaultRepo: "repo", + }, + GCSCredentialsSecret: pStr("credentials-gcs"), }, - GCSConfiguration: &prowapi.GCSConfiguration{ - Bucket: "test-bucket", - PathStrategy: "single", - DefaultOrg: "org", - DefaultRepo: "repo", - }, - GCSCredentialsSecret: pStr("credentials-gcs"), }, }, }, @@ -3649,28 +3654,36 @@ func TestSetDecorationDefaults(t *testing.T) { config: &Config{ ProwConfig: ProwConfig{ Plank: Plank{ - DefaultDecorationConfigs: map[string]*prowapi.DecorationConfig{ - "*": { - UtilityImages: &prowapi.UtilityImages{ - CloneRefs: "clonerefs:test", - InitUpload: "initupload:test", - Entrypoint: "entrypoint:test", - Sidecar: "sidecar:test", - }, - GCSConfiguration: &prowapi.GCSConfiguration{ - Bucket: "test-bucket", - PathStrategy: "single", - DefaultOrg: "org", - DefaultRepo: "repo", + DefaultDecorationConfigs: []*DefaultDecorationConfigEntry{ + { + Repo: regexp.MustCompile(".*"), + Cluster: regexp.MustCompile(""), + Config: &prowapi.DecorationConfig{ + UtilityImages: &prowapi.UtilityImages{ + CloneRefs: "clonerefs:test", + InitUpload: "initupload:test", + Entrypoint: "entrypoint:test", + Sidecar: "sidecar:test", + }, + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "test-bucket", + PathStrategy: "single", + DefaultOrg: "org", + DefaultRepo: "repo", + }, + GCSCredentialsSecret: pStr("credentials-gcs"), }, - GCSCredentialsSecret: pStr("credentials-gcs"), }, - "org/repo": { - GCSConfiguration: &prowapi.GCSConfiguration{ - Bucket: "test-bucket-by-repo", - PathStrategy: "single-by-repo", - DefaultOrg: "org-by-repo", - DefaultRepo: "repo-by-repo", + { + Repo: regexp.MustCompile("org/repo"), + Cluster: regexp.MustCompile(""), + Config: &prowapi.DecorationConfig{ + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "test-bucket-by-repo", + PathStrategy: "single-by-repo", + DefaultOrg: "org-by-repo", + DefaultRepo: "repo-by-repo", + }, }, }, }, @@ -3717,21 +3730,25 @@ func TestSetDecorationDefaults(t *testing.T) { config: &Config{ ProwConfig: ProwConfig{ Plank: Plank{ - DefaultDecorationConfigs: map[string]*prowapi.DecorationConfig{ - "*": { - UtilityImages: &prowapi.UtilityImages{ - CloneRefs: "clonerefs:test", - InitUpload: "initupload:test", - Entrypoint: "entrypoint:test", - Sidecar: "sidecar:test", - }, - GCSConfiguration: &prowapi.GCSConfiguration{ - Bucket: "test-bucket", - PathStrategy: "single", - DefaultOrg: "org", - DefaultRepo: "repo", + DefaultDecorationConfigs: []*DefaultDecorationConfigEntry{ + { + Repo: regexp.MustCompile(".*"), + Cluster: regexp.MustCompile(""), + Config: &prowapi.DecorationConfig{ + UtilityImages: &prowapi.UtilityImages{ + CloneRefs: "clonerefs:test", + InitUpload: "initupload:test", + Entrypoint: "entrypoint:test", + Sidecar: "sidecar:test", + }, + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "test-bucket", + PathStrategy: "single", + DefaultOrg: "org", + DefaultRepo: "repo", + }, + GCSCredentialsSecret: pStr("credentials-gcs"), }, - GCSCredentialsSecret: pStr("credentials-gcs"), }, }, }, @@ -3777,36 +3794,44 @@ func TestSetDecorationDefaults(t *testing.T) { config: &Config{ ProwConfig: ProwConfig{ Plank: Plank{ - DefaultDecorationConfigs: map[string]*prowapi.DecorationConfig{ - "*": { - UtilityImages: &prowapi.UtilityImages{ - CloneRefs: "clonerefs:test", - InitUpload: "initupload:test", - Entrypoint: "entrypoint:test", - Sidecar: "sidecar:test", + DefaultDecorationConfigs: []*DefaultDecorationConfigEntry{ + { + Repo: regexp.MustCompile(".*"), + Cluster: regexp.MustCompile(""), + Config: &prowapi.DecorationConfig{ + UtilityImages: &prowapi.UtilityImages{ + CloneRefs: "clonerefs:test", + InitUpload: "initupload:test", + Entrypoint: "entrypoint:test", + Sidecar: "sidecar:test", + }, + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "test-bucket", + PathStrategy: "single", + DefaultOrg: "org", + DefaultRepo: "repo", + }, + GCSCredentialsSecret: pStr("credentials-gcs"), }, - GCSConfiguration: &prowapi.GCSConfiguration{ - Bucket: "test-bucket", - PathStrategy: "single", - DefaultOrg: "org", - DefaultRepo: "repo", - }, - GCSCredentialsSecret: pStr("credentials-gcs"), }, - "org/repo": { - UtilityImages: &prowapi.UtilityImages{ - CloneRefs: "clonerefs:test-by-repo", - InitUpload: "initupload:test-by-repo", - Entrypoint: "entrypoint:test-by-repo", - Sidecar: "sidecar:test-by-repo", - }, - GCSConfiguration: &prowapi.GCSConfiguration{ - Bucket: "test-bucket-by-repo", - PathStrategy: "single", - DefaultOrg: "org-test", - DefaultRepo: "repo-test", + { + Repo: regexp.MustCompile("org/repo"), + Cluster: regexp.MustCompile(""), + Config: &prowapi.DecorationConfig{ + UtilityImages: &prowapi.UtilityImages{ + CloneRefs: "clonerefs:test-by-repo", + InitUpload: "initupload:test-by-repo", + Entrypoint: "entrypoint:test-by-repo", + Sidecar: "sidecar:test-by-repo", + }, + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "test-bucket-by-repo", + PathStrategy: "single", + DefaultOrg: "org-test", + DefaultRepo: "repo-test", + }, + GCSCredentialsSecret: pStr("credentials-gcs"), }, - GCSCredentialsSecret: pStr("credentials-gcs"), }, }, }, @@ -3835,36 +3860,44 @@ func TestSetDecorationDefaults(t *testing.T) { config: &Config{ ProwConfig: ProwConfig{ Plank: Plank{ - DefaultDecorationConfigs: map[string]*prowapi.DecorationConfig{ - "*": { - UtilityImages: &prowapi.UtilityImages{ - CloneRefs: "clonerefs:test", - InitUpload: "initupload:test", - Entrypoint: "entrypoint:test", - Sidecar: "sidecar:test", + DefaultDecorationConfigs: []*DefaultDecorationConfigEntry{ + { + Repo: regexp.MustCompile(".*"), + Cluster: regexp.MustCompile(""), + Config: &prowapi.DecorationConfig{ + UtilityImages: &prowapi.UtilityImages{ + CloneRefs: "clonerefs:test", + InitUpload: "initupload:test", + Entrypoint: "entrypoint:test", + Sidecar: "sidecar:test", + }, + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "test-bucket", + PathStrategy: "single", + DefaultOrg: "org", + DefaultRepo: "repo", + }, + GCSCredentialsSecret: pStr("credentials-gcs"), }, - GCSConfiguration: &prowapi.GCSConfiguration{ - Bucket: "test-bucket", - PathStrategy: "single", - DefaultOrg: "org", - DefaultRepo: "repo", - }, - GCSCredentialsSecret: pStr("credentials-gcs"), }, - "org/repo": { - UtilityImages: &prowapi.UtilityImages{ - CloneRefs: "clonerefs:test-by-repo", - InitUpload: "initupload:test-by-repo", - Entrypoint: "entrypoint:test-by-repo", - Sidecar: "sidecar:test-by-repo", - }, - GCSConfiguration: &prowapi.GCSConfiguration{ - Bucket: "test-bucket-by-repo", - PathStrategy: "single-by-repo", - DefaultOrg: "org-by-repo", - DefaultRepo: "repo-by-repo", + { + Repo: regexp.MustCompile("org/repo"), + Cluster: regexp.MustCompile(""), + Config: &prowapi.DecorationConfig{ + UtilityImages: &prowapi.UtilityImages{ + CloneRefs: "clonerefs:test-by-repo", + InitUpload: "initupload:test-by-repo", + Entrypoint: "entrypoint:test-by-repo", + Sidecar: "sidecar:test-by-repo", + }, + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "test-bucket-by-repo", + PathStrategy: "single-by-repo", + DefaultOrg: "org-by-repo", + DefaultRepo: "repo-by-repo", + }, + GCSCredentialsSecret: pStr("credentials-gcs-by-repo"), }, - GCSCredentialsSecret: pStr("credentials-gcs-by-repo"), }, }, }, @@ -3893,36 +3926,44 @@ func TestSetDecorationDefaults(t *testing.T) { config: &Config{ ProwConfig: ProwConfig{ Plank: Plank{ - DefaultDecorationConfigs: map[string]*prowapi.DecorationConfig{ - "*": { - UtilityImages: &prowapi.UtilityImages{ - CloneRefs: "clonerefs:test", - InitUpload: "initupload:test", - Entrypoint: "entrypoint:test", - Sidecar: "sidecar:test", - }, - GCSConfiguration: &prowapi.GCSConfiguration{ - Bucket: "test-bucket", - PathStrategy: "single", - DefaultOrg: "org", - DefaultRepo: "repo", + DefaultDecorationConfigs: []*DefaultDecorationConfigEntry{ + { + Repo: regexp.MustCompile(".*"), + Cluster: regexp.MustCompile(""), + Config: &prowapi.DecorationConfig{ + UtilityImages: &prowapi.UtilityImages{ + CloneRefs: "clonerefs:test", + InitUpload: "initupload:test", + Entrypoint: "entrypoint:test", + Sidecar: "sidecar:test", + }, + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "test-bucket", + PathStrategy: "single", + DefaultOrg: "org", + DefaultRepo: "repo", + }, + GCSCredentialsSecret: pStr("credentials-gcs"), }, - GCSCredentialsSecret: pStr("credentials-gcs"), }, - "org": { - UtilityImages: &prowapi.UtilityImages{ - CloneRefs: "clonerefs:test-by-org", - InitUpload: "initupload:test-by-org", - Entrypoint: "entrypoint:test-by-org", - Sidecar: "sidecar:test-by-org", + { + Repo: regexp.MustCompile("org"), + Cluster: regexp.MustCompile(""), + Config: &prowapi.DecorationConfig{ + UtilityImages: &prowapi.UtilityImages{ + CloneRefs: "clonerefs:test-by-org", + InitUpload: "initupload:test-by-org", + Entrypoint: "entrypoint:test-by-org", + Sidecar: "sidecar:test-by-org", + }, + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "test-bucket-by-org", + PathStrategy: "single-by-org", + DefaultOrg: "org-by-org", + DefaultRepo: "repo-by-org", + }, + GCSCredentialsSecret: pStr("credentials-gcs-by-org"), }, - GCSConfiguration: &prowapi.GCSConfiguration{ - Bucket: "test-bucket-by-org", - PathStrategy: "single-by-org", - DefaultOrg: "org-by-org", - DefaultRepo: "repo-by-org", - }, - GCSCredentialsSecret: pStr("credentials-gcs-by-org"), }, }, }, @@ -3951,21 +3992,25 @@ func TestSetDecorationDefaults(t *testing.T) { config: &Config{ ProwConfig: ProwConfig{ Plank: Plank{ - DefaultDecorationConfigs: map[string]*prowapi.DecorationConfig{ - "*": { - UtilityImages: &prowapi.UtilityImages{ - CloneRefs: "clonerefs:test-by-*", - InitUpload: "initupload:test-by-*", - Entrypoint: "entrypoint:test-by-*", - Sidecar: "sidecar:test-by-*", - }, - GCSConfiguration: &prowapi.GCSConfiguration{ - Bucket: "test-bucket-by-*", - PathStrategy: "single-by-*", - DefaultOrg: "org-by-*", - DefaultRepo: "repo-by-*", + DefaultDecorationConfigs: []*DefaultDecorationConfigEntry{ + { + Repo: regexp.MustCompile(".*"), + Cluster: regexp.MustCompile(""), + Config: &prowapi.DecorationConfig{ + UtilityImages: &prowapi.UtilityImages{ + CloneRefs: "clonerefs:test-by-*", + InitUpload: "initupload:test-by-*", + Entrypoint: "entrypoint:test-by-*", + Sidecar: "sidecar:test-by-*", + }, + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "test-bucket-by-*", + PathStrategy: "single-by-*", + DefaultOrg: "org-by-*", + DefaultRepo: "repo-by-*", + }, + GCSCredentialsSecret: pStr("credentials-gcs-by-*"), }, - GCSCredentialsSecret: pStr("credentials-gcs-by-*"), }, }, }, @@ -3995,51 +4040,63 @@ func TestSetDecorationDefaults(t *testing.T) { config: &Config{ ProwConfig: ProwConfig{ Plank: Plank{ - DefaultDecorationConfigs: map[string]*prowapi.DecorationConfig{ - "*": { - UtilityImages: &prowapi.UtilityImages{ - CloneRefs: "clonerefs:test-by-*", - InitUpload: "initupload:test-by-*", - Entrypoint: "entrypoint:test-by-*", - Sidecar: "sidecar:test-by-*", + DefaultDecorationConfigs: []*DefaultDecorationConfigEntry{ + { + Repo: regexp.MustCompile(".*"), + Cluster: regexp.MustCompile(""), + Config: &prowapi.DecorationConfig{ + UtilityImages: &prowapi.UtilityImages{ + CloneRefs: "clonerefs:test-by-*", + InitUpload: "initupload:test-by-*", + Entrypoint: "entrypoint:test-by-*", + Sidecar: "sidecar:test-by-*", + }, + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "test-bucket-by-*", + PathStrategy: "single-by-*", + DefaultOrg: "org-by-*", + DefaultRepo: "repo-by-*", + }, + GCSCredentialsSecret: pStr("credentials-gcs-by-*"), }, - GCSConfiguration: &prowapi.GCSConfiguration{ - Bucket: "test-bucket-by-*", - PathStrategy: "single-by-*", - DefaultOrg: "org-by-*", - DefaultRepo: "repo-by-*", - }, - GCSCredentialsSecret: pStr("credentials-gcs-by-*"), }, - "org": { - UtilityImages: &prowapi.UtilityImages{ - CloneRefs: "clonerefs:test-by-org", - InitUpload: "initupload:test-by-org", - Entrypoint: "entrypoint:test-by-org", - Sidecar: "sidecar:test-by-org", - }, - GCSConfiguration: &prowapi.GCSConfiguration{ - Bucket: "test-bucket-by-org", - PathStrategy: "single-by-org", - DefaultOrg: "org-by-org", - DefaultRepo: "repo-by-org", + { + Repo: regexp.MustCompile("org"), + Cluster: regexp.MustCompile(""), + Config: &prowapi.DecorationConfig{ + UtilityImages: &prowapi.UtilityImages{ + CloneRefs: "clonerefs:test-by-org", + InitUpload: "initupload:test-by-org", + Entrypoint: "entrypoint:test-by-org", + Sidecar: "sidecar:test-by-org", + }, + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "test-bucket-by-org", + PathStrategy: "single-by-org", + DefaultOrg: "org-by-org", + DefaultRepo: "repo-by-org", + }, + GCSCredentialsSecret: pStr("credentials-gcs-by-org"), }, - GCSCredentialsSecret: pStr("credentials-gcs-by-org"), }, - "org/repo": { - UtilityImages: &prowapi.UtilityImages{ - CloneRefs: "clonerefs:test-by-org-repo", - InitUpload: "initupload:test-by-org-repo", - Entrypoint: "entrypoint:test-by-org-repo", - Sidecar: "sidecar:test-by-org-repo", - }, - GCSConfiguration: &prowapi.GCSConfiguration{ - Bucket: "test-bucket-by-org-repo", - PathStrategy: "single-by-org-repo", - DefaultOrg: "org-by-org-repo", - DefaultRepo: "repo-by-org-repo", + { + Repo: regexp.MustCompile("org/repo"), + Cluster: regexp.MustCompile(""), + Config: &prowapi.DecorationConfig{ + UtilityImages: &prowapi.UtilityImages{ + CloneRefs: "clonerefs:test-by-org-repo", + InitUpload: "initupload:test-by-org-repo", + Entrypoint: "entrypoint:test-by-org-repo", + Sidecar: "sidecar:test-by-org-repo", + }, + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "test-bucket-by-org-repo", + PathStrategy: "single-by-org-repo", + DefaultOrg: "org-by-org-repo", + DefaultRepo: "repo-by-org-repo", + }, + GCSCredentialsSecret: pStr("credentials-gcs-by-org-repo"), }, - GCSCredentialsSecret: pStr("credentials-gcs-by-org-repo"), }, }, }, @@ -4069,36 +4126,44 @@ func TestSetDecorationDefaults(t *testing.T) { config: &Config{ ProwConfig: ProwConfig{ Plank: Plank{ - DefaultDecorationConfigs: map[string]*prowapi.DecorationConfig{ - "*": { - UtilityImages: &prowapi.UtilityImages{ - CloneRefs: "clonerefs:test-by-*", - InitUpload: "initupload:test-by-*", - Entrypoint: "entrypoint:test-by-*", - Sidecar: "sidecar:test-by-*", + DefaultDecorationConfigs: []*DefaultDecorationConfigEntry{ + { + Repo: regexp.MustCompile(".*"), + Cluster: regexp.MustCompile(""), + Config: &prowapi.DecorationConfig{ + UtilityImages: &prowapi.UtilityImages{ + CloneRefs: "clonerefs:test-by-*", + InitUpload: "initupload:test-by-*", + Entrypoint: "entrypoint:test-by-*", + Sidecar: "sidecar:test-by-*", + }, + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "test-bucket-by-*", + PathStrategy: "single-by-*", + DefaultOrg: "org-by-*", + DefaultRepo: "repo-by-*", + }, + GCSCredentialsSecret: pStr("credentials-gcs-by-*"), }, - GCSConfiguration: &prowapi.GCSConfiguration{ - Bucket: "test-bucket-by-*", - PathStrategy: "single-by-*", - DefaultOrg: "org-by-*", - DefaultRepo: "repo-by-*", - }, - GCSCredentialsSecret: pStr("credentials-gcs-by-*"), }, - "org": { - UtilityImages: &prowapi.UtilityImages{ - CloneRefs: "clonerefs:test-by-org", - InitUpload: "initupload:test-by-org", - Entrypoint: "entrypoint:test-by-org", - Sidecar: "sidecar:test-by-org", - }, - GCSConfiguration: &prowapi.GCSConfiguration{ - Bucket: "test-bucket-by-org", - PathStrategy: "single-by-org", - DefaultOrg: "org-by-org", - DefaultRepo: "repo-by-org", + { + Repo: regexp.MustCompile("org"), + Cluster: regexp.MustCompile(""), + Config: &prowapi.DecorationConfig{ + UtilityImages: &prowapi.UtilityImages{ + CloneRefs: "clonerefs:test-by-org", + InitUpload: "initupload:test-by-org", + Entrypoint: "entrypoint:test-by-org", + Sidecar: "sidecar:test-by-org", + }, + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "test-bucket-by-org", + PathStrategy: "single-by-org", + DefaultOrg: "org-by-org", + DefaultRepo: "repo-by-org", + }, + GCSCredentialsSecret: pStr("credentials-gcs-by-org"), }, - GCSCredentialsSecret: pStr("credentials-gcs-by-org"), }, }, }, @@ -4128,21 +4193,25 @@ func TestSetDecorationDefaults(t *testing.T) { }, ProwConfig: ProwConfig{ Plank: Plank{ - DefaultDecorationConfigs: map[string]*prowapi.DecorationConfig{ - "*": { - UtilityImages: &prowapi.UtilityImages{ - CloneRefs: "clonerefs:test", - InitUpload: "initupload:test", - Entrypoint: "entrypoint:test", - Sidecar: "sidecar:test", + DefaultDecorationConfigs: []*DefaultDecorationConfigEntry{ + { + Repo: regexp.MustCompile(".*"), + Cluster: regexp.MustCompile(""), + Config: &prowapi.DecorationConfig{ + UtilityImages: &prowapi.UtilityImages{ + CloneRefs: "clonerefs:test", + InitUpload: "initupload:test", + Entrypoint: "entrypoint:test", + Sidecar: "sidecar:test", + }, + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "test-bucket", + PathStrategy: "single", + DefaultOrg: "org", + DefaultRepo: "repo", + }, + GCSCredentialsSecret: pStr("credentials-gcs"), }, - GCSConfiguration: &prowapi.GCSConfiguration{ - Bucket: "test-bucket", - PathStrategy: "single", - DefaultOrg: "org", - DefaultRepo: "repo", - }, - GCSCredentialsSecret: pStr("credentials-gcs"), }, }, }, @@ -4173,21 +4242,25 @@ func TestSetDecorationDefaults(t *testing.T) { }, ProwConfig: ProwConfig{ Plank: Plank{ - DefaultDecorationConfigs: map[string]*prowapi.DecorationConfig{ - "*": { - UtilityImages: &prowapi.UtilityImages{ - CloneRefs: "clonerefs:test", - InitUpload: "initupload:test", - Entrypoint: "entrypoint:test", - Sidecar: "sidecar:test", - }, - GCSConfiguration: &prowapi.GCSConfiguration{ - Bucket: "test-bucket", - PathStrategy: "single", - DefaultOrg: "org", - DefaultRepo: "repo", + DefaultDecorationConfigs: []*DefaultDecorationConfigEntry{ + { + Repo: regexp.MustCompile(".*"), + Cluster: regexp.MustCompile(""), + Config: &prowapi.DecorationConfig{ + UtilityImages: &prowapi.UtilityImages{ + CloneRefs: "clonerefs:test", + InitUpload: "initupload:test", + Entrypoint: "entrypoint:test", + Sidecar: "sidecar:test", + }, + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "test-bucket", + PathStrategy: "single", + DefaultOrg: "org", + DefaultRepo: "repo", + }, + GCSCredentialsSecret: pStr("credentials-gcs"), }, - GCSCredentialsSecret: pStr("credentials-gcs"), }, }, }, @@ -4228,21 +4301,25 @@ func TestSetPeriodicDecorationDefaults(t *testing.T) { config: &Config{ ProwConfig: ProwConfig{ Plank: Plank{ - DefaultDecorationConfigs: map[string]*prowapi.DecorationConfig{ - "*": { - UtilityImages: &prowapi.UtilityImages{ - CloneRefs: "clonerefs:test-by-*", - InitUpload: "initupload:test-by-*", - Entrypoint: "entrypoint:test-by-*", - Sidecar: "sidecar:test-by-*", - }, - GCSConfiguration: &prowapi.GCSConfiguration{ - Bucket: "test-bucket-by-*", - PathStrategy: "single-by-*", - DefaultOrg: "org-by-*", - DefaultRepo: "repo-by-*", + DefaultDecorationConfigs: []*DefaultDecorationConfigEntry{ + { + Repo: regexp.MustCompile(".*"), + Cluster: regexp.MustCompile(".*"), + Config: &prowapi.DecorationConfig{ + UtilityImages: &prowapi.UtilityImages{ + CloneRefs: "clonerefs:test-by-*", + InitUpload: "initupload:test-by-*", + Entrypoint: "entrypoint:test-by-*", + Sidecar: "sidecar:test-by-*", + }, + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "test-bucket-by-*", + PathStrategy: "single-by-*", + DefaultOrg: "org-by-*", + DefaultRepo: "repo-by-*", + }, + GCSCredentialsSecret: pStr("credentials-gcs-by-*"), }, - GCSCredentialsSecret: pStr("credentials-gcs-by-*"), }, }, }, @@ -4270,36 +4347,44 @@ func TestSetPeriodicDecorationDefaults(t *testing.T) { config: &Config{ ProwConfig: ProwConfig{ Plank: Plank{ - DefaultDecorationConfigs: map[string]*prowapi.DecorationConfig{ - "*": { - UtilityImages: &prowapi.UtilityImages{ - CloneRefs: "clonerefs:test-by-*", - InitUpload: "initupload:test-by-*", - Entrypoint: "entrypoint:test-by-*", - Sidecar: "sidecar:test-by-*", + DefaultDecorationConfigs: []*DefaultDecorationConfigEntry{ + { + Repo: regexp.MustCompile(".*"), + Cluster: regexp.MustCompile(""), + Config: &prowapi.DecorationConfig{ + UtilityImages: &prowapi.UtilityImages{ + CloneRefs: "clonerefs:test-by-*", + InitUpload: "initupload:test-by-*", + Entrypoint: "entrypoint:test-by-*", + Sidecar: "sidecar:test-by-*", + }, + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "test-bucket-by-*", + PathStrategy: "single-by-*", + DefaultOrg: "org-by-*", + DefaultRepo: "repo-by-*", + }, + GCSCredentialsSecret: pStr("credentials-gcs-by-*"), }, - GCSConfiguration: &prowapi.GCSConfiguration{ - Bucket: "test-bucket-by-*", - PathStrategy: "single-by-*", - DefaultOrg: "org-by-*", - DefaultRepo: "repo-by-*", - }, - GCSCredentialsSecret: pStr("credentials-gcs-by-*"), }, - "org": { - UtilityImages: &prowapi.UtilityImages{ - CloneRefs: "clonerefs:test-by-org", - InitUpload: "initupload:test-by-org", - Entrypoint: "entrypoint:test-by-org", - Sidecar: "sidecar:test-by-org", - }, - GCSConfiguration: &prowapi.GCSConfiguration{ - Bucket: "test-bucket-by-org", - PathStrategy: "single-by-org", - DefaultOrg: "org-by-org", - DefaultRepo: "repo-by-org", + { + Repo: regexp.MustCompile("org"), + Cluster: regexp.MustCompile(""), + Config: &prowapi.DecorationConfig{ + UtilityImages: &prowapi.UtilityImages{ + CloneRefs: "clonerefs:test-by-org", + InitUpload: "initupload:test-by-org", + Entrypoint: "entrypoint:test-by-org", + Sidecar: "sidecar:test-by-org", + }, + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "test-bucket-by-org", + PathStrategy: "single-by-org", + DefaultOrg: "org-by-org", + DefaultRepo: "repo-by-org", + }, + GCSCredentialsSecret: pStr("credentials-gcs-by-org"), }, - GCSCredentialsSecret: pStr("credentials-gcs-by-org"), }, }, }, @@ -4335,36 +4420,44 @@ func TestSetPeriodicDecorationDefaults(t *testing.T) { config: &Config{ ProwConfig: ProwConfig{ Plank: Plank{ - DefaultDecorationConfigs: map[string]*prowapi.DecorationConfig{ - "*": { - UtilityImages: &prowapi.UtilityImages{ - CloneRefs: "clonerefs:test-by-*", - InitUpload: "initupload:test-by-*", - Entrypoint: "entrypoint:test-by-*", - Sidecar: "sidecar:test-by-*", + DefaultDecorationConfigs: []*DefaultDecorationConfigEntry{ + { + Repo: regexp.MustCompile(".*"), + Cluster: regexp.MustCompile(""), + Config: &prowapi.DecorationConfig{ + UtilityImages: &prowapi.UtilityImages{ + CloneRefs: "clonerefs:test-by-*", + InitUpload: "initupload:test-by-*", + Entrypoint: "entrypoint:test-by-*", + Sidecar: "sidecar:test-by-*", + }, + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "test-bucket-by-*", + PathStrategy: "single-by-*", + DefaultOrg: "org-by-*", + DefaultRepo: "repo-by-*", + }, + GCSCredentialsSecret: pStr("credentials-gcs-by-*"), }, - GCSConfiguration: &prowapi.GCSConfiguration{ - Bucket: "test-bucket-by-*", - PathStrategy: "single-by-*", - DefaultOrg: "org-by-*", - DefaultRepo: "repo-by-*", - }, - GCSCredentialsSecret: pStr("credentials-gcs-by-*"), }, - "org/repo": { - UtilityImages: &prowapi.UtilityImages{ - CloneRefs: "clonerefs:test-by-org-repo", - InitUpload: "initupload:test-by-org-repo", - Entrypoint: "entrypoint:test-by-org-repo", - Sidecar: "sidecar:test-by-org-repo", - }, - GCSConfiguration: &prowapi.GCSConfiguration{ - Bucket: "test-bucket-by-org-repo", - PathStrategy: "single-by-org-repo", - DefaultOrg: "org-by-org-repo", - DefaultRepo: "repo-by-org-repo", + { + Repo: regexp.MustCompile("org/repo"), + Cluster: regexp.MustCompile(""), + Config: &prowapi.DecorationConfig{ + UtilityImages: &prowapi.UtilityImages{ + CloneRefs: "clonerefs:test-by-org-repo", + InitUpload: "initupload:test-by-org-repo", + Entrypoint: "entrypoint:test-by-org-repo", + Sidecar: "sidecar:test-by-org-repo", + }, + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "test-bucket-by-org-repo", + PathStrategy: "single-by-org-repo", + DefaultOrg: "org-by-org-repo", + DefaultRepo: "repo-by-org-repo", + }, + GCSCredentialsSecret: pStr("credentials-gcs-by-org-repo"), }, - GCSCredentialsSecret: pStr("credentials-gcs-by-org-repo"), }, }, }, @@ -4403,21 +4496,25 @@ func TestSetPeriodicDecorationDefaults(t *testing.T) { }, ProwConfig: ProwConfig{ Plank: Plank{ - DefaultDecorationConfigs: map[string]*prowapi.DecorationConfig{ - "*": { - UtilityImages: &prowapi.UtilityImages{ - CloneRefs: "clonerefs:test-by-*", - InitUpload: "initupload:test-by-*", - Entrypoint: "entrypoint:test-by-*", - Sidecar: "sidecar:test-by-*", - }, - GCSConfiguration: &prowapi.GCSConfiguration{ - Bucket: "test-bucket-by-*", - PathStrategy: "single-by-*", - DefaultOrg: "org-by-*", - DefaultRepo: "repo-by-*", + DefaultDecorationConfigs: []*DefaultDecorationConfigEntry{ + { + Repo: regexp.MustCompile(".*"), + Cluster: regexp.MustCompile(""), + Config: &prowapi.DecorationConfig{ + UtilityImages: &prowapi.UtilityImages{ + CloneRefs: "clonerefs:test-by-*", + InitUpload: "initupload:test-by-*", + Entrypoint: "entrypoint:test-by-*", + Sidecar: "sidecar:test-by-*", + }, + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "test-bucket-by-*", + PathStrategy: "single-by-*", + DefaultOrg: "org-by-*", + DefaultRepo: "repo-by-*", + }, + GCSCredentialsSecret: pStr("credentials-gcs-by-*"), }, - GCSCredentialsSecret: pStr("credentials-gcs-by-*"), }, }, }, @@ -4448,21 +4545,25 @@ func TestSetPeriodicDecorationDefaults(t *testing.T) { }, ProwConfig: ProwConfig{ Plank: Plank{ - DefaultDecorationConfigs: map[string]*prowapi.DecorationConfig{ - "*": { - UtilityImages: &prowapi.UtilityImages{ - CloneRefs: "clonerefs:test-by-*", - InitUpload: "initupload:test-by-*", - Entrypoint: "entrypoint:test-by-*", - Sidecar: "sidecar:test-by-*", + DefaultDecorationConfigs: []*DefaultDecorationConfigEntry{ + { + Repo: regexp.MustCompile(".*"), + Cluster: regexp.MustCompile(""), + Config: &prowapi.DecorationConfig{ + UtilityImages: &prowapi.UtilityImages{ + CloneRefs: "clonerefs:test-by-*", + InitUpload: "initupload:test-by-*", + Entrypoint: "entrypoint:test-by-*", + Sidecar: "sidecar:test-by-*", + }, + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "test-bucket-by-*", + PathStrategy: "single-by-*", + DefaultOrg: "org-by-*", + DefaultRepo: "repo-by-*", + }, + GCSCredentialsSecret: pStr("credentials-gcs-by-*"), }, - GCSConfiguration: &prowapi.GCSConfiguration{ - Bucket: "test-bucket-by-*", - PathStrategy: "single-by-*", - DefaultOrg: "org-by-*", - DefaultRepo: "repo-by-*", - }, - GCSCredentialsSecret: pStr("credentials-gcs-by-*"), }, }, }, @@ -4482,93 +4583,6 @@ func TestSetPeriodicDecorationDefaults(t *testing.T) { } } -func TestDecorationRequested(t *testing.T) { - yes := true - no := false - testCases := []struct { - name string - decorateAll bool - presubmits map[string][]Presubmit - postsubmits map[string][]Postsubmit - periodics []Periodic - expected bool - }{ - { - name: "decorate_all_jobs set", - decorateAll: true, - presubmits: map[string][]Presubmit{ - "org/repo": { - {JobBase: JobBase{Name: "presubmit-job"}}, - }, - }, - expected: true, - }, - { - name: "at-least one job is decorated", - presubmits: map[string][]Presubmit{ - "org/repo": { - {JobBase: JobBase{Name: "presubmit-job"}}, - }, - }, - postsubmits: map[string][]Postsubmit{ - "org/repo": { - {JobBase: JobBase{UtilityConfig: UtilityConfig{Decorate: &yes}}}, - }, - }, - expected: true, - }, - { - name: "decorate_all_jobs set, at-least one job does not opt out", - decorateAll: true, - presubmits: map[string][]Presubmit{ - "org/repo": { - {JobBase: JobBase{UtilityConfig: UtilityConfig{Decorate: &no}}}, - }, - }, - postsubmits: map[string][]Postsubmit{ - "org/repo": { - {JobBase: JobBase{UtilityConfig: UtilityConfig{Decorate: &no}}}, - }, - }, - periodics: []Periodic{ - {JobBase: JobBase{Name: "periodic-job"}}, - }, - expected: true, - }, - { - name: "decorate_all_jobs set, all jobs opt out", - presubmits: map[string][]Presubmit{ - "org/repo": { - {JobBase: JobBase{UtilityConfig: UtilityConfig{Decorate: &no}}}, - }, - }, - postsubmits: map[string][]Postsubmit{ - "org/repo": { - {JobBase: JobBase{UtilityConfig: UtilityConfig{Decorate: &no}}}, - }, - }, - periodics: []Periodic{ - {JobBase: JobBase{UtilityConfig: UtilityConfig{Decorate: &no}}}, - }, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - jobConfig := &JobConfig{ - DecorateAllJobs: tc.decorateAll, - PresubmitsStatic: tc.presubmits, - PostsubmitsStatic: tc.postsubmits, - Periodics: tc.periodics, - } - - if actual := jobConfig.decorationRequested(); actual != tc.expected { - t.Errorf("expected %t got %t", tc.expected, actual) - } - }) - } -} - func TestInRepoConfigEnabled(t *testing.T) { testCases := []struct { name string @@ -4808,30 +4822,56 @@ func TestInRepoConfigAllowsCluster(t *testing.T) { } } -func TestGetDefaultDecorationConfigsThreadSafety(t *testing.T) { - const repo = "repo" - p := Plank{DefaultDecorationConfigs: map[string]*prowapi.DecorationConfig{ - "*": { - GCSConfiguration: &prowapi.GCSConfiguration{ - MediaTypes: map[string]string{"text": "text"}, +// func TestFinalizeDefaultDecorationConfigs(t *testing.T) { +// } + +func TestMergeDefaultDecorationConfigThreadSafety(t *testing.T) { + const repo = "org/repo" + const cluster = "default" + p := Plank{DefaultDecorationConfigs: []*DefaultDecorationConfigEntry{ + { + Repo: regexp.MustCompile(`.*`), + Cluster: regexp.MustCompile(`.*`), + Config: &prowapi.DecorationConfig{ + GCSConfiguration: &prowapi.GCSConfiguration{ + MediaTypes: map[string]string{"text": "text"}, + }, + GCSCredentialsSecret: pStr("service-account-secret"), }, }, - repo: { - GCSConfiguration: &prowapi.GCSConfiguration{ - MediaTypes: map[string]string{"text": "text"}, + { + Repo: regexp.MustCompile(repo), + Cluster: regexp.MustCompile(`.*`), + Config: &prowapi.DecorationConfig{ + GCSConfiguration: &prowapi.GCSConfiguration{ + MediaTypes: map[string]string{"text": "text2"}, + }, + }, + }, + { + Repo: regexp.MustCompile(`.*`), + Cluster: regexp.MustCompile(cluster), + Config: &prowapi.DecorationConfig{ + DefaultServiceAccountName: pStr("service-account-name"), + GCSCredentialsSecret: pStr(""), }, }, }} + jobDC := &prowapi.DecorationConfig{ + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "special-bucket", + }, + } s1 := make(chan struct{}) s2 := make(chan struct{}) go func() { - _ = p.GetDefaultDecorationConfigs(repo) + _ = p.MergeDefaultDecorationConfig(repo, cluster, jobDC) close(s1) }() go func() { - _ = p.GetDefaultDecorationConfigs(repo) + _ = p.MergeDefaultDecorationConfig(repo, cluster, jobDC) close(s2) }() diff --git a/prow/config/prow-config-documented.yaml b/prow/config/prow-config-documented.yaml index ee4d5683c7474..abedbc1c66d7d 100644 --- a/prow/config/prow-config-documented.yaml +++ b/prow/config/prow-config-documented.yaml @@ -472,139 +472,10 @@ owners_dir_blacklist: repos: "": null plank: - # DefaultDecorationConfigs holds the default decoration config for specific values. - # This config will be used on each Presubmit and Postsubmit's corresponding org/repo, and on Periodics - # if extraRefs[0] exists. - # Use `org/repo`, `org` or `*` as a key. - default_decoration_configs: - "": - # CookieFileSecret is the name of a kubernetes secret that contains - # a git http.cookiefile, which should be used during the cloning process. - cookiefile_secret: ' ' - - # DefaultServiceAccountName is the name of the Kubernetes service account - # that should be used by the pod if one is not specified in the podspec. - default_service_account_name: "" - - # GCSConfiguration holds options for pushing logs and - # artifacts to GCS from a job. - gcs_configuration: - # Bucket is the bucket to upload to, it can be: - # * a GCS bucket: with gs:// prefix - # * a S3 bucket: with s3:// prefix - # * a GCS bucket: without a prefix (deprecated, it's discouraged to use Bucket without prefix please add the gs:// prefix) - bucket: ' ' - - # DefaultOrg is omitted from GCS paths when using the - # legacy or simple strategy - default_org: ' ' - - # DefaultRepo is omitted from GCS paths when using the - # legacy or simple strategy - default_repo: ' ' - - # JobURLPrefix holds the baseURL under which the jobs output can be viewed. - # If unset, this will be derived based on org/repo from the job_url_prefix_config. - job_url_prefix: ' ' - - # LocalOutputDir specifies a directory where files should be copied INSTEAD of uploading to blob storage. - # This option is useful for testing jobs that use the pod-utilities without actually uploading. - local_output_dir: ' ' - - # MediaTypes holds additional extension media types to add to Go's - # builtin's and the local system's defaults. This maps extensions - # to media types, for example: MediaTypes["log"] = "text/plain" - mediaTypes: - "": "" - - # PathPrefix is an optional path that follows the - # bucket name and comes before any structure - path_prefix: ' ' - - # PathStrategy dictates how the org and repo are used - # when calculating the full path to an artifact in GCS - path_strategy: ' ' - - # GCSCredentialsSecret is the name of the Kubernetes secret - # that holds GCS push credentials. - gcs_credentials_secret: "" - - # GracePeriod is how long the pod utilities will wait - # after sending SIGINT to send SIGKILL when aborting - # a job. Only applicable if decorating the PodSpec. - grace_period: 0s - - # OauthTokenSecret is a Kubernetes secret that contains the OAuth token, - # which is going to be used for fetching a private repository. - oauth_token_secret: - # Key is the a key of the corresponding kubernetes secret that - # holds the value of the OAuth token. - key: ' ' - - # Name is the name of a kubernetes secret. - name: ' ' - - # Resources holds resource requests and limits for utility - # containers used to decorate a PodSpec. - resources: - clonerefs: - limits: - "": "0" - requests: - "": "0" - initupload: - limits: - "": "0" - requests: - "": "0" - place_entrypoint: - limits: - "": "0" - requests: - "": "0" - sidecar: - limits: - "": "0" - requests: - "": "0" - - # S3CredentialsSecret is the name of the Kubernetes secret - # that holds blob storage push credentials. - s3_credentials_secret: "" - - # SkipCloning determines if we should clone source code in the - # initcontainers for jobs that specify refs - skip_cloning: false - - # SSHHostFingerprints are the fingerprints of known SSH hosts - # that the cloning process can trust. - # Create with ssh-keyscan [-t rsa] host - ssh_host_fingerprints: - - "" - - # SSHKeySecrets are the names of Kubernetes secrets that contain - # SSK keys which should be used during the cloning process. - ssh_key_secrets: - - "" - - # Timeout is how long the pod utilities will wait - # before aborting a job with SIGINT. - timeout: 0s - - # UtilityImages holds pull specs for utility container - # images used to decorate a PodSpec. - utility_images: - # CloneRefs is the pull spec used for the clonerefs utility - clonerefs: ' ' - - # Entrypoint is the pull spec used for the entrypoint utility - entrypoint: ' ' - - # InitUpload is the pull spec used for the initupload utility - initupload: ' ' - - # sidecar is the pull spec used for the sidecar utility - sidecar: ' ' + # DefaultDecorationConfigsRaw compiles into DefaultDecorationConfigs. + # It may represent either `[]*DefaultDecorationConfigEntry` or + # `map[string]*prowapi.DecorationConfig`. + default_decoration_configs: null # JobURLPrefixConfig is the host and path prefix under which job details # will be viewable. Use `org/repo`, `org` or `*`as key and an url as value diff --git a/prow/crier/reporters/gcs/internal/util/util.go b/prow/crier/reporters/gcs/internal/util/util.go index b5813bba5f0a1..ea0625dc4f505 100644 --- a/prow/crier/reporters/gcs/internal/util/util.go +++ b/prow/crier/reporters/gcs/internal/util/util.go @@ -101,20 +101,23 @@ func GetJobDestination(cfg config.Getter, pj *prowv1.ProwJob) (bucket, dir strin // jobs are not decorated, so we guess that we should use the default location // for those jobs. This assumption is usually (but not always) correct. // The TestGrid configurator uses the same assumption. - repo := "*" + repo := "" if pj.Spec.Refs != nil { repo = pj.Spec.Refs.Org + "/" + pj.Spec.Refs.Repo + } else if len(pj.Spec.ExtraRefs) > 0 { + repo = fmt.Sprintf("%s/%s", pj.Spec.ExtraRefs[0].Org, pj.Spec.ExtraRefs[0].Repo) } - ddc := cfg().Plank.GetDefaultDecorationConfigs(repo) - var gcsConfig *prowv1.GCSConfiguration if pj.Spec.DecorationConfig != nil && pj.Spec.DecorationConfig.GCSConfiguration != nil { gcsConfig = pj.Spec.DecorationConfig.GCSConfiguration - } else if ddc != nil && ddc.GCSConfiguration != nil { - gcsConfig = ddc.GCSConfiguration } else { - return "", "", fmt.Errorf("couldn't figure out a GCS config for %q", pj.Spec.Job) + ddc := cfg().Plank.MergeDefaultDecorationConfig(repo, pj.Spec.Cluster, nil) + if ddc != nil && ddc.GCSConfiguration != nil { + gcsConfig = ddc.GCSConfiguration + } else { + return "", "", fmt.Errorf("couldn't figure out a GCS config for %q", pj.Spec.Job) + } } ps := downwardapi.NewJobSpec(pj.Spec, pj.Status.BuildID, pj.Name) diff --git a/prow/crier/reporters/gcs/internal/util/util_test.go b/prow/crier/reporters/gcs/internal/util/util_test.go index 976a5387953bc..28f2a78f3580f 100644 --- a/prow/crier/reporters/gcs/internal/util/util_test.go +++ b/prow/crier/reporters/gcs/internal/util/util_test.go @@ -196,7 +196,7 @@ func TestGetJobDestination(t *testing.T) { cfg := testutil.Fca{C: config.Config{ ProwConfig: config.ProwConfig{ Plank: config.Plank{ - DefaultDecorationConfigs: decorationConfigs, + DefaultDecorationConfigs: config.DefaultDecorationMapToSliceTesting(decorationConfigs), }, }, }}.Config diff --git a/prow/crier/reporters/gcs/kubernetes/reporter_test.go b/prow/crier/reporters/gcs/kubernetes/reporter_test.go index 97f5ba37aff53..24f64a7275c9f 100644 --- a/prow/crier/reporters/gcs/kubernetes/reporter_test.go +++ b/prow/crier/reporters/gcs/kubernetes/reporter_test.go @@ -353,15 +353,16 @@ func TestReportPodInfo(t *testing.T) { fca := testutil.Fca{C: config.Config{ProwConfig: config.ProwConfig{ PodNamespace: "test-pods", Plank: config.Plank{ - DefaultDecorationConfigs: map[string]*prowv1.DecorationConfig{"*": { - GCSConfiguration: &prowv1.GCSConfiguration{ - Bucket: "kubernetes-jenkins", - PathPrefix: "some-prefix", - PathStrategy: prowv1.PathStrategyLegacy, - DefaultOrg: "kubernetes", - DefaultRepo: "kubernetes", - }, - }}, + DefaultDecorationConfigs: config.DefaultDecorationMapToSliceTesting( + map[string]*prowv1.DecorationConfig{"*": { + GCSConfiguration: &prowv1.GCSConfiguration{ + Bucket: "kubernetes-jenkins", + PathPrefix: "some-prefix", + PathStrategy: prowv1.PathStrategyLegacy, + DefaultOrg: "kubernetes", + DefaultRepo: "kubernetes", + }, + }}), }, }}} diff --git a/prow/crier/reporters/gcs/reporter_test.go b/prow/crier/reporters/gcs/reporter_test.go index 94409a874ee61..66b5c9e2c9a8c 100644 --- a/prow/crier/reporters/gcs/reporter_test.go +++ b/prow/crier/reporters/gcs/reporter_test.go @@ -74,15 +74,16 @@ func TestReportJobFinished(t *testing.T) { cfg := testutil.Fca{C: config.Config{ ProwConfig: config.ProwConfig{ Plank: config.Plank{ - DefaultDecorationConfigs: map[string]*prowv1.DecorationConfig{"*": { - GCSConfiguration: &prowv1.GCSConfiguration{ - Bucket: "kubernetes-jenkins", - PathPrefix: "some-prefix", - PathStrategy: prowv1.PathStrategyLegacy, - DefaultOrg: "kubernetes", - DefaultRepo: "kubernetes", - }, - }}, + DefaultDecorationConfigs: config.DefaultDecorationMapToSliceTesting( + map[string]*prowv1.DecorationConfig{"*": { + GCSConfiguration: &prowv1.GCSConfiguration{ + Bucket: "kubernetes-jenkins", + PathPrefix: "some-prefix", + PathStrategy: prowv1.PathStrategyLegacy, + DefaultOrg: "kubernetes", + DefaultRepo: "kubernetes", + }, + }}), }, }, }}.Config @@ -152,15 +153,16 @@ func TestReportJobStarted(t *testing.T) { cfg := testutil.Fca{C: config.Config{ ProwConfig: config.ProwConfig{ Plank: config.Plank{ - DefaultDecorationConfigs: map[string]*prowv1.DecorationConfig{"*": { - GCSConfiguration: &prowv1.GCSConfiguration{ - Bucket: "kubernetes-jenkins", - PathPrefix: "some-prefix", - PathStrategy: prowv1.PathStrategyLegacy, - DefaultOrg: "kubernetes", - DefaultRepo: "kubernetes", - }, - }}, + DefaultDecorationConfigs: config.DefaultDecorationMapToSliceTesting( + map[string]*prowv1.DecorationConfig{"*": { + GCSConfiguration: &prowv1.GCSConfiguration{ + Bucket: "kubernetes-jenkins", + PathPrefix: "some-prefix", + PathStrategy: prowv1.PathStrategyLegacy, + DefaultOrg: "kubernetes", + DefaultRepo: "kubernetes", + }, + }}), }, }, }}.Config @@ -214,15 +216,16 @@ func TestReportProwJob(t *testing.T) { cfg := testutil.Fca{C: config.Config{ ProwConfig: config.ProwConfig{ Plank: config.Plank{ - DefaultDecorationConfigs: map[string]*prowv1.DecorationConfig{"*": { - GCSConfiguration: &prowv1.GCSConfiguration{ - Bucket: "kubernetes-jenkins", - PathPrefix: "some-prefix", - PathStrategy: prowv1.PathStrategyLegacy, - DefaultOrg: "kubernetes", - DefaultRepo: "kubernetes", - }, - }}, + DefaultDecorationConfigs: config.DefaultDecorationMapToSliceTesting( + map[string]*prowv1.DecorationConfig{"*": { + GCSConfiguration: &prowv1.GCSConfiguration{ + Bucket: "kubernetes-jenkins", + PathPrefix: "some-prefix", + PathStrategy: prowv1.PathStrategyLegacy, + DefaultOrg: "kubernetes", + DefaultRepo: "kubernetes", + }, + }}), }, }, }}.Config diff --git a/prow/spyglass/spyglass.go b/prow/spyglass/spyglass.go index dcb90c28190f3..6535de3f287c8 100644 --- a/prow/spyglass/spyglass.go +++ b/prow/spyglass/spyglass.go @@ -372,10 +372,11 @@ func (sg *Spyglass) RunToPR(src string) (string, string, int, error) { // per job would probably be a bad idea (indeed, not even the tests try to do this). // This decision should probably be revisited if we ever want other information from it. // TODO (droslean): we should get the default decoration config depending on the org/repo. - if sg.config().Plank.DefaultDecorationConfigs["*"] == nil || sg.config().Plank.DefaultDecorationConfigs["*"].GCSConfiguration == nil { + ddc := sg.config().Plank.MergeDefaultDecorationConfig("", "", nil) + if ddc == nil || ddc.GCSConfiguration == nil { return "", "", 0, fmt.Errorf("couldn't look up a GCS configuration") } - c := sg.config().Plank.DefaultDecorationConfigs["*"].GCSConfiguration + c := ddc.GCSConfiguration // Assumption: we can derive the type of URL from how many components it has, without worrying much about // what the actual path configuration is. switch len(split) { diff --git a/prow/spyglass/spyglass_test.go b/prow/spyglass/spyglass_test.go index f04473eb6751e..1df65a9f15b75 100644 --- a/prow/spyglass/spyglass_test.go +++ b/prow/spyglass/spyglass_test.go @@ -883,16 +883,17 @@ func TestRunToPR(t *testing.T) { fca.Set(&config.Config{ ProwConfig: config.ProwConfig{ Plank: config.Plank{ - DefaultDecorationConfigs: map[string]*prowapi.DecorationConfig{ - "*": { - GCSConfiguration: &prowapi.GCSConfiguration{ - Bucket: "kubernetes-jenkins", - DefaultOrg: "kubernetes", - DefaultRepo: "kubernetes", - PathStrategy: "legacy", + DefaultDecorationConfigs: config.DefaultDecorationMapToSliceTesting( + map[string]*prowapi.DecorationConfig{ + "*": { + GCSConfiguration: &prowapi.GCSConfiguration{ + Bucket: "kubernetes-jenkins", + DefaultOrg: "kubernetes", + DefaultRepo: "kubernetes", + PathStrategy: "legacy", + }, }, - }, - }, + }), }, }, }) @@ -1101,14 +1102,15 @@ func TestGCSPathRoundTrip(t *testing.T) { c: config.Config{ ProwConfig: config.ProwConfig{ Plank: config.Plank{ - DefaultDecorationConfigs: map[string]*prowapi.DecorationConfig{ - "*": { - GCSConfiguration: &prowapi.GCSConfiguration{ - DefaultOrg: tc.defaultOrg, - DefaultRepo: tc.defaultRepo, + DefaultDecorationConfigs: config.DefaultDecorationMapToSliceTesting( + map[string]*prowapi.DecorationConfig{ + "*": { + GCSConfiguration: &prowapi.GCSConfiguration{ + DefaultOrg: tc.defaultOrg, + DefaultRepo: tc.defaultRepo, + }, }, - }, - }, + }), }, }, }, diff --git a/prow/test/BUILD.bazel b/prow/test/BUILD.bazel index 178b791e1a6ef..81897aba4f704 100644 --- a/prow/test/BUILD.bazel +++ b/prow/test/BUILD.bazel @@ -23,6 +23,8 @@ filegroup( srcs = [ ":package-srcs", "//prow/test/data:all-srcs", + "//prow/test/integration/fakeghserver:all-srcs", + "//prow/test/integration/test:all-srcs", ], tags = ["automanaged"], visibility = ["//visibility:public"], diff --git a/prow/test/integration/fakeghserver/BUILD.bazel b/prow/test/integration/fakeghserver/BUILD.bazel index 7cf84fbb43a00..165615f33d2f7 100644 --- a/prow/test/integration/fakeghserver/BUILD.bazel +++ b/prow/test/integration/fakeghserver/BUILD.bazel @@ -29,7 +29,6 @@ go_library( "//prow/interrupts:go_default_library", "//prow/logrusutil:go_default_library", "//prow/pjutil:go_default_library", - "@com_github_google_go_github//github:go_default_library", "@com_github_gorilla_mux//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library", ], @@ -44,9 +43,7 @@ filegroup( filegroup( name = "all-srcs", - srcs = [ - ":package-srcs", - ], + srcs = [":package-srcs"], tags = ["automanaged"], visibility = ["//visibility:public"], ) diff --git a/releng/config-forker/BUILD.bazel b/releng/config-forker/BUILD.bazel index 549ad6f4d41b0..3f07d04672024 100644 --- a/releng/config-forker/BUILD.bazel +++ b/releng/config-forker/BUILD.bazel @@ -40,6 +40,8 @@ go_test( deps = [ "//prow/apis/prowjobs/v1:go_default_library", "//prow/config:go_default_library", + "@com_github_google_go_cmp//cmp:go_default_library", + "@com_github_google_go_cmp//cmp/cmpopts:go_default_library", "@io_k8s_api//core/v1:go_default_library", "@io_k8s_apimachinery//pkg/util/diff:go_default_library", ], diff --git a/releng/config-forker/main.go b/releng/config-forker/main.go index ef75b7cf2bb7b..d3e9e2310d3b4 100644 --- a/releng/config-forker/main.go +++ b/releng/config-forker/main.go @@ -104,6 +104,13 @@ func generatePresubmits(c config.JobConfig, version string) (map[string][]config return newPresubmits, nil } +func shouldDecorate(c *config.JobConfig, util config.UtilityConfig) bool { + if util.Decorate != nil { + return *util.Decorate + } + return c.DecorateAllJobs +} + func generatePeriodics(conf config.JobConfig, version string) ([]config.Periodic, error) { var newPeriodics []config.Periodic for _, periodic := range conf.Periodics { @@ -117,7 +124,7 @@ func generatePeriodics(conf config.JobConfig, version string) ([]config.Periodic c := &p.Spec.Containers[i] c.Image = fixImage(c.Image, version) c.Env = fixEnvVars(c.Env, version) - if !config.ShouldDecorate(&conf, p.JobBase.UtilityConfig) { + if !shouldDecorate(&conf, p.JobBase.UtilityConfig) { c.Command = fixBootstrapArgs(c.Command, version) c.Args = fixBootstrapArgs(c.Args, version) } @@ -128,7 +135,7 @@ func generatePeriodics(conf config.JobConfig, version string) ([]config.Periodic } } } - if config.ShouldDecorate(&conf, p.JobBase.UtilityConfig) { + if shouldDecorate(&conf, p.JobBase.UtilityConfig) { p.ExtraRefs = fixExtraRefs(p.ExtraRefs, version) } if interval, ok := p.Annotations[periodicIntervalAnnotation]; ok { diff --git a/releng/config-forker/main_test.go b/releng/config-forker/main_test.go index 07fa10f4932b8..1eae3b6857551 100644 --- a/releng/config-forker/main_test.go +++ b/releng/config-forker/main_test.go @@ -20,6 +20,8 @@ import ( "reflect" "testing" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/util/diff" prowapi "k8s.io/test-infra/prow/apis/prowjobs/v1" @@ -701,7 +703,7 @@ func TestGeneratePeriodics(t *testing.T) { } if !reflect.DeepEqual(result, expected) { - t.Errorf("Result does not match expected. Difference:\n%s", diff.ObjectDiff(expected, result)) + t.Errorf("Result does not match expected. Difference:\n%s\n", cmp.Diff(expected, result, cmpopts.IgnoreUnexported(config.Periodic{}))) } } diff --git a/testgrid/cmd/configurator/prow.go b/testgrid/cmd/configurator/prow.go index 7ea6e38833fdc..5cf8fd0e71aea 100644 --- a/testgrid/cmd/configurator/prow.go +++ b/testgrid/cmd/configurator/prow.go @@ -67,8 +67,8 @@ func applySingleProwjobAnnotations(c *configpb.Configuration, pc *prowConfig.Con var prefix string if j.DecorationConfig != nil && j.DecorationConfig.GCSConfiguration != nil { prefix = path.Join(j.DecorationConfig.GCSConfiguration.Bucket, j.DecorationConfig.GCSConfiguration.PathPrefix) - } else if pc.Plank.GetDefaultDecorationConfigs(repo) != nil && pc.Plank.GetDefaultDecorationConfigs(repo).GCSConfiguration != nil { - prefix = path.Join(pc.Plank.GetDefaultDecorationConfigs(repo).GCSConfiguration.Bucket, pc.Plank.GetDefaultDecorationConfigs(repo).GCSConfiguration.PathPrefix) + } else if def := pc.Plank.MergeDefaultDecorationConfig(repo, "", nil); def != nil && def.GCSConfiguration != nil { + prefix = path.Join(def.GCSConfiguration.Bucket, def.GCSConfiguration.PathPrefix) } else { return fmt.Errorf("job %s: couldn't figure out a default decoration config", j.Name) } diff --git a/testgrid/cmd/configurator/prow_test.go b/testgrid/cmd/configurator/prow_test.go index 7253dd57fe541..282df09b7f3c7 100644 --- a/testgrid/cmd/configurator/prow_test.go +++ b/testgrid/cmd/configurator/prow_test.go @@ -18,6 +18,7 @@ package main import ( "reflect" + "regexp" "testing" "github.com/GoogleCloudPlatform/testgrid/config/yamlcfg" @@ -929,10 +930,14 @@ func fakeProwConfig() *prowConfig.Config { return &prowConfig.Config{ ProwConfig: prowConfig.ProwConfig{ Plank: prowConfig.Plank{ - DefaultDecorationConfigs: map[string]*prowapi.DecorationConfig{ - "*": { - GCSConfiguration: &prowapi.GCSConfiguration{ - PathPrefix: ProwDefaultGCSPath, + DefaultDecorationConfigs: []*prowConfig.DefaultDecorationConfigEntry{ + { + Repo: regexp.MustCompile(".*"), + Cluster: regexp.MustCompile(".*"), + Config: &prowapi.DecorationConfig{ + GCSConfiguration: &prowapi.GCSConfiguration{ + PathPrefix: ProwDefaultGCSPath, + }, }, }, },