diff --git a/prow/config/generate.go b/prow/config/generate.go index 0a62f74a0cc..37fe6115e57 100644 --- a/prow/config/generate.go +++ b/prow/config/generate.go @@ -78,6 +78,9 @@ type GlobalConfig struct { TestgridConfig TestgridConfig `json:"testgrid_config,omitempty"` + Annotations map[string]string `json:"annotations,omitempty"` + Labels map[string]string `json:"labels,omitempty"` + Resources map[string]v1.ResourceRequirements `json:"resources,omitempty"` BaseRequirements []string `json:"base_requirements,omitempty"` RequirementPresets map[string]RequirementPreset `json:"requirement_presets,omitempty"` @@ -106,6 +109,9 @@ type JobsConfig struct { Cluster string `json:"cluster,omitempty"` NodeSelector map[string]string `json:"node_selector,omitempty"` + Annotations map[string]string `json:"annotations,omitempty"` + Labels map[string]string `json:"labels,omitempty"` + Resources map[string]v1.ResourceRequirements `json:"resources,omitempty"` Requirements []string `json:"requirements,omitempty"` RequirementPresets map[string]RequirementPreset `json:"requirement_presets,omitempty"` @@ -131,6 +137,9 @@ type Job struct { Cluster string `json:"cluster,omitempty"` NodeSelector map[string]string `json:"node_selector,omitempty"` + Annotations map[string]string `json:"annotations,omitempty"` + Labels map[string]string `json:"labels,omitempty"` + Resources string `json:"resources,omitempty"` Modifiers []string `json:"modifiers,omitempty"` Requirements []string `json:"requirements,omitempty"` @@ -615,6 +624,26 @@ func createJobBase(globalConfig GlobalConfig, jobConfig JobsConfig, job Job, jb.Spec.NodeSelector = job.NodeSelector } + if globalConfig.Annotations != nil { + jb.Annotations = globalConfig.Annotations + } + if jobConfig.Annotations != nil { + jb.Annotations = mergeMaps(jb.Annotations, jobConfig.Annotations) + } + if job.Annotations != nil { + jb.Annotations = mergeMaps(jb.Annotations, job.Annotations) + } + + if globalConfig.Labels != nil { + jb.Labels = globalConfig.Labels + } + if jobConfig.Labels != nil { + jb.Labels = mergeMaps(jb.Labels, jobConfig.Labels) + } + if job.Labels != nil { + jb.Labels = mergeMaps(jb.Labels, job.Labels) + } + if job.Timeout != nil { jb.DecorationConfig = &prowjob.DecorationConfig{ Timeout: job.Timeout, @@ -795,3 +824,16 @@ func contains(slice []string, item string) bool { _, ok := set[item] return ok } + +// mergeMaps will merge the two maps into one. +// If there are duplicated keys in the two maps, the value in mp2 will overwrite that of mp1. +func mergeMaps(mp1, mp2 map[string]string) map[string]string { + newMap := make(map[string]string, len(mp1)) + for k, v := range mp1 { + newMap[k] = v + } + for k, v := range mp2 { + newMap[k] = v + } + return newMap +} diff --git a/prow/config/generate_test.go b/prow/config/generate_test.go index cae048ba47d..181b6e1e968 100644 --- a/prow/config/generate_test.go +++ b/prow/config/generate_test.go @@ -110,3 +110,51 @@ func TestFilterReleaseBranchingJobs(t *testing.T) { } } } + +func TestMergeMaps(t *testing.T) { + var testCases = []struct { + name string + mp1 map[string]string + mp2 map[string]string + expected map[string]string + }{ + { + name: "combine two empty maps", + mp1: nil, + mp2: nil, + expected: map[string]string{}, + }, + { + name: "the first map is empty", + mp1: map[string]string{}, + mp2: map[string]string{"a": "aa", "b": "bb"}, + expected: map[string]string{"a": "aa", "b": "bb"}, + }, + { + name: "the second map is empty", + mp1: map[string]string{"a": "aa", "b": "bb"}, + mp2: map[string]string{}, + expected: map[string]string{"a": "aa", "b": "bb"}, + }, + { + name: "two maps without duplicated keys", + mp1: map[string]string{"a": "aa"}, + mp2: map[string]string{"b": "bb"}, + expected: map[string]string{"a": "aa", "b": "bb"}, + }, + { + name: "two maps with duplicated keys", + mp1: map[string]string{"a": "aa", "b": "b"}, + mp2: map[string]string{"b": "bb"}, + expected: map[string]string{"a": "aa", "b": "bb"}, + }, + } + + for _, tc := range testCases { + actual := mergeMaps(tc.mp1, tc.mp2) + + if !reflect.DeepEqual(tc.expected, actual) { + t.Errorf("mergeMaps does not work as intended; actual: %v\n expected %v\n", actual, tc.expected) + } + } +} diff --git a/prow/genjobs/cmd/genjobs/main.go b/prow/genjobs/cmd/genjobs/main.go index 932355715a8..a965abe64ee 100644 --- a/prow/genjobs/cmd/genjobs/main.go +++ b/prow/genjobs/cmd/genjobs/main.go @@ -46,6 +46,7 @@ const ( defaultCluster = "default" defaultsFilename = ".defaults.yaml" yamlExt = ".(yml|yaml)$" + gerritReportLabel = "prow.k8s.io/gerrit-report-label" ) var ( @@ -687,9 +688,13 @@ func updateSSHKeySecrets(o options, job *prowjob.DecorationConfig) { func updateGerritReportingLabels(o options, skipReport, optional bool, labels map[string]string) { if o.SupportGerritReporting && !skipReport { if !optional { - labels["prow.k8s.io/gerrit-report-label"] = "Verified" + // For non-optional jobs, only add the label if it's not configured, + // this allows us defining internal jobs that report to a different label. + if _, ok := labels[gerritReportLabel]; !ok { + labels[gerritReportLabel] = "Verified" + } } else { - labels["prow.k8s.io/gerrit-report-label"] = "Advisory" + labels[gerritReportLabel] = "Advisory" } } }