From e99371de2a9571939e4978852682e76893a5fd66 Mon Sep 17 00:00:00 2001 From: Daniel Helfand Date: Mon, 12 Oct 2020 14:06:06 -0500 Subject: [PATCH] avoid use of previous TaskRunSpecStatus and PipelineRunSpecStatus --- pkg/cmd/clustertask/start_test.go | 117 +++++++++++++++++++++++ pkg/cmd/pipeline/start.go | 2 + pkg/cmd/pipeline/start_test.go | 152 +++++++++++++++++++++++++++++- pkg/cmd/task/start_test.go | 127 +++++++++++++++++++++++++ pkg/options/start.go | 2 + 5 files changed, 399 insertions(+), 1 deletion(-) diff --git a/pkg/cmd/clustertask/start_test.go b/pkg/cmd/clustertask/start_test.go index a257e631f2..a4766ea44d 100644 --- a/pkg/cmd/clustertask/start_test.go +++ b/pkg/cmd/clustertask/start_test.go @@ -23,6 +23,7 @@ import ( "time" "github.com/jonboulle/clockwork" + traction "github.com/tektoncd/cli/pkg/taskrun" "github.com/tektoncd/cli/pkg/test" cb "github.com/tektoncd/cli/pkg/test/builder" testDynamic "github.com/tektoncd/cli/pkg/test/dynamic" @@ -1808,3 +1809,119 @@ func Test_parseRes_v1beta1(t *testing.T) { }) } } + +func Test_start_use_taskrun_cancelled_status_v1beta1(t *testing.T) { + ctasks := []*v1beta1.ClusterTask{ + { + ObjectMeta: v1.ObjectMeta{ + Name: "clustertask", + }, + Spec: v1beta1.TaskSpec{ + Resources: &v1beta1.TaskResources{ + Inputs: []v1beta1.TaskResource{ + { + ResourceDeclaration: v1beta1.ResourceDeclaration{ + Name: "my-repo", + Type: v1beta1.PipelineResourceTypeGit, + }, + }, + }, + Outputs: []v1beta1.TaskResource{ + { + ResourceDeclaration: v1beta1.ResourceDeclaration{ + Name: "code-image", + Type: v1beta1.PipelineResourceTypeImage, + }, + }, + }, + }, + Params: []v1beta1.ParamSpec{ + { + Name: "myarg", + Type: v1beta1.ParamTypeString, + }, + { + Name: "print", + Type: v1beta1.ParamTypeArray, + }, + }, + Steps: []v1beta1.Step{ + { + Container: corev1.Container{ + Name: "hello", + Image: "busybox", + }, + }, + { + Container: corev1.Container{ + Name: "exit", + Image: "busybox", + }, + }, + }, + }, + }, + } + + timeoutDuration, _ := time.ParseDuration("10s") + trName := "ct-run" + taskruns := []*v1beta1.TaskRun{ + { + + ObjectMeta: v1.ObjectMeta{ + Name: trName, + Labels: map[string]string{"tekton.dev/clustertask": "clustertask"}, + Namespace: "ns", + }, + Spec: v1beta1.TaskRunSpec{ + TaskRef: &v1beta1.TaskRef{ + Name: "clustertask", + Kind: v1beta1.ClusterTaskKind, + }, + ServiceAccountName: "serviceaccount", + Timeout: &metav1.Duration{Duration: timeoutDuration}, + Status: v1beta1.TaskRunSpecStatus(v1beta1.TaskRunSpecStatusCancelled), + }, + }, + } + + ns := []*corev1.Namespace{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "ns", + }, + }, + } + + seedData, _ := test.SeedV1beta1TestData(t, pipelinev1beta1test.Data{Namespaces: ns, ClusterTasks: ctasks, TaskRuns: taskruns}) + objs := []runtime.Object{ctasks[0], taskruns[0]} + trName2 := trName + "-2" + tdc := newDynamicClientOpt(versionB1, trName2, objs...) + + cs := pipelinetest.Clients{ + Pipeline: seedData.Pipeline, + Kube: seedData.Kube, + } + cs.Pipeline.Resources = cb.APIResourceList(versionB1, []string{"clustertask", "taskrun"}) + dc, _ := tdc.Client( + cb.UnstructuredV1beta1CT(ctasks[0], versionB1), + cb.UnstructuredV1beta1TR(taskruns[0], versionB1), + ) + p := &test.Params{Tekton: cs.Pipeline, Kube: cs.Kube, Dynamic: dc} + + clustertask := Command(p) + got, _ := test.ExecuteCommand(clustertask, "start", "clustertask", "--use-taskrun", trName, "-n", "ns") + + expected := "TaskRun started: ct-run-2\n\nIn order to track the TaskRun progress run:\ntkn taskrun logs ct-run-2 -f -n ns\n" + test.AssertOutput(t, expected, got) + clients, _ := p.Clients() + tr, err := traction.Get(clients, trName2, metav1.GetOptions{}, "ns") + if err != nil { + t.Errorf("Error listing taskruns %s", err.Error()) + } + + test.AssertOutput(t, "serviceaccount", tr.Spec.ServiceAccountName) + test.AssertOutput(t, timeoutDuration, tr.Spec.Timeout.Duration) + // Assert that new TaskRun does not contain cancelled status of previous run + test.AssertOutput(t, v1beta1.TaskRunSpecStatus(""), tr.Spec.Status) +} diff --git a/pkg/cmd/pipeline/start.go b/pkg/cmd/pipeline/start.go index d12ad5340b..06eeedd4f0 100644 --- a/pkg/cmd/pipeline/start.go +++ b/pkg/cmd/pipeline/start.go @@ -255,6 +255,8 @@ func (opt *startOptions) startPipeline(pipelineStart *v1beta1.Pipeline) error { } // Copy over spec from last or previous PipelineRun to use same values for this PipelineRun pr.Spec = usepr.Spec + // Reapply blank status in case PipelineRun used was cancelled + pr.Spec.Status = "" } if err := mergeRes(pr, opt.Resources); err != nil { diff --git a/pkg/cmd/pipeline/start_test.go b/pkg/cmd/pipeline/start_test.go index ebe5472183..dca122f458 100644 --- a/pkg/cmd/pipeline/start_test.go +++ b/pkg/cmd/pipeline/start_test.go @@ -4202,8 +4202,158 @@ func Test_start_pipeline_use_pipelinerun_v1beta1(t *testing.T) { t.Errorf("Error getting pipelineruns %s", err.Error()) } test.AssertOutput(t, pr.Spec.Params[0].Name, "brush") - test.AssertOutput(t, pr.Spec.Params[0].Value, v1alpha1.ArrayOrString{Type: "string", StringVal: "teeth"}) + test.AssertOutput(t, pr.Spec.Params[0].Value, v1beta1.ArrayOrString{Type: "string", StringVal: "teeth"}) + test.AssertOutput(t, timeoutDuration, pr.Spec.Timeout.Duration) +} + +func Test_start_pipeline_use_pipelinerun_cancelled_status_v1beta1(t *testing.T) { + pipelineName := "test-pipeline" + theonename := "test-pipeline-run-be-the-one" + timeoutDuration, _ := time.ParseDuration("10s") + + ps := []*v1beta1.Pipeline{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: pipelineName, + Namespace: "ns", + }, + Spec: v1beta1.PipelineSpec{ + Tasks: []v1beta1.PipelineTask{ + { + Name: "unit-test-1", + TaskRef: &v1beta1.TaskRef{ + Name: "unit-test-task", + }, + Resources: &v1beta1.PipelineTaskResources{ + Inputs: []v1beta1.PipelineTaskInputResource{ + { + Name: "workspace", + Resource: "git-repo", + }, + }, + Outputs: []v1beta1.PipelineTaskOutputResource{ + { + Name: "image-to-use", + Resource: "best-image", + }, + { + Name: "workspace", + Resource: "git-repo", + }, + }, + }, + }, + }, + Resources: []v1beta1.PipelineDeclaredResource{ + { + Name: "git-repo", + Type: v1alpha1.PipelineResourceTypeGit, + }, + { + Name: "build-image", + Type: v1alpha1.PipelineResourceTypeImage, + }, + }, + Params: []v1beta1.ParamSpec{ + { + Name: "pipeline-param-1", + Type: v1beta1.ParamTypeString, + Default: &v1beta1.ArrayOrString{ + Type: v1beta1.ParamTypeString, + StringVal: "somethingdifferent-1", + }, + }, + { + Name: "rev-param", + Type: v1beta1.ParamTypeString, + Default: &v1beta1.ArrayOrString{ + Type: v1beta1.ParamTypeString, + StringVal: "revision", + }, + }, + }, + }, + }, + } + + prs := []*v1beta1.PipelineRun{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: theonename, + Namespace: "ns", + Labels: map[string]string{"tekton.dev/pipeline": pipelineName}, + }, + Spec: v1beta1.PipelineRunSpec{ + PipelineRef: &v1beta1.PipelineRef{ + Name: pipelineName, + }, + Params: []v1beta1.Param{ + { + Name: "brush", + Value: v1beta1.ArrayOrString{ + Type: v1beta1.ParamTypeString, + StringVal: "teeth", + }, + }, + }, + Timeout: &metav1.Duration{Duration: timeoutDuration}, + Status: v1beta1.PipelineRunSpecStatus(v1beta1.PipelineRunSpecStatusCancelled), + }, + Status: v1beta1.PipelineRunStatus{ + Status: duckv1beta1.Status{ + Conditions: duckv1beta1.Conditions{ + { + Status: corev1.ConditionFalse, + Reason: v1beta1.PipelineRunReasonCancelled.String(), + }, + }, + }, + }, + }, + } + + ns := []*corev1.Namespace{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "ns", + }, + }, + } + + seedData, _ := test.SeedV1beta1TestData(t, pipelinev1beta1test.Data{ + Namespaces: ns, + }) + cs := pipelinetest.Clients{ + Pipeline: seedData.Pipeline, + Kube: seedData.Kube, + Resource: seedData.Resource, + } + cs.Pipeline.Resources = cb.APIResourceList("v1beta1", []string{"pipeline", "pipelinerun"}) + objs := []runtime.Object{ps[0], prs[0]} + _, tdc := newPipelineClient("v1beta1", objs...) + dc, err := tdc.Client( + cb.UnstructuredV1beta1P(ps[0], "v1beta1"), + cb.UnstructuredV1beta1PR(prs[0], "v1beta1"), + ) + if err != nil { + t.Errorf("unable to create dynamic client: %v", err) + } + p := &test.Params{Tekton: cs.Pipeline, Kube: cs.Kube, Dynamic: dc, Resource: cs.Resource} + + pipeline := Command(p) + _, _ = test.ExecuteCommand(pipeline, "start", pipelineName, + "--use-pipelinerun="+theonename, "-n", "ns") + + cl, _ := p.Clients() + pr, err := pipelinerun.Get(cl, "random", v1.GetOptions{}, "ns") + if err != nil { + t.Errorf("Error getting pipelineruns %s", err.Error()) + } + test.AssertOutput(t, pr.Spec.Params[0].Name, "brush") + test.AssertOutput(t, pr.Spec.Params[0].Value, v1beta1.ArrayOrString{Type: "string", StringVal: "teeth"}) test.AssertOutput(t, timeoutDuration, pr.Spec.Timeout.Duration) + // Assert that new PipelineRun does not contain cancelled status of previous run + test.AssertOutput(t, v1beta1.PipelineRunSpecStatus(""), pr.Spec.Status) } func Test_start_pipeline_allkindparam(t *testing.T) { diff --git a/pkg/cmd/task/start_test.go b/pkg/cmd/task/start_test.go index 48d2f9da6b..1007884cf9 100644 --- a/pkg/cmd/task/start_test.go +++ b/pkg/cmd/task/start_test.go @@ -1258,6 +1258,133 @@ func Test_start_use_taskrun_v1beta1(t *testing.T) { test.AssertOutput(t, timeoutDuration, tr.Spec.Timeout.Duration) } +func Test_start_use_taskrun_cancelled_status_v1beta1(t *testing.T) { + tasks := []*v1beta1.Task{ + { + ObjectMeta: v1.ObjectMeta{ + Name: "task", + Namespace: "ns", + }, + Spec: v1beta1.TaskSpec{ + Resources: &v1beta1.TaskResources{ + Inputs: []v1beta1.TaskResource{ + { + ResourceDeclaration: v1beta1.ResourceDeclaration{ + Name: "my-repo", + Type: v1beta1.PipelineResourceTypeGit, + }, + }, + }, + Outputs: []v1beta1.TaskResource{ + { + ResourceDeclaration: v1beta1.ResourceDeclaration{ + Name: "code-image", + Type: v1beta1.PipelineResourceTypeImage, + }, + }, + }, + }, + Params: []v1beta1.ParamSpec{ + { + Name: "myarg", + Type: v1beta1.ParamTypeString, + }, + { + Name: "print", + Type: v1beta1.ParamTypeArray, + }, + }, + Steps: []v1beta1.Step{ + { + Container: corev1.Container{ + Name: "hello", + Image: "busybox", + }, + }, + { + Container: corev1.Container{ + Name: "exit", + Image: "busybox", + }, + }, + }, + Workspaces: []v1beta1.WorkspaceDeclaration{ + { + Name: "test", + Description: "test workspace", + MountPath: "/workspace/test/file", + ReadOnly: true, + }, + }, + }, + }, + } + + timeoutDuration, _ := time.ParseDuration("10s") + + taskruns := []*v1beta1.TaskRun{ + { + + ObjectMeta: v1.ObjectMeta{ + Name: "camper", + Namespace: "ns", + Labels: map[string]string{"tekton.dev/task": "task"}, + }, + Spec: v1beta1.TaskRunSpec{ + TaskRef: &v1beta1.TaskRef{ + Name: "task", + Kind: v1beta1.NamespacedTaskKind, + }, + ServiceAccountName: "camper", + Timeout: &metav1.Duration{Duration: timeoutDuration}, + Status: v1beta1.TaskRunSpecStatus(v1beta1.TaskRunSpecStatusCancelled), + }, + }, + } + + ns := []*corev1.Namespace{ + { + ObjectMeta: metav1.ObjectMeta{ + Name: "ns", + }, + }, + } + + seedData, _ := test.SeedV1beta1TestData(t, pipelinev1beta1test.Data{Namespaces: ns, Tasks: tasks, TaskRuns: taskruns}) + + objs := []runtime.Object{tasks[0], taskruns[0]} + _, tdc := newPipelineClient(versionB1, objs...) + + cs := pipelinetest.Clients{ + Pipeline: seedData.Pipeline, + Kube: seedData.Kube, + } + cs.Pipeline.Resources = cb.APIResourceList(versionB1, []string{"task", "taskrun"}) + dc, _ := tdc.Client( + cb.UnstructuredV1beta1T(tasks[0], versionB1), + cb.UnstructuredV1beta1TR(taskruns[0], versionB1), + ) + p := &test.Params{Tekton: cs.Pipeline, Kube: cs.Kube, Dynamic: dc} + + task := Command(p) + got, _ := test.ExecuteCommand(task, "start", "task", + "--use-taskrun", "camper", + "-n=ns") + + expected := "TaskRun started: random\n\nIn order to track the TaskRun progress run:\ntkn taskrun logs random -f -n ns\n" + test.AssertOutput(t, expected, got) + clients, _ := p.Clients() + tr, err := traction.Get(clients, "random", metav1.GetOptions{}, "ns") + if err != nil { + t.Errorf("Error listing taskruns %s", err.Error()) + } + + test.AssertOutput(t, "camper", tr.Spec.ServiceAccountName) + test.AssertOutput(t, timeoutDuration, tr.Spec.Timeout.Duration) + // Assert that new TaskRun does not contain cancelled status of previous run + test.AssertOutput(t, v1beta1.TaskRunSpecStatus(""), tr.Spec.Status) +} + func Test_start_task_last_generate_name(t *testing.T) { tasks := []*v1alpha1.Task{ tb.Task("task", diff --git a/pkg/options/start.go b/pkg/options/start.go index 7df3ab20d7..44e563e347 100644 --- a/pkg/options/start.go +++ b/pkg/options/start.go @@ -92,6 +92,8 @@ func (taskRunOpts *TaskRunOpts) UseTaskRunFrom(tr *v1beta1.TaskRun, cs *cli.Clie } // Copy over spec from last or previous TaskRun to use same values for this TaskRun tr.Spec = trUsed.Spec + // Reapply blank status in case TaskRun used was cancelled + tr.Spec.Status = "" return nil }