From 01901bdc13c06b41f82bee9805e3f2f1a1465932 Mon Sep 17 00:00:00 2001 From: Vincent Demeester Date: Thu, 6 Feb 2020 10:01:08 +0100 Subject: [PATCH] =?UTF-8?q?ClusterTask=20auto-conversion=20from=20v1alpha1?= =?UTF-8?q?=20to=20v1alpha2=20=F0=9F=8E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds auto-conversion methods and tests for ClusterTask types in v1alpha1 and v1alpha2. Signed-off-by: Vincent Demeester --- .../v1alpha1/cluster_task_conversion.go | 49 +++ .../v1alpha1/cluster_task_conversion_test.go | 321 ++++++++++++++++++ .../v1alpha2/cluster_task_conversion.go | 36 ++ .../v1alpha2/cluster_task_conversion_test.go | 34 ++ 4 files changed, 440 insertions(+) create mode 100644 pkg/apis/pipeline/v1alpha1/cluster_task_conversion.go create mode 100644 pkg/apis/pipeline/v1alpha1/cluster_task_conversion_test.go create mode 100644 pkg/apis/pipeline/v1alpha2/cluster_task_conversion.go create mode 100644 pkg/apis/pipeline/v1alpha2/cluster_task_conversion_test.go diff --git a/pkg/apis/pipeline/v1alpha1/cluster_task_conversion.go b/pkg/apis/pipeline/v1alpha1/cluster_task_conversion.go new file mode 100644 index 00000000000..8b43d2fa8e1 --- /dev/null +++ b/pkg/apis/pipeline/v1alpha1/cluster_task_conversion.go @@ -0,0 +1,49 @@ +/* +Copyright 2020 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 v1alpha1 + +import ( + "context" + "fmt" + + "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha2" + "knative.dev/pkg/apis" +) + +var _ apis.Convertible = (*ClusterTask)(nil) + +// ConvertUp implements api.Convertible +func (source *ClusterTask) ConvertUp(ctx context.Context, obj apis.Convertible) error { + switch sink := obj.(type) { + case *v1alpha2.ClusterTask: + sink.ObjectMeta = source.ObjectMeta + return source.Spec.ConvertUp(ctx, &sink.Spec) + default: + return fmt.Errorf("unknown version, got: %T", sink) + } +} + +// ConvertDown implements api.Convertible +func (sink *ClusterTask) ConvertDown(ctx context.Context, obj apis.Convertible) error { + switch source := obj.(type) { + case *v1alpha2.ClusterTask: + sink.ObjectMeta = source.ObjectMeta + return sink.Spec.ConvertDown(ctx, &source.Spec) + default: + return fmt.Errorf("unknown version, got: %T", sink) + } +} diff --git a/pkg/apis/pipeline/v1alpha1/cluster_task_conversion_test.go b/pkg/apis/pipeline/v1alpha1/cluster_task_conversion_test.go new file mode 100644 index 00000000000..287897a6f2a --- /dev/null +++ b/pkg/apis/pipeline/v1alpha1/cluster_task_conversion_test.go @@ -0,0 +1,321 @@ +/* +Copyright 2020 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 v1alpha1 + +import ( + "context" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha2" + resource "github.com/tektoncd/pipeline/pkg/apis/resource/v1alpha1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "knative.dev/pkg/apis" +) + +func TestClusterTaskConversionBadType(t *testing.T) { + good, bad := &ClusterTask{}, &Pipeline{} + + if err := good.ConvertUp(context.Background(), bad); err == nil { + t.Errorf("ConvertUp() = %#v, wanted error", bad) + } + + if err := good.ConvertDown(context.Background(), bad); err == nil { + t.Errorf("ConvertUp() = %#v, wanted error", bad) + } +} + +func TestClusterTaskConversion(t *testing.T) { + versions := []apis.Convertible{&v1alpha2.ClusterTask{}} + + tests := []struct { + name string + in *ClusterTask + wantErr bool + }{{ + name: "simple conversion", + in: &ClusterTask{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: "bar", + Generation: 1, + }, + Spec: TaskSpec{ + TaskSpec: v1alpha2.TaskSpec{ + Steps: []v1alpha2.Step{{Container: corev1.Container{ + Image: "foo", + }}}, + Volumes: []corev1.Volume{{}}, + Params: []v1alpha2.ParamSpec{{ + Name: "param-1", + Type: v1alpha2.ParamTypeString, + Description: "My first param", + }}, + Resources: &v1alpha2.TaskResources{ + Inputs: []v1alpha2.TaskResource{{ResourceDeclaration: v1alpha2.ResourceDeclaration{ + Name: "input-1", + Type: resource.PipelineResourceTypeGit, + }}}, + Outputs: []v1alpha2.TaskResource{{ResourceDeclaration: v1alpha2.ResourceDeclaration{ + Name: "output-1", + Type: resource.PipelineResourceTypeGit, + }}}, + }, + }, + }, + }, + }, { + name: "deprecated and non deprecated inputs", + in: &ClusterTask{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: "bar", + Generation: 1, + }, + Spec: TaskSpec{ + TaskSpec: v1alpha2.TaskSpec{ + Resources: &v1alpha2.TaskResources{ + Inputs: []v1alpha2.TaskResource{{ResourceDeclaration: v1alpha2.ResourceDeclaration{ + Name: "input-1", + Type: resource.PipelineResourceTypeGit, + }}}, + }, + }, + Inputs: &Inputs{ + Resources: []TaskResource{{ResourceDeclaration: ResourceDeclaration{ + Name: "input-1", + Type: resource.PipelineResourceTypeGit, + }}}, + }, + }, + }, + wantErr: true, + }, { + name: "deprecated and non deprecated inputs", + in: &ClusterTask{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: "bar", + Generation: 1, + }, + Spec: TaskSpec{ + TaskSpec: v1alpha2.TaskSpec{ + Params: []v1alpha2.ParamSpec{{ + Name: "param-1", + Type: v1alpha2.ParamTypeString, + Description: "My first param", + }}, + }, + Inputs: &Inputs{ + Params: []ParamSpec{{ + Name: "param-1", + Type: v1alpha2.ParamTypeString, + Description: "My first param", + }}, + }, + }, + }, + wantErr: true, + }, { + name: "deprecated and non deprecated outputs", + in: &ClusterTask{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: "bar", + Generation: 1, + }, + Spec: TaskSpec{ + TaskSpec: v1alpha2.TaskSpec{ + Resources: &v1alpha2.TaskResources{ + Outputs: []v1alpha2.TaskResource{{ResourceDeclaration: v1alpha2.ResourceDeclaration{ + Name: "output-1", + Type: resource.PipelineResourceTypeGit, + }}}, + }, + }, + Outputs: &Outputs{ + Resources: []TaskResource{{ResourceDeclaration: ResourceDeclaration{ + Name: "output-1", + Type: resource.PipelineResourceTypeGit, + }}}, + }, + }, + }, + wantErr: true, + }} + + for _, test := range tests { + for _, version := range versions { + t.Run(test.name, func(t *testing.T) { + ver := version + if err := test.in.ConvertUp(context.Background(), ver); err != nil { + if !test.wantErr { + t.Errorf("ConvertUp() = %v", err) + } + return + } + t.Logf("ConvertUp() = %#v", ver) + got := &ClusterTask{} + if err := got.ConvertDown(context.Background(), ver); err != nil { + t.Errorf("ConvertDown() = %v", err) + } + t.Logf("ConvertDown() = %#v", got) + if diff := cmp.Diff(test.in, got); diff != "" { + t.Errorf("roundtrip (-want, +got) = %v", diff) + } + }) + } + } +} + +func TestClusterTaskConversionFromDeprecated(t *testing.T) { + versions := []apis.Convertible{&v1alpha2.ClusterTask{}} + tests := []struct { + name string + in *ClusterTask + want *ClusterTask + badField string + }{{ + name: "inputs params", + in: &ClusterTask{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: "bar", + Generation: 1, + }, + Spec: TaskSpec{ + Inputs: &Inputs{ + Params: []ParamSpec{{ + Name: "param-1", + Type: v1alpha2.ParamTypeString, + Description: "My first param", + }}, + }, + }, + }, + want: &ClusterTask{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: "bar", + Generation: 1, + }, + Spec: TaskSpec{ + TaskSpec: v1alpha2.TaskSpec{ + Params: []v1alpha2.ParamSpec{{ + Name: "param-1", + Type: v1alpha2.ParamTypeString, + Description: "My first param", + }}, + }, + }, + }, + }, { + name: "inputs resource", + in: &ClusterTask{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: "bar", + Generation: 1, + }, + Spec: TaskSpec{ + Inputs: &Inputs{ + Resources: []TaskResource{{ResourceDeclaration: ResourceDeclaration{ + Name: "input-1", + Type: resource.PipelineResourceTypeGit, + }}}, + }, + }, + }, + want: &ClusterTask{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: "bar", + Generation: 1, + }, + Spec: TaskSpec{ + TaskSpec: v1alpha2.TaskSpec{ + Resources: &v1alpha2.TaskResources{ + Inputs: []v1alpha2.TaskResource{{ResourceDeclaration: v1alpha2.ResourceDeclaration{ + Name: "input-1", + Type: resource.PipelineResourceTypeGit, + }}}, + }, + }, + }, + }, + }, { + name: "outputs resource", + in: &ClusterTask{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: "bar", + Generation: 1, + }, + Spec: TaskSpec{ + Outputs: &Outputs{ + Resources: []TaskResource{{ResourceDeclaration: ResourceDeclaration{ + Name: "output-1", + Type: resource.PipelineResourceTypeGit, + }}}, + }, + }, + }, + want: &ClusterTask{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo", + Namespace: "bar", + Generation: 1, + }, + Spec: TaskSpec{ + TaskSpec: v1alpha2.TaskSpec{ + Resources: &v1alpha2.TaskResources{ + Outputs: []v1alpha2.TaskResource{{ResourceDeclaration: v1alpha2.ResourceDeclaration{ + Name: "output-1", + Type: resource.PipelineResourceTypeGit, + }}}, + }, + }, + }, + }, + }} + for _, test := range tests { + for _, version := range versions { + t.Run(test.name, func(t *testing.T) { + ver := version + if err := test.in.ConvertUp(context.Background(), ver); err != nil { + if test.badField != "" { + cce, ok := err.(*CannotConvertError) + if ok && cce.Field == test.badField { + return + } + } + t.Errorf("ConvertUp() = %v", err) + } + t.Logf("ConvertUp() = %#v", ver) + got := &ClusterTask{} + if err := got.ConvertDown(context.Background(), ver); err != nil { + t.Errorf("ConvertDown() = %v", err) + } + t.Logf("ConvertDown() = %#v", got) + if diff := cmp.Diff(test.want, got); diff != "" { + t.Errorf("roundtrip (-want, +got) = %v", diff) + } + }) + } + } +} diff --git a/pkg/apis/pipeline/v1alpha2/cluster_task_conversion.go b/pkg/apis/pipeline/v1alpha2/cluster_task_conversion.go new file mode 100644 index 00000000000..5751f7ee43d --- /dev/null +++ b/pkg/apis/pipeline/v1alpha2/cluster_task_conversion.go @@ -0,0 +1,36 @@ +/* +Copyright 2020 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 v1alpha2 + +import ( + "context" + "fmt" + + "knative.dev/pkg/apis" +) + +var _ apis.Convertible = (*ClusterTask)(nil) + +// ConvertUp implements api.Convertible +func (source *ClusterTask) ConvertUp(ctx context.Context, sink apis.Convertible) error { + return fmt.Errorf("v1alpha2 is the highest known version, got: %T", sink) +} + +// ConvertDown implements api.Convertible +func (sink *ClusterTask) ConvertDown(ctx context.Context, source apis.Convertible) error { + return fmt.Errorf("v1alpha2 is the highest know version, got: %T", source) +} diff --git a/pkg/apis/pipeline/v1alpha2/cluster_task_conversion_test.go b/pkg/apis/pipeline/v1alpha2/cluster_task_conversion_test.go new file mode 100644 index 00000000000..2c7c0acfc88 --- /dev/null +++ b/pkg/apis/pipeline/v1alpha2/cluster_task_conversion_test.go @@ -0,0 +1,34 @@ +/* +Copyright 2020 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 v1alpha2 + +import ( + "context" + "testing" +) + +func TestClusterTaskConversionBadType(t *testing.T) { + good, bad := &ClusterTask{}, &Pipeline{} + + if err := good.ConvertUp(context.Background(), bad); err == nil { + t.Errorf("ConvertUp() = %#v, wanted error", bad) + } + + if err := good.ConvertDown(context.Background(), bad); err == nil { + t.Errorf("ConvertDown() = %#v, wanted error", good) + } +}