diff --git a/pkg/rehearse/jobs.go b/pkg/rehearse/jobs.go index 364f65ddc82..8d576aec51c 100644 --- a/pkg/rehearse/jobs.go +++ b/pkg/rehearse/jobs.go @@ -221,13 +221,9 @@ func hasRehearsableLabel(labels map[string]string) bool { } // getResolverConfigForTest returns a resolved ci-operator based on the provided filename and only includes the specified test in the -// `tests` section of the config. +// `tests` section of the config. If `testname` is empty, the resolved config will contain all items from the original `tests`. // The ImageStreamTagMap contains all imagestreamtags used within this config and is used to ensure they exist on all target clusters. -func getResolvedConfigForTest(ciopConfigs config.DataByFilename, resolver registry.Resolver, filename, testname string) (string, apihelper.ImageStreamTagMap, error) { - ciopConfig, ok := ciopConfigs[filename] - if !ok { - return "", nil, fmt.Errorf("ci-operator config file %s was not found", filename) - } +func getResolvedConfigForTest(ciopConfig config.DataWithInfo, resolver registry.Resolver, testname string) (string, apihelper.ImageStreamTagMap, error) { // make copy so we don't change in-memory config ciopCopy := config.DataWithInfo{ Configuration: ciopConfig.Configuration, @@ -236,11 +232,11 @@ func getResolvedConfigForTest(ciopConfigs config.DataByFilename, resolver regist // only include the test we need to reduce env var size ciopCopy.Configuration.Tests = []api.TestStepConfiguration{} for _, test := range ciopConfig.Configuration.Tests { - if test.As == testname { + if testname == "" || test.As == testname { ciopCopy.Configuration.Tests = append(ciopCopy.Configuration.Tests, test) - break } } + ciopConfigResolved, err := registry.ResolveConfig(resolver, ciopCopy.Configuration) if err != nil { return "", nil, fmt.Errorf("failed resolve ReleaseBuildConfiguration: %w", err) @@ -258,45 +254,90 @@ func getResolvedConfigForTest(ciopConfigs config.DataByFilename, resolver regist return string(ciOpConfigContent), imageStreamTags, nil } -// inlineCiOpConfig detects whether a job needs a ci-operator config file -// provided by a `ci-operator-configs` ConfigMap and if yes, returns a copy -// of the job where a reference to this ConfigMap is replaced by the content -// of the needed config file passed to the job as a direct value. This needs -// to happen because the rehearsed Prow jobs may depend on these config files -// being also changed by the tested PR. +// inlineCiOpConfig detects whether a Container in a rehearsed job uses +// a ci-operator config file and if yes, it modifies the Container so that its +// environment has a CONFIG_SPEC variable containing a resolved configuration +// coming from the content of the release repository. +// This needs to happen because the config files or step registry content they +// refer to may change in the PR that triggered a rehearsal, and the rehearsals +// must use all content changed in this way. +// +// Also returns an ImageStreamTagMap with that contains all imagestreamtags used +// within the inlined config (this is needed to later ensure they exist on all +// target clusters where the rehearsals will execute). func inlineCiOpConfig(container *v1.Container, ciopConfigs config.DataByFilename, resolver registry.Resolver, metadata api.Metadata, testname string, loggers Loggers) (apihelper.ImageStreamTagMap, error) { allImageStreamTags := apihelper.ImageStreamTagMap{} - // replace all ConfigMapKeyRef mounts with inline config maps - for index := range container.Env { - env := &(container.Env[index]) - if env.Name == "CONFIG_SPEC" { - // if CONFIG_SPEC has already been set, do not add new CONFIG_SPEC section + if container.Command == nil || container.Command[0] != "ci-operator" { + return allImageStreamTags, nil + } + + var hasConfigEnv bool + var ciopConfig config.DataWithInfo + var envs []v1.EnvVar + for idx, env := range container.Env { + switch { + case env.Name == "CONFIG_SPEC" && env.ValueFrom != nil: + // job attempts to get CONFIG_SPEC from cluster resource, which is weird, + // unexpected and we cannot support rehearsals for that + return nil, fmt.Errorf("CONFIG_SPEC is set from a cluster resource, cannot rehearse such job") + case env.Name == "UNRESOLVED_CONFIG" && env.ValueFrom != nil: + // job attempts to get UNRESOLVED_CONFIG from cluster resource, which is weird, + // unexpected and we cannot support rehearsals for that + return nil, fmt.Errorf("UNRESOLVED_CONFIG is set from a cluster resource, cannot rehearse such job") + case env.Name == "CONFIG_SPEC" && env.Value != "": + // job already has inline CONFIG_SPEC: we should not modify it return allImageStreamTags, nil + case env.Name == "UNRESOLVED_CONFIG" && env.Value != "": + if err := yaml.Unmarshal([]byte(env.Value), &ciopConfig.Configuration); err != nil { + return nil, fmt.Errorf("failed to unmarshal UNRESOLVED_CONFIG: %w", err) + } + // Annoying hack: UNRESOLVED_CONFIG means this is a handcrafted job, which means + // `testname` cannot be relied on (it is derived from job name, which is arbitrary + // in handcrafted jobs). We need the test name to know which `tests` field to + // resolve, so we try to detect it from `--target` arg, if present. + // + // The worst case is that we do not find the matching name. In such case, + // the inlined config will contain all items from `tests` stanza. + testname = "" + for idx, arg := range container.Args { + if strings.HasPrefix(arg, "--target=") { + testname = strings.TrimPrefix(arg, "--target=") + break + } + if arg == "--target" { + if len(container.Args) == (idx + 1) { + return nil, errors.New("plain '--target' is a last arg, expected to be followed with a value") + } + testname = container.Args[idx+1] + break + } + } + hasConfigEnv = true + default: + // Another envvar, we just need to keep it + envs = append(envs, container.Env[idx]) } } - // inline CONFIG_SPEC for all ci-operator jobs - if container.Command != nil && container.Command[0] == "ci-operator" { + if !hasConfigEnv { if err := metadata.IsComplete(); err != nil { return nil, fmt.Errorf("could not infer which ci-operator config this job uses: %w", err) } filename := metadata.Basename() - loggers.Debug.WithField(logCiopConfigFile, filename).Debug("Rehearsal job uses ci-operator config ConfigMap, needed content will be inlined") - ciOpConfigContent, imageStreamTags, err := getResolvedConfigForTest(ciopConfigs, resolver, filename, testname) - if err != nil { - loggers.Job.WithError(err).Error("Failed to get resolved config for test") - return nil, err + if _, ok := ciopConfigs[filename]; !ok { + return nil, fmt.Errorf("ci-operator config file %s was not found", filename) } - apihelper.MergeImageStreamTagMaps(allImageStreamTags, imageStreamTags) + ciopConfig = ciopConfigs[filename] + loggers.Debug.WithField(logCiopConfigFile, filename).Debug("Rehearsal job would use ci-operator config from registry, its content will be inlined") + } - envs := container.Env - env := v1.EnvVar{ - Name: "CONFIG_SPEC", - Value: ciOpConfigContent, - } - envs = append(envs, env) - container.Env = envs + ciOpConfigContent, imageStreamTags, err := getResolvedConfigForTest(ciopConfig, resolver, testname) + if err != nil { + loggers.Job.WithError(err).Error("Failed to get resolved config for test") + return nil, err } + apihelper.MergeImageStreamTagMaps(allImageStreamTags, imageStreamTags) + container.Env = append(envs, v1.EnvVar{Name: "CONFIG_SPEC", Value: ciOpConfigContent}) return allImageStreamTags, nil } diff --git a/pkg/rehearse/jobs_test.go b/pkg/rehearse/jobs_test.go index b34e828073a..82182b41541 100644 --- a/pkg/rehearse/jobs_test.go +++ b/pkg/rehearse/jobs_test.go @@ -115,40 +115,40 @@ func generateTestConfigFiles() config.DataByFilename { var ignoreUnexported = cmpopts.IgnoreUnexported(prowconfig.Presubmit{}, prowconfig.Brancher{}, prowconfig.RegexpChangeMatcher{}) -func makeTestingPresubmitForEnv(env []v1.EnvVar) *prowconfig.Presubmit { - return &prowconfig.Presubmit{ - JobBase: prowconfig.JobBase{ - Agent: "kubernetes", - Name: "test-job-name", - Labels: map[string]string{"pj-rehearse.openshift.io/can-be-rehearsed": "true"}, - Spec: &v1.PodSpec{ - Containers: []v1.Container{ - {Env: env}, +func TestInlineCiopConfig(t *testing.T) { + unresolvedConfig := api.ReleaseBuildConfiguration{ + Tests: []api.TestStepConfiguration{ + { + As: "test1", + MultiStageTestConfiguration: &api.MultiStageTestConfiguration{ + Pre: []api.TestStep{{LiteralTestStep: &api.LiteralTestStep{As: "test1-from-unresolved"}}}, }, }, + { + As: "test2", + }, }, } -} - -func makeCMReference(cmName, key string) *v1.EnvVarSource { - return &v1.EnvVarSource{ - ConfigMapKeyRef: &v1.ConfigMapKeySelector{ - LocalObjectReference: v1.LocalObjectReference{ - Name: cmName, + unresolvedConfigContent, err := yaml.Marshal(&unresolvedConfig) + if err != nil { + t.Fatal("Failed to marshal ci-operator config") + } + test1ConfigFromUnresolved := api.ReleaseBuildConfiguration{ + Tests: []api.TestStepConfiguration{ + { + As: "test1", + MultiStageTestConfigurationLiteral: &api.MultiStageTestConfigurationLiteral{ + Pre: []api.LiteralTestStep{{As: "test1-from-unresolved"}}, + }, }, - Key: key, }, } -} - -var testCiopConfigInfo = api.Metadata{ - Org: "targetOrg", - Repo: "targetRepo", - Branch: "master", -} + test1ConfigContentFromUnresolved, err := yaml.Marshal(&test1ConfigFromUnresolved) + if err != nil { + t.Fatal("Failed to marshal ci-operator config") + } -func TestInlineCiopConfig(t *testing.T) { - testCiopConfig := api.ReleaseBuildConfiguration{ + resolvedConfig := api.ReleaseBuildConfiguration{ Tests: []api.TestStepConfiguration{{ As: "test1", MultiStageTestConfigurationLiteral: &api.MultiStageTestConfigurationLiteral{ @@ -159,41 +159,104 @@ func TestInlineCiopConfig(t *testing.T) { }}, } + testCiopConfigTest1 := api.ReleaseBuildConfiguration{Tests: []api.TestStepConfiguration{resolvedConfig.Tests[0]}} + testCiopConfigContentTest1, err := yaml.Marshal(&testCiopConfigTest1) + if err != nil { + t.Fatal("Failed to marshal ci-operator config") + } + + testCiopConfigTest2 := api.ReleaseBuildConfiguration{Tests: []api.TestStepConfiguration{resolvedConfig.Tests[1]}} + testCiopConfigContentTest2, err := yaml.Marshal(&testCiopConfigTest2) + if err != nil { + t.Fatal("Failed to marshal ci-operator config") + } + + standardMetadata := api.Metadata{Org: "targetOrg", Repo: "targetRepo", Branch: "master"} + incompleteMetadata := api.Metadata{Org: "openshift", Repo: "release"} + + makePresubmit := func(command string, env []v1.EnvVar, args []string) *prowconfig.Presubmit { + return &prowconfig.Presubmit{ + JobBase: prowconfig.JobBase{ + Agent: "kubernetes", + Name: "test-job-name", + Labels: map[string]string{"pj-rehearse.openshift.io/can-be-rehearsed": "true"}, + Spec: &v1.PodSpec{ + Containers: []v1.Container{ + { + Args: args, + Command: []string{command}, + Env: env, + }, + }, + }, + }, + } + } + + configs := config.DataByFilename{ + standardMetadata.Basename(): { + Info: config.Info{ + Metadata: standardMetadata, + }, + Configuration: resolvedConfig, + }, + } + testCases := []struct { - description string - testname string - sourceEnv []v1.EnvVar - configs config.DataByFilename + description string + + testname string + command string + sourceEnv []v1.EnvVar + metadata api.Metadata + expectedEnv []v1.EnvVar expectedError bool expectedImageStreamTagMap apihelper.ImageStreamTagMap - }{{ - description: "empty env -> no changes", - configs: config.DataByFilename{}, - }, { - description: "no Env.ValueFrom -> no changes", - sourceEnv: []v1.EnvVar{{Name: "T", Value: "V"}}, - configs: config.DataByFilename{}, - expectedEnv: []v1.EnvVar{{Name: "T", Value: "V"}}, - }, { - description: "no Env.ValueFrom.ConfigMapKeyRef -> no changes", - sourceEnv: []v1.EnvVar{{Name: "T", ValueFrom: &v1.EnvVarSource{ResourceFieldRef: &v1.ResourceFieldSelector{}}}}, - configs: config.DataByFilename{}, - expectedEnv: []v1.EnvVar{{Name: "T", ValueFrom: &v1.EnvVarSource{ResourceFieldRef: &v1.ResourceFieldSelector{}}}}, - }, { - description: "CM reference but not ci-operator-configs -> no changes", - sourceEnv: []v1.EnvVar{{Name: "T", ValueFrom: makeCMReference("test-cm", "key")}}, - configs: config.DataByFilename{}, - expectedEnv: []v1.EnvVar{{Name: "T", ValueFrom: makeCMReference("test-cm", "key")}}, - }, + }{ + { + description: "not a ci-operator job -> no changes", + command: "not-ci-operator", + metadata: standardMetadata, + }, + { + description: "ci-operator job with CONFIG_SPEC -> no changes", + sourceEnv: []v1.EnvVar{{Name: "CONFIG_SPEC", Value: "this is kept"}}, + metadata: standardMetadata, + expectedEnv: []v1.EnvVar{{Name: "CONFIG_SPEC", Value: "this is kept"}}, + }, + { + description: "ci-operator job -> adds CONFIG_SPEC with resolved config for the given test (test1)", + testname: "test1", + metadata: standardMetadata, + expectedEnv: []v1.EnvVar{{Name: "CONFIG_SPEC", Value: string(testCiopConfigContentTest1)}}, + expectedImageStreamTagMap: apihelper.ImageStreamTagMap{"fancy/willem:first": types.NamespacedName{Namespace: "fancy", Name: "willem:first"}}, + }, { - // After DPTP-1685: jobs are not expected to refer to ci-operator CMs directly anymore, so - // rehearsals do not need to support that cases anymore - description: "CM reference to ci-operator-configs -> no changes; test1", + description: "ci-operator job -> adds CONFIG_SPEC with resolved config for the given test (test2)", + testname: "test2", + metadata: standardMetadata, + expectedEnv: []v1.EnvVar{{Name: "CONFIG_SPEC", Value: string(testCiopConfigContentTest2)}}, + }, + { + description: "ci-operator job with UNRESOLVED_CONFIG -> adds CONFIG_SPEC with resolved config for the given test (test1)", testname: "test1", - sourceEnv: []v1.EnvVar{{Name: "T", ValueFrom: makeCMReference(testCiopConfigInfo.ConfigMapName(), "filename")}}, - configs: config.DataByFilename{"filename": {Info: config.Info{Metadata: testCiopConfigInfo}, Configuration: testCiopConfig}}, - expectedEnv: []v1.EnvVar{{Name: "T", ValueFrom: makeCMReference(testCiopConfigInfo.ConfigMapName(), "filename")}}, + metadata: standardMetadata, + sourceEnv: []v1.EnvVar{{Name: "UNRESOLVED_CONFIG", Value: string(unresolvedConfigContent)}}, + expectedEnv: []v1.EnvVar{{Name: "CONFIG_SPEC", Value: string(test1ConfigContentFromUnresolved)}}, + }, + { + description: "Incomplete metadata -> error", + testname: "test1", + metadata: incompleteMetadata, + expectedError: true, + }, + { + description: "A non-ci-operator jobs with UNRESOLVED_CONFIG should be left untouched", + command: "not-ci-operator", + metadata: standardMetadata, + sourceEnv: []v1.EnvVar{{Name: "UNRESOLVED_CONFIG", Value: "should not change"}}, + expectedEnv: []v1.EnvVar{{Name: "UNRESOLVED_CONFIG", Value: "should not change"}}, }, } @@ -205,10 +268,17 @@ func TestInlineCiopConfig(t *testing.T) { for _, tc := range testCases { t.Run(tc.description, func(t *testing.T) { testLoggers := Loggers{logrus.New(), logrus.New()} - job := makeTestingPresubmitForEnv(tc.sourceEnv) - expectedJob := makeTestingPresubmitForEnv(tc.expectedEnv) + if tc.command == "" { + tc.command = "ci-operator" + } + var args []string + if tc.testname != "" { + args = append(args, fmt.Sprintf("--target=%s", tc.testname)) + } + job := makePresubmit(tc.command, tc.sourceEnv, args) + expectedJob := makePresubmit(tc.command, tc.expectedEnv, args) - imageStreamTags, err := inlineCiOpConfig(&job.Spec.Containers[0], tc.configs, resolver, testCiopConfigInfo, tc.testname, testLoggers) + imageStreamTags, err := inlineCiOpConfig(&job.Spec.Containers[0], configs, resolver, tc.metadata, tc.testname, testLoggers) if tc.expectedError && err == nil { t.Fatalf("Expected inlineCiopConfig() to return an error, none returned") diff --git a/test/integration/pj-rehearse/candidate/ci-operator/jobs/super/duper/super-duper-periodics.yaml b/test/integration/pj-rehearse/candidate/ci-operator/jobs/super/duper/super-duper-periodics.yaml index 5df3b6755b5..d43452e6a5e 100644 --- a/test/integration/pj-rehearse/candidate/ci-operator/jobs/super/duper/super-duper-periodics.yaml +++ b/test/integration/pj-rehearse/candidate/ci-operator/jobs/super/duper/super-duper-periodics.yaml @@ -75,3 +75,124 @@ periodics: requests: cpu: 10m serviceAccountName: ci-operator +- agent: kubernetes + decorate: true + extra_refs: + - base_ref: ciop-cfg-change + org: super + repo: duper + interval: 24h + labels: + pj-rehearse.openshift.io/can-be-rehearsed: "true" + name: periodic-ci-super-duper-periodic-with-unresolved-config + spec: + containers: + - args: + - --no-ci-op-args + - --target=multistage + command: + - ci-operator + env: + - name: UNRESOLVED_CONFIG + value: | + resources: + '*': + limits: + cpu: 500Mi + requests: + cpu: 10Mi + tag_specification: + name: "4.7" + namespace: ocp + tests: + - as: multistage + steps: + cluster_profile: "" + test: + - as: e2e + commands: this is targeted, it should be in inlined CONFIG_SPEC + from: my-image + resources: + requests: + cpu: 1000m + memory: 2Gi + workflow: ipi + - as: also-multistage + steps: + cluster_profile: "" + test: + - as: e2e + commands: this is not targeted, it should not be in inlined CONFIG_SPEC + from: my-image + resources: + requests: + cpu: 1000m + memory: 2Gi + workflow: ipi + image: ci-operator:latest + imagePullPolicy: Always + name: "" + resources: + requests: + cpu: 10m + serviceAccountName: ci-operator +- agent: kubernetes + decorate: true + extra_refs: + - base_ref: ciop-cfg-change + org: super + repo: duper + interval: 24h + labels: + pj-rehearse.openshift.io/can-be-rehearsed: "true" + name: periodic-ci-super-duper-periodic-with-unresolved-config-no-target + spec: + containers: + - args: + - --no-ci-op-args + command: + - ci-operator + env: + - name: UNRESOLVED_CONFIG + value: | + resources: + '*': + limits: + cpu: 500Mi + requests: + cpu: 10Mi + tag_specification: + name: "4.7" + namespace: ocp + tests: + - as: multistage + steps: + cluster_profile: "" + test: + - as: e2e + commands: this job has no --target so this test should be in inline CONFIG_SPEC + from: my-image + resources: + requests: + cpu: 1000m + memory: 2Gi + workflow: ipi + - as: also-multistage + steps: + cluster_profile: "" + test: + - as: e2e + commands: this job has no --target so this test should be in inline CONFIG_SPEC + from: my-image + resources: + requests: + cpu: 1000m + memory: 2Gi + workflow: ipi + image: ci-operator:latest + imagePullPolicy: Always + name: "" + resources: + requests: + cpu: 10m + serviceAccountName: ci-operator diff --git a/test/integration/pj-rehearse/expected.yaml b/test/integration/pj-rehearse/expected.yaml index 51cbd4488f0..e3cb68e8ade 100644 --- a/test/integration/pj-rehearse/expected.yaml +++ b/test/integration/pj-rehearse/expected.yaml @@ -345,6 +345,327 @@ status: startTime: 2020-06-22T22:25:00Z state: triggered +- apiVersion: prow.k8s.io/v1 + kind: ProwJob + metadata: + annotations: + prow.k8s.io/job: rehearse-1234-periodic-ci-super-duper-periodic-with-unresolved-config + creationTimestamp: null + labels: + ci.openshift.org/rehearse: "1234" + created-by-prow: "true" + pj-rehearse.openshift.io/can-be-rehearsed: "true" + prow.k8s.io/job: rehearse-1234-periodic-ci-super-duper-periodic-with-unresolved + prow.k8s.io/refs.org: openshift + prow.k8s.io/refs.pull: "1234" + prow.k8s.io/refs.repo: release + prow.k8s.io/type: presubmit + name: test-prowjob + namespace: test-namespace + resourceVersion: "1" + spec: + agent: kubernetes + cluster: default + context: ci/rehearse/periodic-ci-super-duper-periodic-with-unresolved-config + decoration_config: + gcs_configuration: + bucket: origin-ci-test + default_org: openshift + default_repo: origin + path_strategy: single + gcs_credentials_secret: gce-sa-credentials-gcs-publisher + grace_period: 15s + timeout: 4h0m0s + utility_images: + clonerefs: gcr.io/k8s-prow/clonerefs:v20190129-0a3c54c + entrypoint: gcr.io/k8s-prow/entrypoint:v20190129-0a3c54c + initupload: gcr.io/k8s-prow/initupload:v20190129-0a3c54c + sidecar: gcr.io/k8s-prow/sidecar:v20190129-0a3c54c + extra_refs: + - base_ref: ciop-cfg-change + org: super + repo: duper + workdir: true + job: rehearse-1234-periodic-ci-super-duper-periodic-with-unresolved-config + namespace: test-namespace + pod_spec: + containers: + - args: + - --no-ci-op-args + - --target=multistage + command: + - ci-operator + env: + - name: CONFIG_SPEC + value: | + resources: + '*': + limits: + cpu: 500Mi + requests: + cpu: 10Mi + tag_specification: + name: "4.7" + namespace: ocp + tests: + - as: multistage + literal_steps: + cluster_profile: "" + post: + - as: ipi-deprovision-must-gather + commands: | + gather + from: installer + resources: + requests: + cpu: 1000m + memory: 2Gi + - as: ipi-deprovision-deprovision + commands: | + openshift-cluster destroy + from: installer + resources: + requests: + cpu: 1000m + memory: 2Gi + pre: + - as: ipi-install-rbac + commands: | + setup-rbac-2 + from: installer + resources: + requests: + cpu: 1000m + memory: 2Gi + - as: ipi-install-install + commands: | + openshift-cluster install --newFlag + env: + - default: test parameter default + name: TEST_PARAMETER + from: installer + resources: + requests: + cpu: 1000m + memory: 2Gi + test: + - as: e2e + commands: this is targeted, it should be in inlined CONFIG_SPEC + from: my-image + resources: + requests: + cpu: 1000m + memory: 2Gi + zz_generated_metadata: + branch: "" + org: "" + repo: "" + image: ci-operator:latest + imagePullPolicy: Always + name: "" + resources: + requests: + cpu: 10m + serviceAccountName: ci-operator + refs: + base_ref: master + base_sha: test_sha + org: openshift + pulls: + - author: petr-muller + number: 1234 + sha: test_sha + repo: release + report: true + rerun_command: /test pj-rehearse + type: presubmit + status: + startTime: 2020-06-22T22:25:00Z + state: triggered +- apiVersion: prow.k8s.io/v1 + kind: ProwJob + metadata: + annotations: + prow.k8s.io/job: rehearse-1234-periodic-ci-super-duper-periodic-with-unresolved-config-no-target + creationTimestamp: null + labels: + ci.openshift.org/rehearse: "1234" + created-by-prow: "true" + pj-rehearse.openshift.io/can-be-rehearsed: "true" + prow.k8s.io/job: rehearse-1234-periodic-ci-super-duper-periodic-with-unresolved + prow.k8s.io/refs.org: openshift + prow.k8s.io/refs.pull: "1234" + prow.k8s.io/refs.repo: release + prow.k8s.io/type: presubmit + name: test-prowjob + namespace: test-namespace + resourceVersion: "1" + spec: + agent: kubernetes + cluster: default + context: ci/rehearse/periodic-ci-super-duper-periodic-with-unresolved-config-no-target + decoration_config: + gcs_configuration: + bucket: origin-ci-test + default_org: openshift + default_repo: origin + path_strategy: single + gcs_credentials_secret: gce-sa-credentials-gcs-publisher + grace_period: 15s + timeout: 4h0m0s + utility_images: + clonerefs: gcr.io/k8s-prow/clonerefs:v20190129-0a3c54c + entrypoint: gcr.io/k8s-prow/entrypoint:v20190129-0a3c54c + initupload: gcr.io/k8s-prow/initupload:v20190129-0a3c54c + sidecar: gcr.io/k8s-prow/sidecar:v20190129-0a3c54c + extra_refs: + - base_ref: ciop-cfg-change + org: super + repo: duper + workdir: true + job: rehearse-1234-periodic-ci-super-duper-periodic-with-unresolved-config-no-target + namespace: test-namespace + pod_spec: + containers: + - args: + - --no-ci-op-args + command: + - ci-operator + env: + - name: CONFIG_SPEC + value: | + resources: + '*': + limits: + cpu: 500Mi + requests: + cpu: 10Mi + tag_specification: + name: "4.7" + namespace: ocp + tests: + - as: multistage + literal_steps: + cluster_profile: "" + post: + - as: ipi-deprovision-must-gather + commands: | + gather + from: installer + resources: + requests: + cpu: 1000m + memory: 2Gi + - as: ipi-deprovision-deprovision + commands: | + openshift-cluster destroy + from: installer + resources: + requests: + cpu: 1000m + memory: 2Gi + pre: + - as: ipi-install-rbac + commands: | + setup-rbac-2 + from: installer + resources: + requests: + cpu: 1000m + memory: 2Gi + - as: ipi-install-install + commands: | + openshift-cluster install --newFlag + env: + - default: test parameter default + name: TEST_PARAMETER + from: installer + resources: + requests: + cpu: 1000m + memory: 2Gi + test: + - as: e2e + commands: this job has no --target so this test should be in inline CONFIG_SPEC + from: my-image + resources: + requests: + cpu: 1000m + memory: 2Gi + - as: also-multistage + literal_steps: + cluster_profile: "" + post: + - as: ipi-deprovision-must-gather + commands: | + gather + from: installer + resources: + requests: + cpu: 1000m + memory: 2Gi + - as: ipi-deprovision-deprovision + commands: | + openshift-cluster destroy + from: installer + resources: + requests: + cpu: 1000m + memory: 2Gi + pre: + - as: ipi-install-rbac + commands: | + setup-rbac-2 + from: installer + resources: + requests: + cpu: 1000m + memory: 2Gi + - as: ipi-install-install + commands: | + openshift-cluster install --newFlag + env: + - default: test parameter default + name: TEST_PARAMETER + from: installer + resources: + requests: + cpu: 1000m + memory: 2Gi + test: + - as: e2e + commands: this job has no --target so this test should be in inline CONFIG_SPEC + from: my-image + resources: + requests: + cpu: 1000m + memory: 2Gi + zz_generated_metadata: + branch: "" + org: "" + repo: "" + image: ci-operator:latest + imagePullPolicy: Always + name: "" + resources: + requests: + cpu: 10m + serviceAccountName: ci-operator + refs: + base_ref: master + base_sha: test_sha + org: openshift + pulls: + - author: petr-muller + number: 1234 + sha: test_sha + repo: release + report: true + rerun_command: /test pj-rehearse + type: presubmit + status: + startTime: 2020-06-22T22:25:00Z + state: triggered - apiVersion: prow.k8s.io/v1 kind: ProwJob metadata: