diff --git a/pkg/apis/pipeline/v1/task_conversion.go b/pkg/apis/pipeline/v1/task_conversion.go new file mode 100644 index 00000000000..1e3ef4da890 --- /dev/null +++ b/pkg/apis/pipeline/v1/task_conversion.go @@ -0,0 +1,39 @@ +/* +Copyright 2022 The Tekton Authors +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "context" + "fmt" + + "knative.dev/pkg/apis" +) + +var _ apis.Convertible = (*Task)(nil) + +// ConvertTo implements apis.Convertible +func (t *Task) ConvertTo(ctx context.Context, sink apis.Convertible) error { + if apis.IsInDelete(ctx) { + return nil + } + return fmt.Errorf("v1 is the highest known version, got: %T", sink) +} + +// ConvertFrom implements apis.Convertible +func (t *Task) ConvertFrom(ctx context.Context, source apis.Convertible) error { + if apis.IsInDelete(ctx) { + return nil + } + return fmt.Errorf("v1 is the highest know version, got: %T", source) +} diff --git a/pkg/apis/pipeline/v1/task_conversion_test.go b/pkg/apis/pipeline/v1/task_conversion_test.go new file mode 100644 index 00000000000..2244fd101d2 --- /dev/null +++ b/pkg/apis/pipeline/v1/task_conversion_test.go @@ -0,0 +1,43 @@ +/* +Copyright 2022 The Tetkon Authors +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1_test + +import ( + "context" + "testing" + + v1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" + "knative.dev/pkg/apis" +) + +type convertible struct{} + +func (c *convertible) ConvertTo(ctx context.Context, sink apis.Convertible) error { + return nil +} +func (c *convertible) ConvertFrom(ctx context.Context, source apis.Convertible) error { + return nil +} + +func TestTaskConversionBadType(t *testing.T) { + good, bad := &v1.Task{}, &convertible{} + + if err := good.ConvertTo(context.Background(), bad); err == nil { + t.Errorf("ConvertTo() = %#v, wanted error", bad) + } + + if err := good.ConvertFrom(context.Background(), bad); err == nil { + t.Errorf("ConvertFrom() = %#v, wanted error", good) + } +} diff --git a/pkg/apis/pipeline/v1beta1/container_conversion.go b/pkg/apis/pipeline/v1beta1/container_conversion.go new file mode 100644 index 00000000000..d6ed1f60cb4 --- /dev/null +++ b/pkg/apis/pipeline/v1beta1/container_conversion.go @@ -0,0 +1,160 @@ +package v1beta1 + +import ( + "context" + + v1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" +) + +func (s Step) convertTo(ctx context.Context, sink *v1.Step) { + sink.Name = s.Name + sink.Image = s.Image + sink.Command = s.Command + sink.Args = s.Args + sink.WorkingDir = s.WorkingDir + sink.EnvFrom = s.EnvFrom + sink.Env = s.Env + sink.Resources = s.Resources + sink.VolumeMounts = s.VolumeMounts + sink.VolumeDevices = s.VolumeDevices + sink.ImagePullPolicy = s.ImagePullPolicy + sink.SecurityContext = s.SecurityContext + sink.Script = s.Script + sink.Timeout = s.Timeout + + sink.Workspaces = nil + for _, w := range s.Workspaces { + new := v1.WorkspaceUsage{} + w.convertTo(ctx, &new) + sink.Workspaces = append(sink.Workspaces, new) + } + sink.OnError = s.OnError + sink.StdoutConfig = (*v1.StepOutputConfig)(s.StdoutConfig) + sink.StderrConfig = (*v1.StepOutputConfig)(s.StderrConfig) + + // TODO(#4546): Handle deprecated fields + // Ports, LivenessProbe, ReadinessProbe, StartupProbe, Lifecycle, TerminationMessagePath + // TerminationMessagePolicy, Stdin, StdinOnce, TTY +} + +func (s *Step) convertFrom(ctx context.Context, source v1.Step) { + s.Name = source.Name + s.Image = source.Image + s.Command = source.Command + s.Args = source.Args + s.WorkingDir = source.WorkingDir + s.EnvFrom = source.EnvFrom + s.Env = source.Env + s.Resources = source.Resources + s.VolumeMounts = source.VolumeMounts + s.VolumeDevices = source.VolumeDevices + s.ImagePullPolicy = source.ImagePullPolicy + s.SecurityContext = source.SecurityContext + s.Script = source.Script + s.Timeout = source.Timeout + + s.Workspaces = nil + for _, w := range source.Workspaces { + new := WorkspaceUsage{} + new.convertFrom(ctx, w) + s.Workspaces = append(s.Workspaces, new) + } + s.OnError = source.OnError + s.StdoutConfig = (*StepOutputConfig)(source.StdoutConfig) + s.StderrConfig = (*StepOutputConfig)(source.StderrConfig) +} + +func (s StepTemplate) convertTo(ctx context.Context, sink *v1.StepTemplate) { + sink.Image = s.Image + sink.Command = s.Command + sink.Args = s.Args + sink.WorkingDir = s.WorkingDir + sink.EnvFrom = s.EnvFrom + sink.Env = s.Env + sink.Resources = s.Resources + sink.VolumeMounts = s.VolumeMounts + sink.VolumeDevices = s.VolumeDevices + sink.ImagePullPolicy = s.ImagePullPolicy + sink.SecurityContext = s.SecurityContext + // TODO(#4546): Handle deprecated fields + // Name, Ports, LivenessProbe, ReadinessProbe, StartupProbe, Lifecycle, TerminationMessagePath + // TerminationMessagePolicy, Stdin, StdinOnce, TTY +} + +func (s *StepTemplate) convertFrom(ctx context.Context, source *v1.StepTemplate) { + s.Image = source.Image + s.Command = source.Command + s.Args = source.Args + s.WorkingDir = source.WorkingDir + s.EnvFrom = source.EnvFrom + s.Env = source.Env + s.Resources = source.Resources + s.VolumeMounts = source.VolumeMounts + s.VolumeDevices = source.VolumeDevices + s.ImagePullPolicy = source.ImagePullPolicy + s.SecurityContext = source.SecurityContext +} + +func (s Sidecar) convertTo(ctx context.Context, sink *v1.Sidecar) { + sink.Name = s.Name + sink.Image = s.Image + sink.Command = s.Command + sink.Args = s.Args + sink.WorkingDir = s.WorkingDir + sink.Ports = s.Ports + sink.EnvFrom = s.EnvFrom + sink.Env = s.Env + sink.Resources = s.Resources + sink.VolumeMounts = s.VolumeMounts + sink.VolumeDevices = s.VolumeDevices + sink.LivenessProbe = s.LivenessProbe + sink.ReadinessProbe = s.ReadinessProbe + sink.StartupProbe = s.StartupProbe + sink.Lifecycle = s.Lifecycle + sink.TerminationMessagePath = s.TerminationMessagePath + sink.TerminationMessagePolicy = s.TerminationMessagePolicy + sink.ImagePullPolicy = s.ImagePullPolicy + sink.SecurityContext = s.SecurityContext + sink.Stdin = s.Stdin + sink.StdinOnce = s.StdinOnce + sink.TTY = s.TTY + sink.Script = s.Script + sink.Workspaces = nil + for _, w := range s.Workspaces { + new := v1.WorkspaceUsage{} + w.convertTo(ctx, &new) + sink.Workspaces = append(sink.Workspaces, new) + } +} + +func (s *Sidecar) convertFrom(ctx context.Context, source v1.Sidecar) { + s.Name = source.Name + s.Image = source.Image + s.Command = source.Command + s.Args = source.Args + s.WorkingDir = source.WorkingDir + s.Ports = source.Ports + s.EnvFrom = source.EnvFrom + s.Env = source.Env + s.Resources = source.Resources + s.VolumeMounts = source.VolumeMounts + s.VolumeDevices = source.VolumeDevices + s.LivenessProbe = source.LivenessProbe + s.ReadinessProbe = source.ReadinessProbe + s.StartupProbe = source.StartupProbe + s.Lifecycle = source.Lifecycle + s.TerminationMessagePath = source.TerminationMessagePath + s.TerminationMessagePolicy = source.TerminationMessagePolicy + s.ImagePullPolicy = source.ImagePullPolicy + s.SecurityContext = source.SecurityContext + s.Stdin = source.Stdin + s.StdinOnce = source.StdinOnce + s.TTY = source.TTY + s.Script = source.Script + s.Workspaces = nil + for _, w := range source.Workspaces { + new := WorkspaceUsage{} + new.convertFrom(ctx, w) + s.Workspaces = append(s.Workspaces, new) + } +} diff --git a/pkg/apis/pipeline/v1beta1/param_conversion.go b/pkg/apis/pipeline/v1beta1/param_conversion.go new file mode 100644 index 00000000000..7c6f33fe1ce --- /dev/null +++ b/pkg/apis/pipeline/v1beta1/param_conversion.go @@ -0,0 +1,47 @@ +package v1beta1 + +import ( + "context" + + v1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" +) + +func (p ParamSpec) convertTo(ctx context.Context, sink *v1.ParamSpec) { + sink.Name = p.Name + sink.Type = v1.ParamType(p.Type) + sink.Description = p.Description + var properties map[string]v1.PropertySpec + if p.Properties != nil { + properties = make(map[string]v1.PropertySpec) + } + for k, v := range p.Properties { + properties[k] = v1.PropertySpec{Type: v1.ParamType(v.Type)} + } + sink.Properties = properties + if p.Default != nil { + sink.Default = &v1.ArrayOrString{ + Type: v1.ParamType(p.Default.Type), StringVal: p.Default.StringVal, + ArrayVal: p.Default.ArrayVal, ObjectVal: p.Default.ObjectVal, + } + } +} + +func (p *ParamSpec) convertFrom(ctx context.Context, source v1.ParamSpec) { + p.Name = source.Name + p.Type = ParamType(source.Type) + p.Description = source.Description + var properties map[string]PropertySpec + if source.Properties != nil { + properties = make(map[string]PropertySpec) + } + for k, v := range source.Properties { + properties[k] = PropertySpec{Type: ParamType(v.Type)} + } + p.Properties = properties + if source.Default != nil { + p.Default = &ArrayOrString{ + Type: ParamType(source.Default.Type), StringVal: source.Default.StringVal, + ArrayVal: source.Default.ArrayVal, ObjectVal: source.Default.ObjectVal, + } + } +} diff --git a/pkg/apis/pipeline/v1beta1/result_conversion.go b/pkg/apis/pipeline/v1beta1/result_conversion.go new file mode 100644 index 00000000000..70197bed164 --- /dev/null +++ b/pkg/apis/pipeline/v1beta1/result_conversion.go @@ -0,0 +1,29 @@ +package v1beta1 + +import ( + "context" + + v1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" +) + +func (r TaskResult) convertTo(ctx context.Context, sink *v1.TaskResult) { + sink.Name = r.Name + sink.Type = v1.ResultsType(r.Type) + sink.Description = r.Description + properties := make(map[string]v1.PropertySpec) + for k, v := range r.Properties { + properties[k] = v1.PropertySpec{Type: v1.ParamType(v.Type)} + } + sink.Properties = properties +} + +func (r *TaskResult) convertFrom(ctx context.Context, source v1.TaskResult) { + r.Name = source.Name + r.Type = ResultsType(source.Type) + r.Description = source.Description + properties := make(map[string]PropertySpec) + for k, v := range source.Properties { + properties[k] = PropertySpec{Type: ParamType(v.Type)} + } + r.Properties = properties +} diff --git a/pkg/apis/pipeline/v1beta1/task_conversion.go b/pkg/apis/pipeline/v1beta1/task_conversion.go index f8155cd97c0..9cf8bdbfed7 100644 --- a/pkg/apis/pipeline/v1beta1/task_conversion.go +++ b/pkg/apis/pipeline/v1beta1/task_conversion.go @@ -20,23 +20,121 @@ import ( "context" "fmt" + v1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" "knative.dev/pkg/apis" ) var _ apis.Convertible = (*Task)(nil) -// ConvertTo implements api.Convertible -func (t *Task) ConvertTo(ctx context.Context, sink apis.Convertible) error { +// ConvertTo implements apis.Convertible +func (t *Task) ConvertTo(ctx context.Context, to apis.Convertible) error { if apis.IsInDelete(ctx) { return nil } - return fmt.Errorf("v1beta1 is the highest known version, got: %T", sink) + switch sink := to.(type) { + case *v1.Task: + sink.ObjectMeta = t.ObjectMeta + return t.Spec.ConvertTo(ctx, &sink.Spec) + default: + return fmt.Errorf("unknown version, got: %T", sink) + } +} + +// ConvertTo implements apis.Convertible +func (ts *TaskSpec) ConvertTo(ctx context.Context, sink *v1.TaskSpec) error { + sink.Steps = nil + for _, s := range ts.Steps { + new := v1.Step{} + s.convertTo(ctx, &new) + sink.Steps = append(sink.Steps, new) + } + sink.Volumes = ts.Volumes + if ts.StepTemplate != nil { + new := v1.StepTemplate{} + ts.StepTemplate.convertTo(ctx, &new) + sink.StepTemplate = &new + } + sink.Sidecars = nil + for _, s := range ts.Sidecars { + new := v1.Sidecar{} + s.convertTo(ctx, &new) + sink.Sidecars = append(sink.Sidecars, new) + } + sink.Workspaces = nil + for _, w := range ts.Workspaces { + new := v1.WorkspaceDeclaration{} + w.convertTo(ctx, &new) + sink.Workspaces = append(sink.Workspaces, new) + } + sink.Results = nil + for _, r := range ts.Results { + new := v1.TaskResult{} + r.convertTo(ctx, &new) + sink.Results = append(sink.Results, new) + } + sink.Params = nil + for _, r := range ts.Params { + new := v1.ParamSpec{} + r.convertTo(ctx, &new) + sink.Params = append(sink.Params, new) + } + sink.Description = ts.Description + // TODO(#4546): Handle Resources + return nil } -// ConvertFrom implements api.Convertible -func (t *Task) ConvertFrom(ctx context.Context, source apis.Convertible) error { +// ConvertFrom implements apis.Convertible +func (t *Task) ConvertFrom(ctx context.Context, from apis.Convertible) error { if apis.IsInDelete(ctx) { return nil } - return fmt.Errorf("v1beta1 is the highest know version, got: %T", source) + switch source := from.(type) { + case *v1.Task: + t.ObjectMeta = source.ObjectMeta + return t.Spec.ConvertFrom(ctx, &source.Spec) + default: + return fmt.Errorf("unknown version, got: %T", t) + } +} + +// ConvertFrom implements apis.Convertible +func (ts *TaskSpec) ConvertFrom(ctx context.Context, source *v1.TaskSpec) error { + ts.Steps = nil + for _, s := range source.Steps { + new := Step{} + new.convertFrom(ctx, s) + ts.Steps = append(ts.Steps, new) + } + ts.Volumes = source.Volumes + if source.StepTemplate != nil { + new := StepTemplate{} + new.convertFrom(ctx, source.StepTemplate) + ts.StepTemplate = &new + } + ts.Sidecars = nil + for _, s := range source.Sidecars { + new := Sidecar{} + new.convertFrom(ctx, s) + ts.Sidecars = append(ts.Sidecars, new) + } + ts.Workspaces = nil + for _, w := range source.Workspaces { + new := WorkspaceDeclaration{} + new.convertFrom(ctx, w) + ts.Workspaces = append(ts.Workspaces, new) + } + ts.Results = nil + for _, r := range source.Results { + new := TaskResult{} + new.convertFrom(ctx, r) + ts.Results = append(ts.Results, new) + } + ts.Params = nil + for _, p := range source.Params { + new := ParamSpec{} + new.convertFrom(ctx, p) + ts.Params = append(ts.Params, new) + } + ts.Description = source.Description + return nil } diff --git a/pkg/apis/pipeline/v1beta1/task_conversion_test.go b/pkg/apis/pipeline/v1beta1/task_conversion_test.go index 3ee57a2c3b0..7c99582191f 100644 --- a/pkg/apis/pipeline/v1beta1/task_conversion_test.go +++ b/pkg/apis/pipeline/v1beta1/task_conversion_test.go @@ -14,21 +14,249 @@ See the License for the specific language governing permissions and limitations under the License. */ -package v1beta1 +package v1beta1_test import ( "context" "testing" + "time" + + "github.com/google/go-cmp/cmp" + v1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" + "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" + "github.com/tektoncd/pipeline/test/diff" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "knative.dev/pkg/apis" ) func TestTaskConversionBadType(t *testing.T) { - good, bad := &Task{}, &Pipeline{} + good, bad := &v1beta1.Task{}, &v1beta1.Pipeline{} if err := good.ConvertTo(context.Background(), bad); err == nil { t.Errorf("ConvertTo() = %#v, wanted error", bad) } if err := good.ConvertFrom(context.Background(), bad); err == nil { - t.Errorf("ConvertFrom() = %#v, wanted error", good) + t.Errorf("ConvertTo() = %#v, wanted error", bad) + } +} + +func TestTaskConversion(t *testing.T) { + versions := []apis.Convertible{&v1.Task{}} + + tests := []struct { + name string + in *v1beta1.Task + }{{ + name: "simple task", + in: &v1beta1.Task{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: "bar", + Generation: 1, + }, + Spec: v1beta1.TaskSpec{ + Description: "test", + Steps: []v1beta1.Step{{ + Image: "foo", + }}, + Volumes: []corev1.Volume{{}}, + Params: []v1beta1.ParamSpec{{ + Name: "param-1", + Type: v1beta1.ParamTypeString, + Description: "My first param", + }}, + }, + }, + }, { + name: "task conversion all non deprecated fields", + in: &v1beta1.Task{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: "bar", + Generation: 1, + }, + Spec: v1beta1.TaskSpec{ + Description: "test", + Steps: []v1beta1.Step{{ + Name: "step", + Image: "foo", + Command: []string{"hello"}, + Args: []string{"world"}, + WorkingDir: "/dir", + EnvFrom: []corev1.EnvFromSource{{Prefix: "prefix"}}, + Env: []corev1.EnvVar{{Name: "var"}}, + Resources: corev1.ResourceRequirements{}, + VolumeMounts: []corev1.VolumeMount{}, + VolumeDevices: []corev1.VolumeDevice{}, + ImagePullPolicy: corev1.PullIfNotPresent, + SecurityContext: &corev1.SecurityContext{}, + Script: "echo hello", + Timeout: &metav1.Duration{Duration: time.Hour}, + Workspaces: []v1beta1.WorkspaceUsage{{Name: "workspace"}}, + OnError: "continue", + StdoutConfig: &v1beta1.StepOutputConfig{Path: "/path"}, + StderrConfig: &v1beta1.StepOutputConfig{Path: "/another-path"}, + }}, + StepTemplate: &v1beta1.StepTemplate{ + Image: "foo", + Command: []string{"hello"}, + Args: []string{"world"}, + WorkingDir: "/dir", + EnvFrom: []corev1.EnvFromSource{{Prefix: "prefix"}}, + Env: []corev1.EnvVar{{Name: "var"}}, + Resources: corev1.ResourceRequirements{}, + VolumeMounts: []corev1.VolumeMount{}, + VolumeDevices: []corev1.VolumeDevice{}, + ImagePullPolicy: corev1.PullIfNotPresent, + SecurityContext: &corev1.SecurityContext{}, + }, + Sidecars: []v1beta1.Sidecar{{ + Name: "step", + Image: "foo", + Command: []string{"hello"}, + Args: []string{"world"}, + WorkingDir: "/dir", + Ports: []corev1.ContainerPort{}, + EnvFrom: []corev1.EnvFromSource{{Prefix: "prefix"}}, + Env: []corev1.EnvVar{{Name: "var"}}, + Resources: corev1.ResourceRequirements{}, + VolumeMounts: []corev1.VolumeMount{}, + VolumeDevices: []corev1.VolumeDevice{}, + LivenessProbe: &corev1.Probe{}, + ReadinessProbe: &corev1.Probe{}, + StartupProbe: &corev1.Probe{}, + Lifecycle: &corev1.Lifecycle{}, + TerminationMessagePath: "/path", + TerminationMessagePolicy: corev1.TerminationMessageReadFile, + ImagePullPolicy: corev1.PullIfNotPresent, + SecurityContext: &corev1.SecurityContext{}, + Stdin: true, + StdinOnce: true, + TTY: true, + Script: "echo hello", + Workspaces: []v1beta1.WorkspaceUsage{{Name: "workspace"}}, + }}, + Volumes: []corev1.Volume{{Name: "volume"}}, + Params: []v1beta1.ParamSpec{{ + Name: "param-1", + Type: v1beta1.ParamTypeString, + Description: "My first param", + Properties: map[string]v1beta1.PropertySpec{"foo": {Type: v1beta1.ParamTypeString}}, + Default: v1beta1.NewArrayOrString("bar"), + }}, + Workspaces: []v1beta1.WorkspaceDeclaration{{ + Name: "workspace", + Description: "description", + MountPath: "/foo", + ReadOnly: true, + Optional: true, + }}, + + Results: []v1beta1.TaskResult{{ + Name: "result", + Type: v1beta1.ResultsTypeObject, + Properties: map[string]v1beta1.PropertySpec{"property": {Type: v1beta1.ParamTypeString}}, + Description: "description", + }}, + }, + }, + }} + + for _, test := range tests { + for _, version := range versions { + t.Run(test.name, func(t *testing.T) { + ver := version + if err := test.in.ConvertTo(context.Background(), ver); err != nil { + t.Errorf("ConvertTo() = %v", err) + return + } + t.Logf("ConvertTo() = %#v", ver) + got := &v1beta1.Task{} + if err := got.ConvertFrom(context.Background(), ver); err != nil { + t.Errorf("ConvertFrom() = %v", err) + } + t.Logf("ConvertFrom() = %#v", got) + if d := cmp.Diff(test.in, got); d != "" { + t.Errorf("roundtrip %s", diff.PrintWantGot(d)) + } + }) + } + } +} + +func TestTaskConversionFromDeprecated(t *testing.T) { + // TODO(#4546): We're just dropping Resources when converting from + // v1beta1 to v1. Before moving the stored version to v1, we should + // come up with a better strategy + versions := []apis.Convertible{&v1.Task{}} + tests := []struct { + name string + in *v1beta1.Task + want *v1beta1.Task + }{{ + name: "input resources", + in: &v1beta1.Task{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: "bar", + Generation: 1, + }, + Spec: v1beta1.TaskSpec{ + Resources: &v1beta1.TaskResources{ + Inputs: []v1beta1.TaskResource{}, + }, + }, + }, + want: &v1beta1.Task{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: "bar", + Generation: 1, + }, + Spec: v1beta1.TaskSpec{}, + }, + }, { + name: "output resources", + in: &v1beta1.Task{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: "bar", + Generation: 1, + }, + Spec: v1beta1.TaskSpec{ + Resources: &v1beta1.TaskResources{ + Outputs: []v1beta1.TaskResource{}, + }, + }, + }, + want: &v1beta1.Task{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: "bar", + Generation: 1, + }, + Spec: v1beta1.TaskSpec{}, + }, + }} + for _, test := range tests { + for _, version := range versions { + t.Run(test.name, func(t *testing.T) { + ver := version + if err := test.in.ConvertTo(context.Background(), ver); err != nil { + t.Errorf("ConvertTo() = %v", err) + } + t.Logf("ConvertTo() = %#v", ver) + got := &v1beta1.Task{} + if err := got.ConvertFrom(context.Background(), ver); err != nil { + t.Errorf("ConvertFrom() = %v", err) + } + t.Logf("ConvertFrom() = %#v", got) + if d := cmp.Diff(test.want, got); d != "" { + t.Errorf("roundtrip %s", diff.PrintWantGot(d)) + } + }) + } } } diff --git a/pkg/apis/pipeline/v1beta1/workspace_conversion.go b/pkg/apis/pipeline/v1beta1/workspace_conversion.go new file mode 100644 index 00000000000..c5920e53430 --- /dev/null +++ b/pkg/apis/pipeline/v1beta1/workspace_conversion.go @@ -0,0 +1,33 @@ +package v1beta1 + +import ( + "context" + + v1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" +) + +func (w WorkspaceDeclaration) convertTo(ctx context.Context, sink *v1.WorkspaceDeclaration) { + sink.Name = w.Name + sink.Description = w.Description + sink.MountPath = w.MountPath + sink.ReadOnly = w.ReadOnly + sink.Optional = w.Optional +} + +func (w *WorkspaceDeclaration) convertFrom(ctx context.Context, source v1.WorkspaceDeclaration) { + w.Name = source.Name + w.Description = source.Description + w.MountPath = source.MountPath + w.ReadOnly = source.ReadOnly + w.Optional = source.Optional +} + +func (w WorkspaceUsage) convertTo(ctx context.Context, sink *v1.WorkspaceUsage) { + sink.Name = w.Name + sink.MountPath = w.MountPath +} + +func (w *WorkspaceUsage) convertFrom(ctx context.Context, source v1.WorkspaceUsage) { + w.Name = source.Name + w.MountPath = source.MountPath +}