From b8e244a66b40da3d15e025eed92642461845ccee Mon Sep 17 00:00:00 2001 From: Lee Bernick Date: Fri, 22 Jul 2022 12:16:10 -0400 Subject: [PATCH] Add StdoutConfig and StderrorConfig to v1 Step These fields were previously added to v1beta1 Step, and should be present in the v1 API as well. This commit adds these fields to the v1 package. --- pkg/apis/pipeline/v1/container_types.go | 13 +++++++ pkg/apis/pipeline/v1/merge.go | 2 +- pkg/apis/pipeline/v1/merge_test.go | 22 ++++++++++++ pkg/apis/pipeline/v1/openapi_generated.go | 35 ++++++++++++++++++- pkg/apis/pipeline/v1/swagger.json | 18 ++++++++++ pkg/apis/pipeline/v1/task_validation.go | 10 ++++++ pkg/apis/pipeline/v1/task_validation_test.go | 24 ++++++++++++- pkg/apis/pipeline/v1/zz_generated.deepcopy.go | 26 ++++++++++++++ 8 files changed, 147 insertions(+), 3 deletions(-) diff --git a/pkg/apis/pipeline/v1/container_types.go b/pkg/apis/pipeline/v1/container_types.go index 407c05cc436..f6e75960ff0 100644 --- a/pkg/apis/pipeline/v1/container_types.go +++ b/pkg/apis/pipeline/v1/container_types.go @@ -135,6 +135,19 @@ type Step struct { // stopAndFail indicates exit the taskRun if the container exits with non-zero exit code // continue indicates continue executing the rest of the steps irrespective of the container exit code OnError string `json:"onError,omitempty"` + // Stores configuration for the stdout stream of the step. + // +optional + StdoutConfig *StepOutputConfig `json:"stdoutConfig,omitempty"` + // Stores configuration for the stderr stream of the step. + // +optional + StderrConfig *StepOutputConfig `json:"stderrConfig,omitempty"` +} + +// StepOutputConfig stores configuration for a step output stream. +type StepOutputConfig struct { + // Path to duplicate stdout stream to on container's local filesystem. + // +optional + Path string `json:"path,omitempty"` } // ToK8sContainer converts the Step to a Kubernetes Container struct diff --git a/pkg/apis/pipeline/v1/merge.go b/pkg/apis/pipeline/v1/merge.go index 6075ac04980..b7995ae90ae 100644 --- a/pkg/apis/pipeline/v1/merge.go +++ b/pkg/apis/pipeline/v1/merge.go @@ -58,7 +58,7 @@ func MergeStepsWithStepTemplate(template *StepTemplate, steps []Step) ([]Step, e } // Pass through original step Script, for later conversion. - newStep := Step{Script: s.Script, OnError: s.OnError, Timeout: s.Timeout} + newStep := Step{Script: s.Script, OnError: s.OnError, Timeout: s.Timeout, StdoutConfig: s.StdoutConfig, StderrConfig: s.StderrConfig} newStep.SetContainerFields(merged) steps[i] = newStep } diff --git a/pkg/apis/pipeline/v1/merge_test.go b/pkg/apis/pipeline/v1/merge_test.go index 8fa836f7bab..ee604ee9631 100644 --- a/pkg/apis/pipeline/v1/merge_test.go +++ b/pkg/apis/pipeline/v1/merge_test.go @@ -105,6 +105,28 @@ func TestMergeStepsWithStepTemplate(t *testing.T) { Value: "NEW_VALUE", }}, }}, + }, { + name: "workspace-and-output-config", + template: &v1.StepTemplate{ + VolumeMounts: []corev1.VolumeMount{{ + Name: "data", + MountPath: "/workspace/data", + }}, + }, + steps: []v1.Step{{ + Image: "some-image", + StdoutConfig: &v1.StepOutputConfig{Path: "stdout.txt"}, + StderrConfig: &v1.StepOutputConfig{Path: "stderr.txt"}, + }}, + expected: []v1.Step{{ + Image: "some-image", + StdoutConfig: &v1.StepOutputConfig{Path: "stdout.txt"}, + StderrConfig: &v1.StepOutputConfig{Path: "stderr.txt"}, + VolumeMounts: []corev1.VolumeMount{{ + Name: "data", + MountPath: "/workspace/data", + }}, + }}, }} { t.Run(tc.name, func(t *testing.T) { result, err := v1.MergeStepsWithStepTemplate(tc.template, tc.steps) diff --git a/pkg/apis/pipeline/v1/openapi_generated.go b/pkg/apis/pipeline/v1/openapi_generated.go index d389b93a804..15ba0a4f8c5 100644 --- a/pkg/apis/pipeline/v1/openapi_generated.go +++ b/pkg/apis/pipeline/v1/openapi_generated.go @@ -41,6 +41,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1.ResolverRef": schema_pkg_apis_pipeline_v1_ResolverRef(ref), "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1.Sidecar": schema_pkg_apis_pipeline_v1_Sidecar(ref), "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1.Step": schema_pkg_apis_pipeline_v1_Step(ref), + "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1.StepOutputConfig": schema_pkg_apis_pipeline_v1_StepOutputConfig(ref), "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1.StepTemplate": schema_pkg_apis_pipeline_v1_StepTemplate(ref), "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1.Task": schema_pkg_apis_pipeline_v1_Task(ref), "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1.TaskList": schema_pkg_apis_pipeline_v1_TaskList(ref), @@ -1076,12 +1077,44 @@ func schema_pkg_apis_pipeline_v1_Step(ref common.ReferenceCallback) common.OpenA Format: "", }, }, + "stdoutConfig": { + SchemaProps: spec.SchemaProps{ + Description: "Stores configuration for the stdout stream of the step.", + Ref: ref("github.com/tektoncd/pipeline/pkg/apis/pipeline/v1.StepOutputConfig"), + }, + }, + "stderrConfig": { + SchemaProps: spec.SchemaProps{ + Description: "Stores configuration for the stderr stream of the step.", + Ref: ref("github.com/tektoncd/pipeline/pkg/apis/pipeline/v1.StepOutputConfig"), + }, + }, }, Required: []string{"name"}, }, }, Dependencies: []string{ - "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1.WorkspaceUsage", "k8s.io/api/core/v1.EnvFromSource", "k8s.io/api/core/v1.EnvVar", "k8s.io/api/core/v1.ResourceRequirements", "k8s.io/api/core/v1.SecurityContext", "k8s.io/api/core/v1.VolumeDevice", "k8s.io/api/core/v1.VolumeMount", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration"}, + "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1.StepOutputConfig", "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1.WorkspaceUsage", "k8s.io/api/core/v1.EnvFromSource", "k8s.io/api/core/v1.EnvVar", "k8s.io/api/core/v1.ResourceRequirements", "k8s.io/api/core/v1.SecurityContext", "k8s.io/api/core/v1.VolumeDevice", "k8s.io/api/core/v1.VolumeMount", "k8s.io/apimachinery/pkg/apis/meta/v1.Duration"}, + } +} + +func schema_pkg_apis_pipeline_v1_StepOutputConfig(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "StepOutputConfig stores configuration for a step output stream.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "path": { + SchemaProps: spec.SchemaProps{ + Description: "Path to duplicate stdout stream to on container's local filesystem.", + Type: []string{"string"}, + Format: "", + }, + }, + }, + }, + }, } } diff --git a/pkg/apis/pipeline/v1/swagger.json b/pkg/apis/pipeline/v1/swagger.json index a945319cde9..87ba8b238ff 100644 --- a/pkg/apis/pipeline/v1/swagger.json +++ b/pkg/apis/pipeline/v1/swagger.json @@ -523,6 +523,14 @@ "description": "SecurityContext defines the security options the container should be run with. If set, the fields of SecurityContext override the equivalent fields of PodSecurityContext. More info: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/", "$ref": "#/definitions/v1.SecurityContext" }, + "stderrConfig": { + "description": "Stores configuration for the stderr stream of the step.", + "$ref": "#/definitions/v1.StepOutputConfig" + }, + "stdoutConfig": { + "description": "Stores configuration for the stdout stream of the step.", + "$ref": "#/definitions/v1.StepOutputConfig" + }, "timeout": { "description": "Timeout is the time after which the step times out. Defaults to never. Refer to Go's ParseDuration documentation for expected format: https://golang.org/pkg/time/#ParseDuration", "$ref": "#/definitions/v1.Duration" @@ -564,6 +572,16 @@ } } }, + "v1.StepOutputConfig": { + "description": "StepOutputConfig stores configuration for a step output stream.", + "type": "object", + "properties": { + "path": { + "description": "Path to duplicate stdout stream to on container's local filesystem.", + "type": "string" + } + } + }, "v1.StepTemplate": { "description": "StepTemplate is a template for a Step", "type": "object", diff --git a/pkg/apis/pipeline/v1/task_validation.go b/pkg/apis/pipeline/v1/task_validation.go index 75b32e2096e..10d44700473 100644 --- a/pkg/apis/pipeline/v1/task_validation.go +++ b/pkg/apis/pipeline/v1/task_validation.go @@ -256,6 +256,16 @@ func validateStep(ctx context.Context, s Step, names sets.String) (errs *apis.Fi errs = errs.Also(version.ValidateEnabledAPIFields(ctx, "windows script support", config.AlphaAPIFields).ViaField("script")) } } + // StdoutConfig is an alpha feature and will fail validation if it's used in a task spec + // when the enable-api-fields feature gate is not "alpha". + if s.StdoutConfig != nil { + errs = errs.Also(version.ValidateEnabledAPIFields(ctx, "step stdout stream support", config.AlphaAPIFields).ViaField("stdoutconfig")) + } + // StderrConfig is an alpha feature and will fail validation if it's used in a task spec + // when the enable-api-fields feature gate is not "alpha". + if s.StderrConfig != nil { + errs = errs.Also(version.ValidateEnabledAPIFields(ctx, "step stderr stream support", config.AlphaAPIFields).ViaField("stderrconfig")) + } return errs } diff --git a/pkg/apis/pipeline/v1/task_validation_test.go b/pkg/apis/pipeline/v1/task_validation_test.go index b05c9287043..000540d7600 100644 --- a/pkg/apis/pipeline/v1/task_validation_test.go +++ b/pkg/apis/pipeline/v1/task_validation_test.go @@ -1408,7 +1408,29 @@ func TestIncompatibleAPIVersions(t *testing.T) { script-1`, }}, }, - }} + }, { + name: "stdout stream support requires alpha", + requiredVersion: "alpha", + spec: v1.TaskSpec{ + Steps: []v1.Step{{ + Image: "foo", + StdoutConfig: &v1.StepOutputConfig{ + Path: "/tmp/stdout.txt", + }, + }}, + }, + }, { + name: "stderr stream support requires alpha", + requiredVersion: "alpha", + spec: v1.TaskSpec{ + Steps: []v1.Step{{ + Image: "foo", + StderrConfig: &v1.StepOutputConfig{ + Path: "/tmp/stderr.txt", + }, + }}, + }}, + } versions := []string{"alpha", "stable"} for _, tt := range tests { for _, version := range versions { diff --git a/pkg/apis/pipeline/v1/zz_generated.deepcopy.go b/pkg/apis/pipeline/v1/zz_generated.deepcopy.go index 55bd52f8892..f618a687483 100644 --- a/pkg/apis/pipeline/v1/zz_generated.deepcopy.go +++ b/pkg/apis/pipeline/v1/zz_generated.deepcopy.go @@ -312,6 +312,16 @@ func (in *Step) DeepCopyInto(out *Step) { *out = make([]WorkspaceUsage, len(*in)) copy(*out, *in) } + if in.StdoutConfig != nil { + in, out := &in.StdoutConfig, &out.StdoutConfig + *out = new(StepOutputConfig) + **out = **in + } + if in.StderrConfig != nil { + in, out := &in.StderrConfig, &out.StderrConfig + *out = new(StepOutputConfig) + **out = **in + } return } @@ -325,6 +335,22 @@ func (in *Step) DeepCopy() *Step { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StepOutputConfig) DeepCopyInto(out *StepOutputConfig) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StepOutputConfig. +func (in *StepOutputConfig) DeepCopy() *StepOutputConfig { + if in == nil { + return nil + } + out := new(StepOutputConfig) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *StepTemplate) DeepCopyInto(out *StepTemplate) { *out = *in