From ba09bb1ed1651164d0d1bad9ca95074b4cc6dd2a Mon Sep 17 00:00:00 2001 From: Andrew Bayer Date: Thu, 23 Jun 2022 14:49:59 -0400 Subject: [PATCH] Add support for Pipeline minimal embedded status Fixes #1618 Signed-off-by: Andrew Bayer --- pkg/cmd/pipelinerun/logs_test.go | 64 ++- pkg/pipelinerun/pipelinerun.go | 96 ++++- pkg/pipelinerun/pipelinerun_test.go | 376 ++++++++++++++++++ pkg/pipelinerun/tracker.go | 7 + pkg/pipelinerun/tracker_test.go | 131 ++++-- test/e2e-tests.sh | 15 + .../github.com/gdamore/tcell/{ => v2}/LICENSE | 0 .../github.com/hashicorp/go-plugin/README.md | 5 +- .../github.com/hashicorp/go-plugin/client.go | 15 +- .../hashicorp/go-plugin/process_posix.go | 1 + .../hashicorp/go-plugin/rpc_server.go | 6 +- .../github.com/hashicorp/go-plugin/server.go | 6 +- .../go-secure-stdlib/parseutil/parseutil.go | 99 +++++ .../hashicorp/go-version/CHANGELOG.md | 2 +- .../github.com/hashicorp/go-version/README.md | 2 +- .../hashicorp/go-version/version.go | 17 + .../vault/sdk/helper/certutil/helpers.go | 212 ++++++---- .../vault/sdk/helper/certutil/types.go | 213 +++++++++- .../vault/sdk/helper/consts/consts.go | 2 + .../sdk/helper/pluginutil/multiplexing.pb.go | 2 +- .../hashicorp/vault/sdk/logical/auth.go | 21 +- .../vault/sdk/logical/identity.pb.go | 2 +- .../vault/sdk/logical/managed_key.go | 8 +- .../hashicorp/vault/sdk/logical/plugin.pb.go | 41 +- .../hashicorp/vault/sdk/logical/plugin.proto | 6 + .../vault/sdk/logical/response_util.go | 2 + .../hashicorp/vault/sdk/version/version.go | 6 + .../vault/sdk/version/version_base.go | 7 +- .../github.com/ktr0731/go-fuzzyfinder/LICENSE | 2 +- .../github.com/nsf/termbox-go/LICENSE | 19 + .../tektoncd/pipeline/test/diff/print.go | 27 ++ .../tektoncd/pipeline/test/parse/yaml.go | 151 +++++++ vendor/modules.txt | 2 + 33 files changed, 1392 insertions(+), 173 deletions(-) rename third_party/VENDOR-LICENSE/github.com/gdamore/tcell/{ => v2}/LICENSE (100%) create mode 100644 third_party/VENDOR-LICENSE/github.com/nsf/termbox-go/LICENSE create mode 100644 vendor/github.com/tektoncd/pipeline/test/diff/print.go create mode 100644 vendor/github.com/tektoncd/pipeline/test/parse/yaml.go diff --git a/pkg/cmd/pipelinerun/logs_test.go b/pkg/cmd/pipelinerun/logs_test.go index 9c63ded9f1..b37d3653e7 100644 --- a/pkg/cmd/pipelinerun/logs_test.go +++ b/pkg/cmd/pipelinerun/logs_test.go @@ -34,6 +34,7 @@ import ( pipelinetest "github.com/tektoncd/pipeline/test/v1alpha1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/watch" "k8s.io/client-go/dynamic" "knative.dev/pkg/apis" @@ -258,13 +259,13 @@ func TestPipelinerunLogs(t *testing.T) { }, } - trs := []*v1alpha1.TaskRun{ + trs := []*v1beta1.TaskRun{ { ObjectMeta: metav1.ObjectMeta{ Namespace: ns, Name: tr1Name, }, - Spec: v1alpha1.TaskRunSpec{ + Spec: v1beta1.TaskRunSpec{ TaskRef: &v1beta1.TaskRef{ Name: task1Name, }, @@ -307,7 +308,7 @@ func TestPipelinerunLogs(t *testing.T) { Namespace: ns, Name: tr2Name, }, - Spec: v1alpha1.TaskRunSpec{ + Spec: v1beta1.TaskRunSpec{ TaskRef: &v1beta1.TaskRef{ Name: task2Name, }, @@ -347,24 +348,43 @@ func TestPipelinerunLogs(t *testing.T) { }, } - prs := []*v1alpha1.PipelineRun{ + prs := []*v1beta1.PipelineRun{ { ObjectMeta: metav1.ObjectMeta{ Name: prName, Namespace: ns, Labels: map[string]string{"tekton.dev/pipeline": prName}, }, - Spec: v1alpha1.PipelineRunSpec{ - PipelineRef: &v1alpha1.PipelineRef{ + Spec: v1beta1.PipelineRunSpec{ + PipelineRef: &v1beta1.PipelineRef{ Name: pipelineName, }, }, - Status: v1alpha1.PipelineRunStatus{ - PipelineRunStatusFields: v1alpha1.PipelineRunStatusFields{ - TaskRuns: map[string]*v1alpha1.PipelineRunTaskRunStatus{ - tr1Name: {PipelineTaskName: task1Name, Status: &trs[0].Status}, - tr2Name: {PipelineTaskName: task2Name, Status: &trs[1].Status}, + Status: v1beta1.PipelineRunStatus{ + PipelineRunStatusFields: v1beta1.PipelineRunStatusFields{ + ChildReferences: []v1beta1.ChildStatusReference{ + { + Name: tr1Name, + PipelineTaskName: task1Name, + TypeMeta: runtime.TypeMeta{ + APIVersion: "tekton.dev/v1beta1", + Kind: "TaskRun", + }, + }, { + Name: tr2Name, + PipelineTaskName: task2Name, + TypeMeta: runtime.TypeMeta{ + APIVersion: "tekton.dev/v1beta1", + Kind: "TaskRun", + }, + }, }, + /* + TaskRuns: map[string]*v1beta1.PipelineRunTaskRunStatus{ + tr1Name: {PipelineTaskName: task1Name, Status: &trs[0].Status}, + tr2Name: {PipelineTaskName: task2Name, Status: &trs[1].Status}, + }, + */ }, Status: duckv1beta1.Status{ Conditions: duckv1beta1.Conditions{ @@ -377,23 +397,23 @@ func TestPipelinerunLogs(t *testing.T) { }, }, } - pps := []*v1alpha1.Pipeline{ + pps := []*v1beta1.Pipeline{ { ObjectMeta: metav1.ObjectMeta{ Name: pipelineName, Namespace: ns, }, - Spec: v1alpha1.PipelineSpec{ - Tasks: []v1alpha1.PipelineTask{ + Spec: v1beta1.PipelineSpec{ + Tasks: []v1beta1.PipelineTask{ { Name: task1Name, - TaskRef: &v1alpha1.TaskRef{ + TaskRef: &v1beta1.TaskRef{ Name: task1Name, }, }, { Name: task2Name, - TaskRef: &v1alpha1.TaskRef{ + TaskRef: &v1beta1.TaskRef{ Name: task2Name, }, }, @@ -532,19 +552,19 @@ func TestPipelinerunLogs(t *testing.T) { for _, s := range scenarios { t.Run(s.name, func(t *testing.T) { - cs, _ := test.SeedTestData(t, pipelinetest.Data{PipelineRuns: prs, Pipelines: pps, TaskRuns: trs, Pods: p, Namespaces: nsList}) + cs, _ := test.SeedV1beta1TestData(t, pipelinev1beta1test.Data{PipelineRuns: prs, Pipelines: pps, TaskRuns: trs, Pods: p, Namespaces: nsList}) cs.Pipeline.Resources = cb.APIResourceList(versionA1, []string{"task", "taskrun", "pipeline", "pipelinerun"}) tdc := testDynamic.Options{} dc, err := tdc.Client( - cb.UnstructuredP(pps[0], versionA1), - cb.UnstructuredPR(prs[0], versionA1), - cb.UnstructuredTR(trs[0], versionA1), - cb.UnstructuredTR(trs[1], versionA1), + cb.UnstructuredV1beta1P(pps[0], versionA1), + cb.UnstructuredV1beta1PR(prs[0], versionA1), + cb.UnstructuredV1beta1TR(trs[0], versionA1), + cb.UnstructuredV1beta1TR(trs[1], versionA1), ) if err != nil { t.Errorf("unable to create dynamic client: %v", err) } - prlo := logOptsv1aplha1(prName, ns, cs, dc, fake.Streamer(fakeLogs), s.allSteps, false, s.prefixing, s.tasks...) + prlo := logOptsv1beta1(prName, ns, cs, dc, fake.Streamer(fakeLogs), s.allSteps, false, s.prefixing, s.tasks...) output, _ := fetchLogs(prlo) expected := strings.Join(s.expectedLogs, "\n") + "\n" diff --git a/pkg/pipelinerun/pipelinerun.go b/pkg/pipelinerun/pipelinerun.go index bae2788e44..742fa31faa 100644 --- a/pkg/pipelinerun/pipelinerun.go +++ b/pkg/pipelinerun/pipelinerun.go @@ -26,6 +26,8 @@ import ( prsort "github.com/tektoncd/cli/pkg/pipelinerun/sort" "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1" "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" + "github.com/tektoncd/pipeline/pkg/client/clientset/versioned" + "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" @@ -71,8 +73,8 @@ func List(c *cli.Clients, opts metav1.ListOptions, ns string) (*v1beta1.Pipeline return nil, err } - var runs *v1beta1.PipelineRunList - if err := runtime.DefaultUnstructuredConverter.FromUnstructured(unstructuredPR.UnstructuredContent(), &runs); err != nil { + var prList *v1beta1.PipelineRunList + if err := runtime.DefaultUnstructuredConverter.FromUnstructured(unstructuredPR.UnstructuredContent(), &prList); err != nil { return nil, err } if err != nil { @@ -80,7 +82,19 @@ func List(c *cli.Clients, opts metav1.ListOptions, ns string) (*v1beta1.Pipeline return nil, err } - return runs, nil + var populatedPRs []v1beta1.PipelineRun + + for _, pr := range prList.Items { + updatedPR, err := populatePipelineRunTaskStatuses(c, ns, pr) + if err != nil { + return nil, err + } + populatedPRs = append(populatedPRs, *updatedPR) + } + + prList.Items = populatedPRs + + return prList, nil } // It will fetch the resource based on the api available and return v1beta1 form @@ -117,7 +131,13 @@ func GetV1beta1(c *cli.Clients, prname string, opts metav1.GetOptions, ns string fmt.Fprintf(os.Stderr, "Failed to get pipelinerun from %s namespace \n", ns) return nil, err } - return pipelinerun, nil + + populatedPR, err := populatePipelineRunTaskStatuses(c, ns, *pipelinerun) + if err != nil { + return nil, err + } + + return populatedPR, nil } // It will fetch the resource in v1alpha1 struct format @@ -209,3 +229,71 @@ func createUnstructured(obj runtime.Object, c *cli.Clients, opts metav1.CreateOp return pipelinerun, nil } + +func populatePipelineRunTaskStatuses(c *cli.Clients, ns string, pr v1beta1.PipelineRun) (*v1beta1.PipelineRun, error) { + taskRunMap, runMap, err := getFullPipelineTaskStatuses(context.Background(), c.Tekton, ns, &pr) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to get TaskRun and Run statuses for PipelineRun %s from namespace %s\n", pr.Name, ns) + return nil, err + } + pr.Status.TaskRuns = taskRunMap + pr.Status.Runs = runMap + + return &pr, nil +} + +// getFullPipelineTaskStatuses returns populated TaskRun and Run status maps for a PipelineRun from its ChildReferences. +// If the PipelineRun has no ChildReferences, its .Status.TaskRuns and .Status.Runs will be returned instead. +// TODO(abayer): Remove in favor of github.com/tektoncd/pipeline/pkg/status.GetFullPipelineTaskStatuses when CLI can move to Pipeline v0.36.0 or later. +func getFullPipelineTaskStatuses(ctx context.Context, client versioned.Interface, ns string, pr *v1beta1.PipelineRun) (map[string]*v1beta1.PipelineRunTaskRunStatus, + map[string]*v1beta1.PipelineRunRunStatus, error) { + // If the PipelineRun is nil, just return + if pr == nil { + return nil, nil, nil + } + + // If there are no child references or either TaskRuns or Runs is non-zero, return the existing TaskRuns and Runs maps + if len(pr.Status.ChildReferences) == 0 || len(pr.Status.TaskRuns) > 0 || len(pr.Status.Runs) > 0 { + return pr.Status.TaskRuns, pr.Status.Runs, nil + } + + trStatuses := make(map[string]*v1beta1.PipelineRunTaskRunStatus) + runStatuses := make(map[string]*v1beta1.PipelineRunRunStatus) + + for _, cr := range pr.Status.ChildReferences { + switch cr.Kind { + case "TaskRun": + tr, err := client.TektonV1beta1().TaskRuns(ns).Get(ctx, cr.Name, metav1.GetOptions{}) + if err != nil && !errors.IsNotFound(err) { + return nil, nil, err + } + + trStatuses[cr.Name] = &v1beta1.PipelineRunTaskRunStatus{ + PipelineTaskName: cr.PipelineTaskName, + WhenExpressions: cr.WhenExpressions, + } + + if tr != nil { + trStatuses[cr.Name].Status = &tr.Status + } + case "Run": + r, err := client.TektonV1alpha1().Runs(ns).Get(ctx, cr.Name, metav1.GetOptions{}) + if err != nil && !errors.IsNotFound(err) { + return nil, nil, err + } + + runStatuses[cr.Name] = &v1beta1.PipelineRunRunStatus{ + PipelineTaskName: cr.PipelineTaskName, + WhenExpressions: cr.WhenExpressions, + } + + if r != nil { + runStatuses[cr.Name].Status = &r.Status + } + default: + // Don't do anything for unknown types. + } + } + + return trStatuses, runStatuses, nil +} diff --git a/pkg/pipelinerun/pipelinerun_test.go b/pkg/pipelinerun/pipelinerun_test.go index 1e13057992..3a6a04751d 100644 --- a/pkg/pipelinerun/pipelinerun_test.go +++ b/pkg/pipelinerun/pipelinerun_test.go @@ -15,9 +15,11 @@ package pipelinerun import ( + "fmt" "testing" "time" + "github.com/google/go-cmp/cmp" "github.com/jonboulle/clockwork" "github.com/tektoncd/cli/pkg/test" cb "github.com/tektoncd/cli/pkg/test/builder" @@ -25,9 +27,12 @@ import ( "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1" "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" pipelinev1beta1test "github.com/tektoncd/pipeline/test" + "github.com/tektoncd/pipeline/test/diff" + "github.com/tektoncd/pipeline/test/parse" pipelinetest "github.com/tektoncd/pipeline/test/v1alpha1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "knative.dev/pkg/apis" duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" ) @@ -38,6 +43,7 @@ func TestPipelineRunsList_with_single_run(t *testing.T) { runDuration := 1 * time.Minute prdata := []*v1alpha1.PipelineRun{ + { ObjectMeta: metav1.ObjectMeta{ Name: "pipelinerun", @@ -459,6 +465,376 @@ func TestPipelineRunGet_v1beta1(t *testing.T) { test.AssertOutput(t, "pipelinerun1", got.Name) } +func TestPipelineRunGet_MinimalEmbeddedStatus(t *testing.T) { + version := "v1beta1" + clock := clockwork.NewFakeClock() + pr1Started := clock.Now().Add(10 * time.Second) + runDuration := 1 * time.Minute + + prdata := []*v1beta1.PipelineRun{ + parse.MustParsePipelineRun(t, fmt.Sprintf(` +metadata: + name: pipelinerun1 + namespace: ns + labels: + tekton.dev/pipeline: pipeline +spec: + pipelineRef: + name: pipeline +status: + conditions: + - lastTransitionTime: null + message: All Tasks have completed executing + reason: Succeeded + status: "True" + type: Succeeded + startTime: %s + completionTime: %s + childReferences: + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: task-run-1 + pipelineTaskName: tr1 + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: task-run-2 + pipelineTaskName: tr2 + - apiVersion: tekton.dev/v1alpha1 + kind: Run + name: run-1 + pipelineTaskName: r1 + - apiVersion: tekton.dev/v1alpha1 + kind: Run + name: run-2 + pipelineTaskName: r2 +`, pr1Started.Format(time.RFC3339), pr1Started.Add(runDuration).Format(time.RFC3339))), + parse.MustParsePipelineRun(t, fmt.Sprintf(` +metadata: + name: pipelinerun2 + namespace: ns + labels: + tekton.dev/pipeline: pipeline +spec: + pipelineRef: + name: pipeline +status: + conditions: + - lastTransitionTime: null + message: All Tasks have completed executing + reason: Succeeded + status: "True" + type: Succeeded + startTime: %s + completionTime: %s + taskRuns: + task-run-1: + pipelineTaskName: tr1 + status: + conditions: + - reason: Succeeded + status: "True" + type: Succeeded + task-run-2: + pipelineTaskName: tr2 + status: + conditions: + - reason: Failed + status: "False" + type: Succeeded + runs: + run-1: + pipelineTaskName: r1 + status: + conditions: + - reason: Succeeded + status: "True" + type: Succeeded + run-2: + pipelineTaskName: r2 + status: + conditions: + - reason: Failed + status: "False" + type: Succeeded +`, pr1Started.Format(time.RFC3339), pr1Started.Add(runDuration).Format(time.RFC3339))), + } + + trData := []*v1beta1.TaskRun{ + parse.MustParseTaskRun(t, ` +metadata: + name: task-run-1 + namespace: ns +spec: + taskRef: + name: someTask +status: + conditions: + - reason: Succeeded + status: "True" + type: Succeeded +`), + parse.MustParseTaskRun(t, ` +metadata: + name: task-run-2 + namespace: ns +spec: + taskRef: + name: someTask +status: + conditions: + - reason: Failed + status: "False" + type: Succeeded +`), + } + + runsData := []*v1alpha1.Run{ + parse.MustParseRun(t, ` +metadata: + name: run-1 + namespace: ns +spec: + ref: + name: someCustomTask +status: + conditions: + - reason: Succeeded + status: "True" + type: Succeeded +`), + parse.MustParseRun(t, ` +metadata: + name: run-2 + namespace: ns +spec: + ref: + name: someCustomTask +status: + conditions: + - reason: Failed + status: "False" + type: Succeeded +`), + } + + cs, _ := test.SeedV1beta1TestData(t, pipelinev1beta1test.Data{ + PipelineRuns: prdata, + TaskRuns: trData, + Runs: runsData, + }) + + cs.Pipeline.Resources = cb.APIResourceList(version, []string{"pipelinerun"}) + tdc := testDynamic.Options{} + dc, err := tdc.Client( + cb.UnstructuredV1beta1PR(prdata[0], version), + cb.UnstructuredV1beta1PR(prdata[1], version), + ) + if err != nil { + t.Errorf("unable to create dynamic client: %v", err) + } + + p := &test.Params{Tekton: cs.Pipeline, Clock: clock, Kube: cs.Kube, Dynamic: dc} + c, err := p.Clients() + if err != nil { + t.Errorf("unable to create client: %v", err) + } + + got, err := Get(c, "pipelinerun1", metav1.GetOptions{}, "ns") + if err != nil { + t.Errorf("unexpected Error") + } + test.AssertOutput(t, "pipelinerun1", got.Name) + + tr1 := got.Status.TaskRuns[trData[0].Name] + if tr1 == nil { + t.Fatalf("TaskRun status map does not contain expected TaskRun %s", trData[0].Name) + } + test.AssertOutput(t, string(v1beta1.TaskRunReasonSuccessful), tr1.Status.GetCondition(apis.ConditionSucceeded).Reason) + tr2 := got.Status.TaskRuns[trData[1].Name] + if tr2 == nil { + t.Fatalf("TaskRun status map does not contain expected TaskRun %s", trData[1].Name) + } + test.AssertOutput(t, string(v1beta1.TaskRunReasonFailed), tr2.Status.GetCondition(apis.ConditionSucceeded).Reason) + + r1 := got.Status.Runs[runsData[0].Name] + if r1 == nil { + t.Fatalf("Run status map does not contain expected Run %s", runsData[0].Name) + } + test.AssertOutput(t, "Succeeded", r1.Status.GetCondition(apis.ConditionSucceeded).Reason) + r2 := got.Status.Runs[runsData[1].Name] + if r2 == nil { + t.Fatalf("Run status map does not contain expected Run %s", runsData[1].Name) + } + test.AssertOutput(t, "Failed", r2.Status.GetCondition(apis.ConditionSucceeded).Reason) + + gotFull, err := Get(c, "pipelinerun2", metav1.GetOptions{}, "ns") + if err != nil { + t.Errorf("unexpected Error") + } + + if d := cmp.Diff(got.Status.TaskRuns, gotFull.Status.TaskRuns); d != "" { + t.Errorf("mismatch between minimal and full TaskRun statuses: %s", diff.PrintWantGot(d)) + } + if d := cmp.Diff(got.Status.Runs, gotFull.Status.Runs); d != "" { + t.Errorf("mismatch between minimal and full Run statuses: %s", diff.PrintWantGot(d)) + } +} + +func TestPipelineRunList_MinimalEmbeddedStatus(t *testing.T) { + version := "v1beta1" + clock := clockwork.NewFakeClock() + pr1Started := clock.Now().Add(10 * time.Second) + runDuration := 1 * time.Minute + + prdata := []*v1beta1.PipelineRun{parse.MustParsePipelineRun(t, fmt.Sprintf(` +metadata: + name: pipelinerun1 + namespace: ns + labels: + tekton.dev/pipeline: pipeline +spec: + pipelineRef: + name: pipeline +status: + conditions: + - lastTransitionTime: null + message: All Tasks have completed executing + reason: Succeeded + status: "True" + type: Succeeded + startTime: %s + completionTime: %s + childReferences: + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: task-run-1 + pipelineTaskName: tr1 + - apiVersion: tekton.dev/v1beta1 + kind: TaskRun + name: task-run-2 + pipelineTaskName: tr2 + - apiVersion: tekton.dev/v1alpha1 + kind: Run + name: run-1 + pipelineTaskName: r1 + - apiVersion: tekton.dev/v1alpha1 + kind: Run + name: run-2 + pipelineTaskName: r2 +`, pr1Started.Format(time.RFC3339), pr1Started.Add(runDuration).Format(time.RFC3339))), + } + + trData := []*v1beta1.TaskRun{ + parse.MustParseTaskRun(t, ` +metadata: + name: task-run-1 + namespace: ns +spec: + taskRef: + name: someTask +status: + conditions: + - reason: Succeeded + status: "True" + type: Succeeded +`), + parse.MustParseTaskRun(t, ` +metadata: + name: task-run-2 + namespace: ns +spec: + taskRef: + name: someTask +status: + conditions: + - reason: Failed + status: "False" + type: Succeeded +`), + } + + runsData := []*v1alpha1.Run{ + parse.MustParseRun(t, ` +metadata: + name: run-1 + namespace: ns +spec: + ref: + name: someCustomTask +status: + conditions: + - reason: Succeeded + status: "True" + type: Succeeded +`), + parse.MustParseRun(t, ` +metadata: + name: run-2 + namespace: ns +spec: + ref: + name: someCustomTask +status: + conditions: + - reason: Failed + status: "False" + type: Succeeded +`), + } + + cs, _ := test.SeedV1beta1TestData(t, pipelinev1beta1test.Data{ + PipelineRuns: prdata, + TaskRuns: trData, + Runs: runsData, + }) + + cs.Pipeline.Resources = cb.APIResourceList(version, []string{"pipelinerun"}) + tdc := testDynamic.Options{} + dc, err := tdc.Client( + cb.UnstructuredV1beta1PR(prdata[0], version), + ) + if err != nil { + t.Errorf("unable to create dynamic client: %v", err) + } + + p := &test.Params{Tekton: cs.Pipeline, Clock: clock, Kube: cs.Kube, Dynamic: dc} + c, err := p.Clients() + if err != nil { + t.Errorf("unable to create client: %v", err) + } + + prList, err := List(c, metav1.ListOptions{}, "ns") + if err != nil { + t.Errorf("unexpected Error") + } + test.AssertOutput(t, 1, len(prList.Items)) + + got := prList.Items[0] + test.AssertOutput(t, "pipelinerun1", got.Name) + + tr1 := got.Status.TaskRuns[trData[0].Name] + if tr1 == nil { + t.Fatalf("TaskRun status map does not contain expected TaskRun %s", trData[0].Name) + } + test.AssertOutput(t, string(v1beta1.TaskRunReasonSuccessful), tr1.Status.GetCondition(apis.ConditionSucceeded).Reason) + tr2 := got.Status.TaskRuns[trData[1].Name] + if tr2 == nil { + t.Fatalf("TaskRun status map does not contain expected TaskRun %s", trData[1].Name) + } + test.AssertOutput(t, string(v1beta1.TaskRunReasonFailed), tr2.Status.GetCondition(apis.ConditionSucceeded).Reason) + + r1 := got.Status.Runs[runsData[0].Name] + if r1 == nil { + t.Fatalf("Run status map does not contain expected Run %s", runsData[0].Name) + } + test.AssertOutput(t, "Succeeded", r1.Status.GetCondition(apis.ConditionSucceeded).Reason) + r2 := got.Status.Runs[runsData[1].Name] + if r2 == nil { + t.Fatalf("Run status map does not contain expected Run %s", runsData[1].Name) + } + test.AssertOutput(t, "Failed", r2.Status.GetCondition(apis.ConditionSucceeded).Reason) +} + func TestPipelineRunCreate(t *testing.T) { version := "v1alpha1" prdata := v1beta1.PipelineRun{ diff --git a/pkg/pipelinerun/tracker.go b/pkg/pipelinerun/tracker.go index e04c57f4af..0157d928a1 100644 --- a/pkg/pipelinerun/tracker.go +++ b/pkg/pipelinerun/tracker.go @@ -93,7 +93,14 @@ func (t *Tracker) Monitor(allowed []string) <-chan []trh.Run { if !ok || pr == nil { return } + + trMap, runMap, err := getFullPipelineTaskStatuses(context.Background(), t.Tekton, t.Ns, pr) + if err != nil { + return + } pr.DeepCopyInto(&pipelinerunConverted) + pipelinerunConverted.Status.TaskRuns = trMap + pipelinerunConverted.Status.Runs = runMap } trC <- t.findNewTaskruns(&pipelinerunConverted, allowed) diff --git a/pkg/pipelinerun/tracker_test.go b/pkg/pipelinerun/tracker_test.go index 21eb66e52c..0319f43298 100644 --- a/pkg/pipelinerun/tracker_test.go +++ b/pkg/pipelinerun/tracker_test.go @@ -18,16 +18,18 @@ import ( "testing" "time" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" "github.com/tektoncd/cli/pkg/actions" trh "github.com/tektoncd/cli/pkg/taskrun" "github.com/tektoncd/cli/pkg/test" - clitest "github.com/tektoncd/cli/pkg/test" cb "github.com/tektoncd/cli/pkg/test/builder" - "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1" "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" "github.com/tektoncd/pipeline/pkg/client/clientset/versioned" - pipelinetest "github.com/tektoncd/pipeline/test/v1alpha1" + pipelinev1beta1test "github.com/tektoncd/pipeline/test" + "github.com/tektoncd/pipeline/test/diff" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/watch" @@ -54,13 +56,15 @@ func TestTracker_pipelinerun_complete(t *testing.T) { ) scenarios := []struct { - name string - tasks []string - expected []trh.Run + name string + tasks []string + fullEmbeddedStatus bool + expected []trh.Run }{ { - name: "for all tasks", - tasks: allTasks, + name: "for all tasks, full status", + tasks: allTasks, + fullEmbeddedStatus: true, expected: []trh.Run{ { Name: tr1Name, @@ -70,10 +74,33 @@ func TestTracker_pipelinerun_complete(t *testing.T) { Task: task2Name, }, }, - }, - { - name: "for one task", - tasks: onlyTask1, + }, { + name: "for one task, full status", + tasks: onlyTask1, + fullEmbeddedStatus: true, + expected: []trh.Run{ + { + Name: tr1Name, + Task: task1Name, + }, + }, + }, { + name: "for all tasks, minimal status", + tasks: allTasks, + fullEmbeddedStatus: false, + expected: []trh.Run{ + { + Name: tr1Name, + Task: task1Name, + }, { + Name: tr2Name, + Task: task2Name, + }, + }, + }, { + name: "for one task, minimal status", + tasks: onlyTask1, + fullEmbeddedStatus: false, expected: []trh.Run{ { Name: tr1Name, @@ -84,19 +111,19 @@ func TestTracker_pipelinerun_complete(t *testing.T) { } for _, s := range scenarios { - taskruns := []*v1alpha1.TaskRun{ + taskruns := []*v1beta1.TaskRun{ { ObjectMeta: metav1.ObjectMeta{ Name: tr1Name, Namespace: ns, }, - Spec: v1alpha1.TaskRunSpec{ + Spec: v1beta1.TaskRunSpec{ TaskRef: &v1beta1.TaskRef{ Name: task1Name, }, }, - Status: v1alpha1.TaskRunStatus{ - TaskRunStatusFields: v1alpha1.TaskRunStatusFields{ + Status: v1beta1.TaskRunStatus{ + TaskRunStatusFields: v1beta1.TaskRunStatusFields{ PodName: tr1Pod, }, }, @@ -106,20 +133,20 @@ func TestTracker_pipelinerun_complete(t *testing.T) { Name: tr2Name, Namespace: ns, }, - Spec: v1alpha1.TaskRunSpec{ + Spec: v1beta1.TaskRunSpec{ TaskRef: &v1beta1.TaskRef{ Name: task2Name, }, }, - Status: v1alpha1.TaskRunStatus{ - TaskRunStatusFields: v1alpha1.TaskRunStatusFields{ + Status: v1beta1.TaskRunStatus{ + TaskRunStatusFields: v1beta1.TaskRunStatusFields{ PodName: tr2Pod, }, }, }, } - initialPR := []*v1alpha1.PipelineRun{ + initialPR := []*v1beta1.PipelineRun{ { ObjectMeta: metav1.ObjectMeta{ Name: prName, @@ -135,16 +162,27 @@ func TestTracker_pipelinerun_complete(t *testing.T) { }, }, }, - PipelineRunStatusFields: v1alpha1.PipelineRunStatusFields{ - TaskRuns: map[string]*v1alpha1.PipelineRunTaskRunStatus{ - tr1Name: {PipelineTaskName: task1Name, Status: &taskruns[0].Status}, - }, - }, + PipelineRunStatusFields: v1beta1.PipelineRunStatusFields{}, }, }, } - pr := &v1alpha1.PipelineRun{ - Status: v1alpha1.PipelineRunStatus{ + if s.fullEmbeddedStatus { + initialPR[0].Status.TaskRuns = map[string]*v1beta1.PipelineRunTaskRunStatus{ + tr1Name: {PipelineTaskName: task1Name, Status: &taskruns[0].Status}, + } + } else { + initialPR[0].Status.ChildReferences = []v1beta1.ChildStatusReference{{ + Name: tr1Name, + PipelineTaskName: task1Name, + TypeMeta: runtime.TypeMeta{ + APIVersion: "tekton.dev/v1beta1", + Kind: "TaskRun", + }, + }} + } + + pr := &v1beta1.PipelineRun{ + Status: v1beta1.PipelineRunStatus{ Status: duckv1beta1.Status{ Conditions: duckv1beta1.Conditions{ { @@ -153,23 +191,48 @@ func TestTracker_pipelinerun_complete(t *testing.T) { }, }, }, - PipelineRunStatusFields: v1alpha1.PipelineRunStatusFields{ - TaskRuns: map[string]*v1alpha1.PipelineRunTaskRunStatus{ + PipelineRunStatusFields: v1beta1.PipelineRunStatusFields{ + TaskRuns: map[string]*v1beta1.PipelineRunTaskRunStatus{ tr1Name: {PipelineTaskName: task1Name, Status: &taskruns[0].Status}, tr2Name: {PipelineTaskName: task2Name, Status: &taskruns[1].Status}, }, }, }, } + if s.fullEmbeddedStatus { + initialPR[0].Status.TaskRuns = map[string]*v1beta1.PipelineRunTaskRunStatus{ + tr1Name: {PipelineTaskName: task1Name, Status: &taskruns[0].Status}, + tr2Name: {PipelineTaskName: task2Name, Status: &taskruns[1].Status}, + } + } else { + initialPR[0].Status.ChildReferences = []v1beta1.ChildStatusReference{{ + Name: tr1Name, + PipelineTaskName: task1Name, + TypeMeta: runtime.TypeMeta{ + APIVersion: "tekton.dev/v1beta1", + Kind: "TaskRun", + }, + }, { + Name: tr2Name, + PipelineTaskName: task2Name, + TypeMeta: runtime.TypeMeta{ + APIVersion: "tekton.dev/v1beta1", + Kind: "TaskRun", + }, + }} + } - tc := startPipelineRun(t, pipelinetest.Data{PipelineRuns: initialPR, TaskRuns: taskruns}, pr.Status) + tc := startPipelineRun(t, pipelinev1beta1test.Data{PipelineRuns: initialPR, TaskRuns: taskruns}, pr.Status) tracker := NewTracker(pipelineName, ns, tc) if err := actions.InitializeAPIGroupRes(tracker.Tekton.Discovery()); err != nil { t.Errorf("failed to initialize APIGroup Resource") } output := taskRunsFor(s.tasks, tracker) - clitest.AssertOutput(t, s.expected, output) + if d := cmp.Diff(s.expected, output, cmpopts.SortSlices(func(i, j trh.Run) bool { return i.Name < j.Name })); d != "" { + t.Errorf("Unexpected output: %s", diff.PrintWantGot(d)) + } + } } @@ -181,13 +244,13 @@ func taskRunsFor(onlyTasks []string, tracker *Tracker) []trh.Run { return output } -func startPipelineRun(t *testing.T, data pipelinetest.Data, prStatus ...v1alpha1.PipelineRunStatus) versioned.Interface { - cs, _ := test.SeedTestData(t, data) +func startPipelineRun(t *testing.T, data pipelinev1beta1test.Data, prStatus ...v1beta1.PipelineRunStatus) versioned.Interface { + cs, _ := test.SeedV1beta1TestData(t, data) // to keep pushing the taskrun over the period(simulate watch) watcher := watch.NewFake() cs.Pipeline.PrependWatchReactor("pipelineruns", k8stest.DefaultWatchReactor(watcher, nil)) - cs.Pipeline.Resources = cb.APIResourceList("v1alpha1", []string{"task", "taskrun", "pipeline", "pipelinerun"}) + cs.Pipeline.Resources = cb.APIResourceList("v1beta1", []string{"task", "taskrun", "pipeline", "pipelinerun"}) go func() { for _, status := range prStatus { time.Sleep(time.Second * 2) diff --git a/test/e2e-tests.sh b/test/e2e-tests.sh index b594b13796..937f6d3b75 100755 --- a/test/e2e-tests.sh +++ b/test/e2e-tests.sh @@ -38,6 +38,12 @@ tkn() { fi } +function set_minimal_embedded_status() { + jsonpatch=$(printf "{\"data\": {\"embedded-status\": \"%s\"}}" "minimal") + echo "feature-flags ConfigMap patch: ${jsonpatch}" + kubectl patch configmap feature-flags -n tekton-pipelines -p "$jsonpatch" +} + kubectl get crds|grep tekton\\.dev && fail_test "TektonCD CRDS should not be installed, you should reset them before each runs" # command before creation of resources @@ -172,4 +178,13 @@ fi go_test_e2e ./test/e2e/... || failed=1 (( failed )) && fail_test +# Re-run the PipelineRun tests with "embedded-status" set to "minimal" +header "Running Go e2e tests with Pipeline embedded-status set to minimal" + +set_minimal_embedded_status +failed=0 + +go_test_e2e ./test/e2e/pipelinerun/... || failed=1 +(( failed )) && fail_test + success diff --git a/third_party/VENDOR-LICENSE/github.com/gdamore/tcell/LICENSE b/third_party/VENDOR-LICENSE/github.com/gdamore/tcell/v2/LICENSE similarity index 100% rename from third_party/VENDOR-LICENSE/github.com/gdamore/tcell/LICENSE rename to third_party/VENDOR-LICENSE/github.com/gdamore/tcell/v2/LICENSE diff --git a/third_party/VENDOR-LICENSE/github.com/hashicorp/go-plugin/README.md b/third_party/VENDOR-LICENSE/github.com/hashicorp/go-plugin/README.md index 46ee09fc0c..39391f24fe 100644 --- a/third_party/VENDOR-LICENSE/github.com/hashicorp/go-plugin/README.md +++ b/third_party/VENDOR-LICENSE/github.com/hashicorp/go-plugin/README.md @@ -3,8 +3,9 @@ `go-plugin` is a Go (golang) plugin system over RPC. It is the plugin system that has been in use by HashiCorp tooling for over 4 years. While initially created for [Packer](https://www.packer.io), it is additionally in use by -[Terraform](https://www.terraform.io), [Nomad](https://www.nomadproject.io), and -[Vault](https://www.vaultproject.io). +[Terraform](https://www.terraform.io), [Nomad](https://www.nomadproject.io), +[Vault](https://www.vaultproject.io), and +[Boundary](https://www.boundaryproject.io). While the plugin system is over RPC, it is currently only designed to work over a local [reliable] network. Plugins over a real network are not supported diff --git a/third_party/VENDOR-LICENSE/github.com/hashicorp/go-plugin/client.go b/third_party/VENDOR-LICENSE/github.com/hashicorp/go-plugin/client.go index 67dca88357..e0bee88a1d 100644 --- a/third_party/VENDOR-LICENSE/github.com/hashicorp/go-plugin/client.go +++ b/third_party/VENDOR-LICENSE/github.com/hashicorp/go-plugin/client.go @@ -574,6 +574,8 @@ func (c *Client) Start() (addr net.Addr, err error) { c.config.TLSConfig = &tls.Config{ Certificates: []tls.Certificate{cert}, + ClientAuth: tls.RequireAndVerifyClientCert, + MinVersion: tls.VersionTLS12, ServerName: "localhost", } } @@ -629,17 +631,19 @@ func (c *Client) Start() (addr net.Addr, err error) { // Wait for the command to end. err := cmd.Wait() - debugMsgArgs := []interface{}{ + msgArgs := []interface{}{ "path", path, "pid", pid, } if err != nil { - debugMsgArgs = append(debugMsgArgs, + msgArgs = append(msgArgs, []interface{}{"error", err.Error()}...) + c.logger.Error("plugin process exited", msgArgs...) + } else { + // Log and make sure to flush the logs right away + c.logger.Info("plugin process exited", msgArgs...) } - // Log and make sure to flush the logs write away - c.logger.Debug("plugin process exited", debugMsgArgs...) os.Stderr.Sync() // Set that we exited, which takes a lock @@ -774,7 +778,7 @@ func (c *Client) Start() (addr net.Addr, err error) { } // loadServerCert is used by AutoMTLS to read an x.509 cert returned by the -// server, and load it as the RootCA for the client TLSConfig. +// server, and load it as the RootCA and ClientCA for the client TLSConfig. func (c *Client) loadServerCert(cert string) error { certPool := x509.NewCertPool() @@ -791,6 +795,7 @@ func (c *Client) loadServerCert(cert string) error { certPool.AddCert(x509Cert) c.config.TLSConfig.RootCAs = certPool + c.config.TLSConfig.ClientCAs = certPool return nil } diff --git a/third_party/VENDOR-LICENSE/github.com/hashicorp/go-plugin/process_posix.go b/third_party/VENDOR-LICENSE/github.com/hashicorp/go-plugin/process_posix.go index 70ba546bf6..185957f8d1 100644 --- a/third_party/VENDOR-LICENSE/github.com/hashicorp/go-plugin/process_posix.go +++ b/third_party/VENDOR-LICENSE/github.com/hashicorp/go-plugin/process_posix.go @@ -1,3 +1,4 @@ +//go:build !windows // +build !windows package plugin diff --git a/third_party/VENDOR-LICENSE/github.com/hashicorp/go-plugin/rpc_server.go b/third_party/VENDOR-LICENSE/github.com/hashicorp/go-plugin/rpc_server.go index 5bb18dd5db..449ba6cc1e 100644 --- a/third_party/VENDOR-LICENSE/github.com/hashicorp/go-plugin/rpc_server.go +++ b/third_party/VENDOR-LICENSE/github.com/hashicorp/go-plugin/rpc_server.go @@ -45,7 +45,11 @@ func (s *RPCServer) Serve(lis net.Listener) { for { conn, err := lis.Accept() if err != nil { - log.Printf("[ERR] plugin: plugin server: %s", err) + severity := "ERR" + if errors.Is(err, net.ErrClosed) { + severity = "DEBUG" + } + log.Printf("[%s] plugin: plugin server: %s", severity, err) return } diff --git a/third_party/VENDOR-LICENSE/github.com/hashicorp/go-plugin/server.go b/third_party/VENDOR-LICENSE/github.com/hashicorp/go-plugin/server.go index 7a58cc3919..e134999103 100644 --- a/third_party/VENDOR-LICENSE/github.com/hashicorp/go-plugin/server.go +++ b/third_party/VENDOR-LICENSE/github.com/hashicorp/go-plugin/server.go @@ -304,13 +304,13 @@ func Serve(opts *ServeConfig) { certPEM, keyPEM, err := generateCert() if err != nil { - logger.Error("failed to generate client certificate", "error", err) + logger.Error("failed to generate server certificate", "error", err) panic(err) } cert, err := tls.X509KeyPair(certPEM, keyPEM) if err != nil { - logger.Error("failed to parse client certificate", "error", err) + logger.Error("failed to parse server certificate", "error", err) panic(err) } @@ -319,6 +319,8 @@ func Serve(opts *ServeConfig) { ClientAuth: tls.RequireAndVerifyClientCert, ClientCAs: clientCertPool, MinVersion: tls.VersionTLS12, + RootCAs: clientCertPool, + ServerName: "localhost", } // We send back the raw leaf cert data for the client rather than the diff --git a/third_party/VENDOR-LICENSE/github.com/hashicorp/go-secure-stdlib/parseutil/parseutil.go b/third_party/VENDOR-LICENSE/github.com/hashicorp/go-secure-stdlib/parseutil/parseutil.go index 167953158c..e469499bdc 100644 --- a/third_party/VENDOR-LICENSE/github.com/hashicorp/go-secure-stdlib/parseutil/parseutil.go +++ b/third_party/VENDOR-LICENSE/github.com/hashicorp/go-secure-stdlib/parseutil/parseutil.go @@ -4,6 +4,7 @@ import ( "encoding/json" "errors" "fmt" + "math" "regexp" "strconv" "strings" @@ -92,6 +93,9 @@ func ParseCapacityString(in interface{}) (uint64, error) { return cap, nil } +// Parse a duration from an arbitrary value (a string or numeric value) into +// a time.Duration; when units are missing (such as when a numeric type is +// provided), the duration is assumed to be in seconds. func ParseDurationSecond(in interface{}) (time.Duration, error) { var dur time.Duration jsonIn, ok := in.(json.Number) @@ -147,6 +151,9 @@ func ParseDurationSecond(in interface{}) (time.Duration, error) { return dur, nil } +// Parse an absolute timestamp from the provided arbitrary value (string or +// numeric value). When an untyped numeric value is provided, it is assumed +// to be seconds from the Unix Epoch. func ParseAbsoluteTime(in interface{}) (time.Time, error) { var t time.Time switch inp := in.(type) { @@ -195,6 +202,13 @@ func ParseAbsoluteTime(in interface{}) (time.Time, error) { return t, nil } +// ParseInt takes an arbitrary value (either a string or numeric type) and +// parses it as an int64 value. This value is assumed to be larger than the +// provided type, but cannot safely be cast. +// +// When the end value is bounded (such as an int value), it is recommended +// to instead call SafeParseInt or SafeParseIntRange to safely cast to a +// more restrictive type. func ParseInt(in interface{}) (int64, error) { var ret int64 jsonIn, ok := in.(json.Number) @@ -232,6 +246,11 @@ func ParseInt(in interface{}) (int64, error) { return ret, nil } +// ParseDirectIntSlice behaves similarly to ParseInt, but accepts typed +// slices, returning a slice of int64s. +// +// If the starting value may not be in slice form (e.g.. a bare numeric value +// could be provided), it is suggested to call ParseIntSlice instead. func ParseDirectIntSlice(in interface{}) ([]int64, error) { var ret []int64 @@ -290,6 +309,10 @@ func ParseDirectIntSlice(in interface{}) ([]int64, error) { // nicely handle the common cases of providing only an int-ish, providing // an actual slice of int-ishes, or providing a comma-separated list of // numbers. +// +// When []int64 is not the desired final type (or the values should be +// range-bound), it is suggested to call SafeParseIntSlice or +// SafeParseIntSliceRange instead. func ParseIntSlice(in interface{}) ([]int64, error) { if ret, err := ParseInt(in); err == nil { return []int64{ret}, nil @@ -320,6 +343,7 @@ func ParseIntSlice(in interface{}) ([]int64, error) { return nil, errors.New("could not parse value from input") } +// Parses the provided arbitrary value as a boolean-like value. func ParseBool(in interface{}) (bool, error) { var result bool if err := mapstructure.WeakDecode(in, &result); err != nil { @@ -328,6 +352,7 @@ func ParseBool(in interface{}) (bool, error) { return result, nil } +// Parses the provided arbitrary value as a string. func ParseString(in interface{}) (string, error) { var result string if err := mapstructure.WeakDecode(in, &result); err != nil { @@ -336,6 +361,7 @@ func ParseString(in interface{}) (string, error) { return result, nil } +// Parses the provided string-like value as a comma-separated list of values. func ParseCommaStringSlice(in interface{}) ([]string, error) { jsonIn, ok := in.(json.Number) if ok { @@ -362,6 +388,7 @@ func ParseCommaStringSlice(in interface{}) ([]string, error) { return strutil.TrimStrings(result), nil } +// Parses the specified value as one or more addresses, separated by commas. func ParseAddrs(addrs interface{}) ([]*sockaddr.SockAddrMarshaler, error) { out := make([]*sockaddr.SockAddrMarshaler, 0) stringAddrs := make([]string, 0) @@ -401,3 +428,75 @@ func ParseAddrs(addrs interface{}) ([]*sockaddr.SockAddrMarshaler, error) { return out, nil } + +// Parses the provided arbitrary value (see ParseInt), ensuring it is within +// the specified range (inclusive of bounds). If this range corresponds to a +// smaller type, the returned value can then be safely cast without risking +// overflow. +func SafeParseIntRange(in interface{}, min int64, max int64) (int64, error) { + raw, err := ParseInt(in) + if err != nil { + return 0, err + } + + if raw < min || raw > max { + return 0, fmt.Errorf("error parsing int value; out of range [%v to %v]: %v", min, max, raw) + } + + return raw, nil +} + +// Parses the specified arbitrary value (see ParseInt), ensuring that the +// resulting value is within the range for an int value. If no error occurred, +// the caller knows no overflow occurred. +func SafeParseInt(in interface{}) (int, error) { + raw, err := SafeParseIntRange(in, math.MinInt, math.MaxInt) + return int(raw), err +} + +// Parses the provided arbitrary value (see ParseIntSlice) into a slice of +// int64 values, ensuring each is within the specified range (inclusive of +// bounds). If this range corresponds to a smaller type, the returned value +// can then be safely cast without risking overflow. +// +// If elements is positive, it is used to ensure the resulting slice is +// bounded above by that many number of elements (inclusive). +func SafeParseIntSliceRange(in interface{}, minValue int64, maxValue int64, elements int) ([]int64, error) { + raw, err := ParseIntSlice(in) + if err != nil { + return nil, err + } + + if elements > 0 && len(raw) > elements { + return nil, fmt.Errorf("error parsing value from input: got %v but expected at most %v elements", len(raw), elements) + } + + for index, value := range raw { + if value < minValue || value > maxValue { + return nil, fmt.Errorf("error parsing value from input: element %v was outside of range [%v to %v]: %v", index, minValue, maxValue, value) + } + } + + return raw, nil +} + +// Parses the provided arbitrary value (see ParseIntSlice) into a slice of +// int values, ensuring the each resulting value in the slice is within the +// range for an int value. If no error occurred, the caller knows no overflow +// occurred. +// +// If elements is positive, it is used to ensure the resulting slice is +// bounded above by that many number of elements (inclusive). +func SafeParseIntSlice(in interface{}, elements int) ([]int, error) { + raw, err := SafeParseIntSliceRange(in, math.MinInt, math.MaxInt, elements) + if err != nil || raw == nil { + return nil, err + } + + var result = make([]int, 0, len(raw)) + for _, element := range raw { + result = append(result, int(element)) + } + + return result, nil +} diff --git a/third_party/VENDOR-LICENSE/github.com/hashicorp/go-version/CHANGELOG.md b/third_party/VENDOR-LICENSE/github.com/hashicorp/go-version/CHANGELOG.md index 2020c47274..094550020e 100644 --- a/third_party/VENDOR-LICENSE/github.com/hashicorp/go-version/CHANGELOG.md +++ b/third_party/VENDOR-LICENSE/github.com/hashicorp/go-version/CHANGELOG.md @@ -1,4 +1,4 @@ -# 1.4.0 (January 5, 2021) +# 1.4.0 (January 5, 2022) FEATURES: diff --git a/third_party/VENDOR-LICENSE/github.com/hashicorp/go-version/README.md b/third_party/VENDOR-LICENSE/github.com/hashicorp/go-version/README.md index 851a337beb..4d25050903 100644 --- a/third_party/VENDOR-LICENSE/github.com/hashicorp/go-version/README.md +++ b/third_party/VENDOR-LICENSE/github.com/hashicorp/go-version/README.md @@ -1,5 +1,5 @@ # Versioning Library for Go -[![Build Status](https://circleci.com/gh/hashicorp/go-version/tree/master.svg?style=svg)](https://circleci.com/gh/hashicorp/go-version/tree/master) +[![Build Status](https://circleci.com/gh/hashicorp/go-version/tree/main.svg?style=svg)](https://circleci.com/gh/hashicorp/go-version/tree/main) [![GoDoc](https://godoc.org/github.com/hashicorp/go-version?status.svg)](https://godoc.org/github.com/hashicorp/go-version) go-version is a library for parsing versions and version constraints, diff --git a/third_party/VENDOR-LICENSE/github.com/hashicorp/go-version/version.go b/third_party/VENDOR-LICENSE/github.com/hashicorp/go-version/version.go index 116a74466d..e87df69906 100644 --- a/third_party/VENDOR-LICENSE/github.com/hashicorp/go-version/version.go +++ b/third_party/VENDOR-LICENSE/github.com/hashicorp/go-version/version.go @@ -388,3 +388,20 @@ func (v *Version) String() string { func (v *Version) Original() string { return v.original } + +// UnmarshalText implements encoding.TextUnmarshaler interface. +func (v *Version) UnmarshalText(b []byte) error { + temp, err := NewVersion(string(b)) + if err != nil { + return err + } + + *v = *temp + + return nil +} + +// MarshalText implements encoding.TextMarshaler interface. +func (v *Version) MarshalText() ([]byte, error) { + return []byte(v.String()), nil +} diff --git a/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/helper/certutil/helpers.go b/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/helper/certutil/helpers.go index b6bee2e342..457de9b022 100644 --- a/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/helper/certutil/helpers.go +++ b/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/helper/certutil/helpers.go @@ -150,6 +150,46 @@ func ParsePKIJSON(input []byte) (*ParsedCertBundle, error) { return nil, errutil.UserError{Err: "unable to parse out of either secret data or a secret object"} } +func ParseDERKey(privateKeyBytes []byte) (signer crypto.Signer, format BlockType, err error) { + if signer, err = x509.ParseECPrivateKey(privateKeyBytes); err == nil { + format = ECBlock + return + } + + if signer, err = x509.ParsePKCS1PrivateKey(privateKeyBytes); err == nil { + format = PKCS1Block + return + } + + var rawKey interface{} + if rawKey, err = x509.ParsePKCS8PrivateKey(privateKeyBytes); err == nil { + switch rawSigner := rawKey.(type) { + case *rsa.PrivateKey: + signer = rawSigner + case *ecdsa.PrivateKey: + signer = rawSigner + case ed25519.PrivateKey: + signer = rawSigner + default: + return nil, UnknownBlock, errutil.InternalError{Err: "unknown type for parsed PKCS8 Private Key"} + } + + format = PKCS8Block + return + } + + return nil, UnknownBlock, err +} + +func ParsePEMKey(keyPem string) (crypto.Signer, BlockType, error) { + pemBlock, _ := pem.Decode([]byte(keyPem)) + if pemBlock == nil { + return nil, UnknownBlock, errutil.UserError{Err: "no data found in PEM block"} + } + + return ParseDERKey(pemBlock.Bytes) +} + // ParsePEMBundle takes a string of concatenated PEM-format certificate // and private key values and decodes/parses them, checking validity along // the way. The first certificate must be the subject certificate and issuing @@ -170,43 +210,19 @@ func ParsePEMBundle(pemBundle string) (*ParsedCertBundle, error) { return nil, errutil.UserError{Err: "no data found in PEM block"} } - if signer, err := x509.ParseECPrivateKey(pemBlock.Bytes); err == nil { + if signer, format, err := ParseDERKey(pemBlock.Bytes); err == nil { if parsedBundle.PrivateKeyType != UnknownPrivateKey { return nil, errutil.UserError{Err: "more than one private key given; provide only one private key in the bundle"} } - parsedBundle.PrivateKeyFormat = ECBlock - parsedBundle.PrivateKeyType = ECPrivateKey - parsedBundle.PrivateKeyBytes = pemBlock.Bytes - parsedBundle.PrivateKey = signer - } else if signer, err := x509.ParsePKCS1PrivateKey(pemBlock.Bytes); err == nil { - if parsedBundle.PrivateKeyType != UnknownPrivateKey { - return nil, errutil.UserError{Err: "more than one private key given; provide only one private key in the bundle"} + parsedBundle.PrivateKeyFormat = format + parsedBundle.PrivateKeyType = GetPrivateKeyTypeFromSigner(signer) + if parsedBundle.PrivateKeyType == UnknownPrivateKey { + return nil, errutil.UserError{Err: "Unknown type of private key included in the bundle: %v"} } - parsedBundle.PrivateKeyType = RSAPrivateKey - parsedBundle.PrivateKeyFormat = PKCS1Block + parsedBundle.PrivateKeyBytes = pemBlock.Bytes parsedBundle.PrivateKey = signer - } else if signer, err := x509.ParsePKCS8PrivateKey(pemBlock.Bytes); err == nil { - parsedBundle.PrivateKeyFormat = PKCS8Block - - if parsedBundle.PrivateKeyType != UnknownPrivateKey { - return nil, errutil.UserError{Err: "More than one private key given; provide only one private key in the bundle"} - } - switch signer := signer.(type) { - case *rsa.PrivateKey: - parsedBundle.PrivateKey = signer - parsedBundle.PrivateKeyType = RSAPrivateKey - parsedBundle.PrivateKeyBytes = pemBlock.Bytes - case *ecdsa.PrivateKey: - parsedBundle.PrivateKey = signer - parsedBundle.PrivateKeyType = ECPrivateKey - parsedBundle.PrivateKeyBytes = pemBlock.Bytes - case ed25519.PrivateKey: - parsedBundle.PrivateKey = signer - parsedBundle.PrivateKeyType = Ed25519PrivateKey - parsedBundle.PrivateKeyBytes = pemBlock.Bytes - } } else if certificates, err := x509.ParseCertificates(pemBlock.Bytes); err == nil { certPath = append(certPath, &CertBlock{ Certificate: certificates[0], @@ -336,7 +352,21 @@ func generateSerialNumber(randReader io.Reader) (*big.Int, error) { return serial, nil } -// ComparePublicKeys compares two public keys and returns true if they match +// ComparePublicKeysAndType compares two public keys and returns true if they match, +// false if their types or contents differ, and an error on unsupported key types. +func ComparePublicKeysAndType(key1Iface, key2Iface crypto.PublicKey) (bool, error) { + equal, err := ComparePublicKeys(key1Iface, key2Iface) + if err != nil { + if strings.Contains(err.Error(), "key types do not match:") { + return false, nil + } + } + + return equal, err +} + +// ComparePublicKeys compares two public keys and returns true if they match, +// returns an error if public key types are mismatched, or they are an unsupported key type. func ComparePublicKeys(key1Iface, key2Iface crypto.PublicKey) (bool, error) { switch key1Iface.(type) { case *rsa.PublicKey: @@ -416,18 +446,30 @@ func ParsePublicKeyPEM(data []byte) (interface{}, error) { return nil, errors.New("data does not contain any valid public keys") } -// addPolicyIdentifiers adds certificate policies extension -// +// AddPolicyIdentifiers adds certificate policies extension, based on CreationBundle func AddPolicyIdentifiers(data *CreationBundle, certTemplate *x509.Certificate) { - for _, oidstr := range data.Params.PolicyIdentifiers { - oid, err := StringToOid(oidstr) + oidOnly := true + for _, oidStr := range data.Params.PolicyIdentifiers { + oid, err := StringToOid(oidStr) if err == nil { certTemplate.PolicyIdentifiers = append(certTemplate.PolicyIdentifiers, oid) } + if err != nil { + oidOnly = false + } + } + if !oidOnly { // Because all policy information is held in the same extension, when we use an extra extension to + // add policy qualifier information, that overwrites any information in the PolicyIdentifiers field on the Cert + // Template, so we need to reparse all the policy identifiers here + extension, err := CreatePolicyInformationExtensionFromStorageStrings(data.Params.PolicyIdentifiers) + if err == nil { + // If this errors out, don't add it, rely on the OIDs parsed into PolicyIdentifiers above + certTemplate.ExtraExtensions = append(certTemplate.ExtraExtensions, *extension) + } } } -// addExtKeyUsageOids adds custom extended key usage OIDs to certificate +// AddExtKeyUsageOids adds custom extended key usage OIDs to certificate func AddExtKeyUsageOids(data *CreationBundle, certTemplate *x509.Certificate) { for _, oidstr := range data.Params.ExtKeyUsageOIDs { oid, err := StringToOid(oidstr) @@ -585,25 +627,17 @@ func DefaultOrValueKeyBits(keyType string, keyBits int) (int, error) { // certain internal circumstances. func DefaultOrValueHashBits(keyType string, keyBits int, hashBits int) (int, error) { if keyType == "ec" { - // To comply with BSI recommendations Section 4.2 and Mozilla root - // store policy section 5.1.2, enforce that NIST P-curves use a hash - // length corresponding to curve length. Note that ed25519 does not - // the "ec" key type. - expectedHashBits := expectedNISTPCurveHashBits[keyBits] - - if expectedHashBits != hashBits && hashBits != 0 { - return hashBits, fmt.Errorf("unsupported signature hash algorithm length (%d) for NIST P-%d", hashBits, keyBits) - } else if hashBits == 0 { - hashBits = expectedHashBits - } + // Enforcement of curve moved to selectSignatureAlgorithmForECDSA. See + // note there about why. } else if keyType == "rsa" && hashBits == 0 { // To match previous behavior (and ignoring NIST's recommendations for // hash size to align with RSA key sizes), default to SHA-2-256. hashBits = 256 - } else if keyType == "ed25519" || keyType == "ed448" { + } else if keyType == "ed25519" || keyType == "ed448" || keyType == "any" { // No-op; ed25519 and ed448 internally specify their own hash and // we do not need to select one. Double hashing isn't supported in - // certificate signing and we must + // certificate signing. Additionally, the any key type can't know + // what hash algorithm to use yet, so default to zero. return 0, nil } @@ -642,7 +676,7 @@ func ValidateDefaultOrValueKeyTypeSignatureLength(keyType string, keyBits int, h // Validates that the length of the hash (in bits) used in the signature // calculation is a known, approved value. func ValidateSignatureLength(keyType string, hashBits int) error { - if keyType == "ed25519" || keyType == "ed448" { + if keyType == "any" || keyType == "ec" || keyType == "ed25519" || keyType == "ed448" { // ed25519 and ed448 include built-in hashing and is not externally // configurable. There are three modes for each of these schemes: // @@ -654,6 +688,13 @@ func ValidateSignatureLength(keyType string, hashBits int) error { // // In all cases, we won't have a hash algorithm to validate here, so // return nil. + // + // Additionally, when KeyType is any, we can't yet validate the + // signature algorithm size, so it takes the default zero value. + // + // When KeyType is ec, we also can't validate this value as we're + // forcefully ignoring the users' choice and specifying a value based + // on issuer type. return nil } @@ -842,16 +883,25 @@ func createCertificate(data *CreationBundle, randReader io.Reader, privateKeyGen } if data.SigningBundle != nil { - if len(data.SigningBundle.Certificate.AuthorityKeyId) > 0 && - !bytes.Equal(data.SigningBundle.Certificate.AuthorityKeyId, data.SigningBundle.Certificate.SubjectKeyId) { - - result.CAChain = []*CertBlock{ - { + if (len(data.SigningBundle.Certificate.AuthorityKeyId) > 0 && + !bytes.Equal(data.SigningBundle.Certificate.AuthorityKeyId, data.SigningBundle.Certificate.SubjectKeyId)) || + data.Params.ForceAppendCaChain { + var chain []*CertBlock + + signingChain := data.SigningBundle.CAChain + // Some bundles already include the root included in the chain, so don't include it twice. + if len(signingChain) == 0 || !bytes.Equal(signingChain[0].Bytes, data.SigningBundle.CertificateBytes) { + chain = append(chain, &CertBlock{ Certificate: data.SigningBundle.Certificate, Bytes: data.SigningBundle.CertificateBytes, - }, + }) } - result.CAChain = append(result.CAChain, data.SigningBundle.CAChain...) + + if len(signingChain) > 0 { + chain = append(chain, signingChain...) + } + + result.CAChain = chain } } @@ -859,16 +909,25 @@ func createCertificate(data *CreationBundle, randReader io.Reader, privateKeyGen } func selectSignatureAlgorithmForECDSA(pub crypto.PublicKey, signatureBits int) x509.SignatureAlgorithm { - // If signature bits are configured, prefer them to the default choice. - switch signatureBits { - case 256: - return x509.ECDSAWithSHA256 - case 384: - return x509.ECDSAWithSHA384 - case 512: - return x509.ECDSAWithSHA512 - } - + // Previously we preferred the user-specified signature bits for ECDSA + // keys. However, this could result in using a longer hash function than + // the underlying NIST P-curve will encode (e.g., a SHA-512 hash with a + // P-256 key). This isn't ideal: the hash is implicitly truncated + // (effectively turning it into SHA-512/256) and we then need to rely + // on the prefix security of the hash. Since both NIST and Mozilla guidance + // suggest instead using the correct hash function, we should prefer that + // over the operator-specified signatureBits. + // + // Lastly, note that pub above needs to be the _signer's_ public key; + // the issue with DefaultOrValueHashBits is that it is called at role + // configuration time, which might _precede_ issuer generation. Thus + // it only has access to the desired key type and not the actual issuer. + // The reference from that function is reproduced below: + // + // > To comply with BSI recommendations Section 4.2 and Mozilla root + // > store policy section 5.1.2, enforce that NIST P-curves use a hash + // > length corresponding to curve length. Note that ed25519 does not + // > implement the "ec" key type. key, ok := pub.(*ecdsa.PublicKey) if !ok { return x509.ECDSAWithSHA256 @@ -1120,7 +1179,7 @@ func signCertificate(data *CreationBundle, randReader io.Reader) (*ParsedCertBun return nil, errutil.InternalError{Err: fmt.Sprintf("unable to parse created certificate: %s", err)} } - result.CAChain = data.SigningBundle.GetCAChain() + result.CAChain = data.SigningBundle.GetFullChain() return result, nil } @@ -1190,3 +1249,20 @@ func GetPublicKeySize(key crypto.PublicKey) int { return -1 } + +// CreateKeyBundle create a KeyBundle struct object which includes a generated key +// of keyType with keyBits leveraging the randomness from randReader. +func CreateKeyBundle(keyType string, keyBits int, randReader io.Reader) (KeyBundle, error) { + return CreateKeyBundleWithKeyGenerator(keyType, keyBits, randReader, generatePrivateKey) +} + +// CreateKeyBundleWithKeyGenerator create a KeyBundle struct object which includes +// a generated key of keyType with keyBits leveraging the randomness from randReader and +// delegates the actual key generation to keyGenerator +func CreateKeyBundleWithKeyGenerator(keyType string, keyBits int, randReader io.Reader, keyGenerator KeyGenerator) (KeyBundle, error) { + result := KeyBundle{} + if err := keyGenerator(keyType, keyBits, &result, randReader); err != nil { + return result, err + } + return result, nil +} diff --git a/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/helper/certutil/types.go b/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/helper/certutil/types.go index 076a4e3528..a5caa2e440 100644 --- a/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/helper/certutil/types.go +++ b/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/helper/certutil/types.go @@ -17,7 +17,10 @@ import ( "crypto/tls" "crypto/x509" "crypto/x509/pkix" + "encoding/asn1" + "encoding/json" "encoding/pem" + "errors" "fmt" "math/big" "net" @@ -78,9 +81,10 @@ type BlockType string // Well-known formats const ( - PKCS1Block BlockType = "RSA PRIVATE KEY" - PKCS8Block BlockType = "PRIVATE KEY" - ECBlock BlockType = "EC PRIVATE KEY" + UnknownBlock BlockType = "" + PKCS1Block BlockType = "RSA PRIVATE KEY" + PKCS8Block BlockType = "PRIVATE KEY" + ECBlock BlockType = "EC PRIVATE KEY" ) // ParsedPrivateKeyContainer allows common key setting for certs and CSRs @@ -137,6 +141,25 @@ type ParsedCSRBundle struct { CSR *x509.CertificateRequest } +type KeyBundle struct { + PrivateKeyType PrivateKeyType + PrivateKeyBytes []byte + PrivateKey crypto.Signer +} + +func GetPrivateKeyTypeFromSigner(signer crypto.Signer) PrivateKeyType { + switch signer.(type) { + case *rsa.PrivateKey: + return RSAPrivateKey + case *ecdsa.PrivateKey: + return ECPrivateKey + case ed25519.PrivateKey: + return Ed25519PrivateKey + default: + return UnknownPrivateKey + } +} + // ToPEMBundle converts a string-based certificate bundle // to a PEM-based string certificate bundle in trust path // order, leaf certificate first @@ -661,9 +684,32 @@ type URLEntries struct { OCSPServers []string `json:"ocsp_servers" structs:"ocsp_servers" mapstructure:"ocsp_servers"` } +type NotAfterBehavior int + +const ( + ErrNotAfterBehavior NotAfterBehavior = iota + TruncateNotAfterBehavior + PermitNotAfterBehavior +) + +var notAfterBehaviorNames = map[NotAfterBehavior]string{ + ErrNotAfterBehavior: "err", + TruncateNotAfterBehavior: "truncate", + PermitNotAfterBehavior: "permit", +} + +func (n NotAfterBehavior) String() string { + if name, ok := notAfterBehaviorNames[n]; ok && len(name) > 0 { + return name + } + + return "unknown" +} + type CAInfoBundle struct { ParsedCertBundle - URLs *URLEntries + URLs *URLEntries + LeafNotAfterBehavior NotAfterBehavior } func (b *CAInfoBundle) GetCAChain() []*CertBlock { @@ -675,13 +721,7 @@ func (b *CAInfoBundle) GetCAChain() []*CertBlock { (len(b.Certificate.AuthorityKeyId) == 0 && !bytes.Equal(b.Certificate.RawIssuer, b.Certificate.RawSubject)) { - chain = append(chain, &CertBlock{ - Certificate: b.Certificate, - Bytes: b.CertificateBytes, - }) - if b.CAChain != nil && len(b.CAChain) > 0 { - chain = append(chain, b.CAChain...) - } + chain = b.GetFullChain() } return chain @@ -690,10 +730,14 @@ func (b *CAInfoBundle) GetCAChain() []*CertBlock { func (b *CAInfoBundle) GetFullChain() []*CertBlock { var chain []*CertBlock - chain = append(chain, &CertBlock{ - Certificate: b.Certificate, - Bytes: b.CertificateBytes, - }) + // Some bundles already include the root included in the chain, + // so don't include it twice. + if len(b.CAChain) == 0 || !bytes.Equal(b.CAChain[0].Bytes, b.CertificateBytes) { + chain = append(chain, &CertBlock{ + Certificate: b.Certificate, + Bytes: b.CertificateBytes, + }) + } if len(b.CAChain) > 0 { chain = append(chain, b.CAChain...) @@ -738,6 +782,7 @@ type CreationParameters struct { PolicyIdentifiers []string BasicConstraintsValidForNonCA bool SignatureBits int + ForceAppendCaChain bool // Only used when signing a CA cert UseCSRValues bool @@ -825,3 +870,141 @@ func AddKeyUsages(data *CreationBundle, certTemplate *x509.Certificate) { certTemplate.ExtKeyUsage = append(certTemplate.ExtKeyUsage, x509.ExtKeyUsageMicrosoftKernelCodeSigning) } } + +// SetParsedPrivateKey sets the private key parameters on the bundle +func (p *KeyBundle) SetParsedPrivateKey(privateKey crypto.Signer, privateKeyType PrivateKeyType, privateKeyBytes []byte) { + p.PrivateKey = privateKey + p.PrivateKeyType = privateKeyType + p.PrivateKeyBytes = privateKeyBytes +} + +func (p *KeyBundle) ToPrivateKeyPemString() (string, error) { + block := pem.Block{} + + if p.PrivateKeyBytes != nil && len(p.PrivateKeyBytes) > 0 { + block.Bytes = p.PrivateKeyBytes + switch p.PrivateKeyType { + case RSAPrivateKey: + block.Type = "RSA PRIVATE KEY" + case ECPrivateKey: + block.Type = "EC PRIVATE KEY" + default: + block.Type = "PRIVATE KEY" + } + privateKeyPemString := strings.TrimSpace(string(pem.EncodeToMemory(&block))) + return privateKeyPemString, nil + } + + return "", errutil.InternalError{Err: "No Private Key Bytes to Wrap"} +} + +// PolicyIdentifierWithQualifierEntry Structure for Internal Storage +type PolicyIdentifierWithQualifierEntry struct { + PolicyIdentifierOid string `json:"oid",mapstructure:"oid"` + CPS string `json:"cps,omitempty",mapstructure:"cps"` + Notice string `json:"notice,omitempty",mapstructure:"notice"` +} + +// GetPolicyIdentifierFromString parses out the internal structure of a Policy Identifier +func GetPolicyIdentifierFromString(policyIdentifier string) (*PolicyIdentifierWithQualifierEntry, error) { + if policyIdentifier == "" { + return nil, nil + } + entry := &PolicyIdentifierWithQualifierEntry{} + // Either a OID, or a JSON Entry: First check OID: + _, err := StringToOid(policyIdentifier) + if err == nil { + entry.PolicyIdentifierOid = policyIdentifier + return entry, nil + } + // Now Check If JSON Entry + jsonErr := json.Unmarshal([]byte(policyIdentifier), &entry) + if jsonErr != nil { // Neither, if we got here + return entry, errors.New(fmt.Sprintf("Policy Identifier %q is neither a valid OID: %s, Nor JSON Policy Identifier: %s", policyIdentifier, err.Error(), jsonErr.Error())) + } + return entry, nil +} + +// Policy Identifier with Qualifier Structure for ASN Marshalling: + +var policyInformationOid = asn1.ObjectIdentifier{2, 5, 29, 32} + +type policyInformation struct { + PolicyIdentifier asn1.ObjectIdentifier + Qualifiers []interface{} `asn1:"tag:optional,omitempty"` +} + +var cpsPolicyQualifierID = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 2, 1} + +type cpsUrlPolicyQualifier struct { + PolicyQualifierID asn1.ObjectIdentifier + Qualifier string `asn1:"tag:optional,ia5"` +} + +var userNoticePolicyQualifierID = asn1.ObjectIdentifier{1, 3, 6, 1, 5, 5, 7, 2, 2} + +type userNoticePolicyQualifier struct { + PolicyQualifierID asn1.ObjectIdentifier + Qualifier userNotice +} + +type userNotice struct { + ExplicitText string `asn1:"tag:optional,utf8"` +} + +func createPolicyIdentifierWithQualifier(entry PolicyIdentifierWithQualifierEntry) (*policyInformation, error) { + // Each Policy is Identified by a Unique ID, as designated here: + policyOid, err := StringToOid(entry.PolicyIdentifierOid) + if err != nil { + return nil, err + } + pi := policyInformation{ + PolicyIdentifier: policyOid, + } + if entry.CPS != "" { + qualifier := cpsUrlPolicyQualifier{ + PolicyQualifierID: cpsPolicyQualifierID, + Qualifier: entry.CPS, + } + pi.Qualifiers = append(pi.Qualifiers, qualifier) + } + if entry.Notice != "" { + qualifier := userNoticePolicyQualifier{ + PolicyQualifierID: userNoticePolicyQualifierID, + Qualifier: userNotice{ + ExplicitText: entry.Notice, + }, + } + pi.Qualifiers = append(pi.Qualifiers, qualifier) + } + return &pi, nil +} + +// CreatePolicyInformationExtensionFromStorageStrings parses the stored policyIdentifiers, which might be JSON Policy +// Identifier with Qualifier Entries or String OIDs, and returns an extension if everything parsed correctly, and an +// error if constructing +func CreatePolicyInformationExtensionFromStorageStrings(policyIdentifiers []string) (*pkix.Extension, error) { + var policyInformationList []policyInformation + for _, policyIdentifierStr := range policyIdentifiers { + policyIdentifierEntry, err := GetPolicyIdentifierFromString(policyIdentifierStr) + if err != nil { + return nil, err + } + if policyIdentifierEntry != nil { // Okay to skip empty entries if there is no error + policyInformationStruct, err := createPolicyIdentifierWithQualifier(*policyIdentifierEntry) + if err != nil { + return nil, err + } + policyInformationList = append(policyInformationList, *policyInformationStruct) + } + } + asn1Bytes, err := asn1.Marshal(policyInformationList) + if err != nil { + return nil, err + } + return &pkix.Extension{ + Id: policyInformationOid, + Critical: false, + Value: asn1Bytes, + }, nil +} diff --git a/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/helper/consts/consts.go b/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/helper/consts/consts.go index b10f57a229..c431e2e594 100644 --- a/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/helper/consts/consts.go +++ b/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/helper/consts/consts.go @@ -32,4 +32,6 @@ const ( // ReplicationResolverALPN is the negotiated protocol used for // resolving replicaiton addresses ReplicationResolverALPN = "replication_resolver_v1" + + VaultEnableFilePermissionsCheckEnv = "VAULT_ENABLE_FILE_PERMISSIONS_CHECK" ) diff --git a/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/helper/pluginutil/multiplexing.pb.go b/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/helper/pluginutil/multiplexing.pb.go index fa3357d490..d0ff51e57b 100644 --- a/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/helper/pluginutil/multiplexing.pb.go +++ b/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/helper/pluginutil/multiplexing.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v3.19.3 +// protoc v3.19.4 // source: sdk/helper/pluginutil/multiplexing.proto package pluginutil diff --git a/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/logical/auth.go b/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/logical/auth.go index 7f68bc936e..62707e8195 100644 --- a/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/logical/auth.go +++ b/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/logical/auth.go @@ -8,7 +8,8 @@ import ( ) // Auth is the resulting authentication information that is part of -// Response for credential backends. +// Response for credential backends. It's also attached to Request objects and +// defines the authentication used for the request. This value is audit logged. type Auth struct { LeaseOptions @@ -101,10 +102,28 @@ type Auth struct { // Orphan is set if the token does not have a parent Orphan bool `json:"orphan"` + // PolicyResults is the set of policies that grant the token access to the + // requesting path. + PolicyResults *PolicyResults `json:"policy_results"` + // MFARequirement MFARequirement *MFARequirement `json:"mfa_requirement"` + + // EntityCreated is set to true if an entity is created as part of a login request + EntityCreated bool `json:"entity_created"` } func (a *Auth) GoString() string { return fmt.Sprintf("*%#v", *a) } + +type PolicyResults struct { + Allowed bool `json:"allowed"` + GrantingPolicies []PolicyInfo `json:"granting_policies"` +} + +type PolicyInfo struct { + Name string `json:"name"` + NamespaceId string `json:"namespace_id"` + Type string `json:"type"` +} diff --git a/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/logical/identity.pb.go b/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/logical/identity.pb.go index c472b68a09..4b1a36b398 100644 --- a/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/logical/identity.pb.go +++ b/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/logical/identity.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v3.19.3 +// protoc v3.19.4 // source: sdk/logical/identity.proto package logical diff --git a/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/logical/managed_key.go b/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/logical/managed_key.go index 917d1c5e5a..750459542c 100644 --- a/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/logical/managed_key.go +++ b/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/logical/managed_key.go @@ -40,17 +40,17 @@ type ( type ManagedKeySystemView interface { // WithManagedKeyByName retrieves an instantiated managed key for consumption by the given function. The // provided key can only be used within the scope of that function call - WithManagedKeyByName(ctx context.Context, keyName, mountPoint string, f ManagedKeyConsumer) error + WithManagedKeyByName(ctx context.Context, keyName, backendUUID string, f ManagedKeyConsumer) error // WithManagedKeyByUUID retrieves an instantiated managed key for consumption by the given function. The // provided key can only be used within the scope of that function call - WithManagedKeyByUUID(ctx context.Context, keyUuid, mountPoint string, f ManagedKeyConsumer) error + WithManagedKeyByUUID(ctx context.Context, keyUuid, backendUUID string, f ManagedKeyConsumer) error // WithManagedSigningKeyByName retrieves an instantiated managed signing key for consumption by the given function, // with the same semantics as WithManagedKeyByName - WithManagedSigningKeyByName(ctx context.Context, keyName, mountPoint string, f ManagedSigningKeyConsumer) error + WithManagedSigningKeyByName(ctx context.Context, keyName, backendUUID string, f ManagedSigningKeyConsumer) error // WithManagedSigningKeyByUUID retrieves an instantiated managed signing key for consumption by the given function, // with the same semantics as WithManagedKeyByUUID - WithManagedSigningKeyByUUID(ctx context.Context, keyUuid, mountPoint string, f ManagedSigningKeyConsumer) error + WithManagedSigningKeyByUUID(ctx context.Context, keyUuid, backendUUID string, f ManagedSigningKeyConsumer) error } type ManagedAsymmetricKey interface { diff --git a/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/logical/plugin.pb.go b/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/logical/plugin.pb.go index d4722ce097..1fb53f9a79 100644 --- a/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/logical/plugin.pb.go +++ b/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/logical/plugin.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.27.1 -// protoc v3.19.3 +// protoc v3.19.4 // source: sdk/logical/plugin.proto package logical @@ -27,6 +27,10 @@ type PluginEnvironment struct { // VaultVersion is the version of the Vault server VaultVersion string `protobuf:"bytes,1,opt,name=vault_version,json=vaultVersion,proto3" json:"vault_version,omitempty"` + // VaultVersionPrerelease is the prerelease information of the Vault server + VaultVersionPrerelease string `protobuf:"bytes,2,opt,name=vault_version_prerelease,json=vaultVersionPrerelease,proto3" json:"vault_version_prerelease,omitempty"` + // VaultVersionMetadata is the version metadata of the Vault server + VaultVersionMetadata string `protobuf:"bytes,3,opt,name=vault_version_metadata,json=vaultVersionMetadata,proto3" json:"vault_version_metadata,omitempty"` } func (x *PluginEnvironment) Reset() { @@ -68,18 +72,39 @@ func (x *PluginEnvironment) GetVaultVersion() string { return "" } +func (x *PluginEnvironment) GetVaultVersionPrerelease() string { + if x != nil { + return x.VaultVersionPrerelease + } + return "" +} + +func (x *PluginEnvironment) GetVaultVersionMetadata() string { + if x != nil { + return x.VaultVersionMetadata + } + return "" +} + var File_sdk_logical_plugin_proto protoreflect.FileDescriptor var file_sdk_logical_plugin_proto_rawDesc = []byte{ 0x0a, 0x18, 0x73, 0x64, 0x6b, 0x2f, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x6c, 0x6f, 0x67, 0x69, - 0x63, 0x61, 0x6c, 0x22, 0x38, 0x0a, 0x11, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x45, 0x6e, 0x76, - 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, 0x6c, - 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x28, 0x5a, - 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, - 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x73, 0x64, 0x6b, 0x2f, - 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x63, 0x61, 0x6c, 0x22, 0xa8, 0x01, 0x0a, 0x11, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x45, 0x6e, + 0x76, 0x69, 0x72, 0x6f, 0x6e, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x76, 0x61, 0x75, + 0x6c, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0c, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x38, + 0x0a, 0x18, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, + 0x70, 0x72, 0x65, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x16, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x50, 0x72, + 0x65, 0x72, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x12, 0x34, 0x0a, 0x16, 0x76, 0x61, 0x75, 0x6c, + 0x74, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x14, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x42, 0x28, + 0x5a, 0x26, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, + 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x76, 0x61, 0x75, 0x6c, 0x74, 0x2f, 0x73, 0x64, 0x6b, + 0x2f, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x61, 0x6c, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/logical/plugin.proto b/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/logical/plugin.proto index 5992c21395..f2df6c75d9 100644 --- a/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/logical/plugin.proto +++ b/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/logical/plugin.proto @@ -7,4 +7,10 @@ package logical; message PluginEnvironment { // VaultVersion is the version of the Vault server string vault_version = 1; + + // VaultVersionPrerelease is the prerelease information of the Vault server + string vault_version_prerelease = 2; + + // VaultVersionMetadata is the version metadata of the Vault server + string vault_version_metadata = 3; } diff --git a/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/logical/response_util.go b/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/logical/response_util.go index 92e3483d87..7454189f1d 100644 --- a/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/logical/response_util.go +++ b/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/logical/response_util.go @@ -120,6 +120,8 @@ func RespondErrorCommon(req *Request, resp *Response, err error) (int, error) { statusCode = http.StatusPreconditionFailed case errwrap.Contains(err, ErrPathFunctionalityRemoved.Error()): statusCode = http.StatusNotFound + case errwrap.Contains(err, ErrRelativePath.Error()): + statusCode = http.StatusBadRequest } } diff --git a/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/version/version.go b/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/version/version.go index 1a4521ae61..78b8eb829c 100644 --- a/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/version/version.go +++ b/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/version/version.go @@ -11,6 +11,7 @@ type VersionInfo struct { Version string `json:"version,omitempty"` VersionPrerelease string `json:"version_prerelease,omitempty"` VersionMetadata string `json:"version_metadata,omitempty"` + BuildDate string `json:"build_date,omitempty"` } func GetVersion() *VersionInfo { @@ -29,6 +30,7 @@ func GetVersion() *VersionInfo { Version: ver, VersionPrerelease: rel, VersionMetadata: md, + BuildDate: BuildDate, } } @@ -70,5 +72,9 @@ func (c *VersionInfo) FullVersionNumber(rev bool) string { fmt.Fprintf(&versionString, " (%s)", c.Revision) } + if c.BuildDate != "" { + fmt.Fprintf(&versionString, ", built %s", c.BuildDate) + } + return versionString.String() } diff --git a/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/version/version_base.go b/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/version/version_base.go index 5211c15ba0..fd2cba1207 100644 --- a/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/version/version_base.go +++ b/third_party/VENDOR-LICENSE/github.com/hashicorp/vault/sdk/version/version_base.go @@ -5,10 +5,13 @@ var ( GitCommit string GitDescribe string + // The compilation date. This will be filled in by the compiler. + BuildDate string + // Whether cgo is enabled or not; set at build time CgoEnabled bool - Version = "1.10.0" - VersionPrerelease = "dev1" + Version = "1.11.0" + VersionPrerelease = "" VersionMetadata = "" ) diff --git a/third_party/VENDOR-LICENSE/github.com/ktr0731/go-fuzzyfinder/LICENSE b/third_party/VENDOR-LICENSE/github.com/ktr0731/go-fuzzyfinder/LICENSE index a14c474632..2591bc981a 100644 --- a/third_party/VENDOR-LICENSE/github.com/ktr0731/go-fuzzyfinder/LICENSE +++ b/third_party/VENDOR-LICENSE/github.com/ktr0731/go-fuzzyfinder/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2019 ktr0731 +Copyright (c) 2019-2021 ktr0731 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/third_party/VENDOR-LICENSE/github.com/nsf/termbox-go/LICENSE b/third_party/VENDOR-LICENSE/github.com/nsf/termbox-go/LICENSE new file mode 100644 index 0000000000..d9bc068ce7 --- /dev/null +++ b/third_party/VENDOR-LICENSE/github.com/nsf/termbox-go/LICENSE @@ -0,0 +1,19 @@ +Copyright (C) 2012 termbox-go authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/tektoncd/pipeline/test/diff/print.go b/vendor/github.com/tektoncd/pipeline/test/diff/print.go new file mode 100644 index 0000000000..f38803c348 --- /dev/null +++ b/vendor/github.com/tektoncd/pipeline/test/diff/print.go @@ -0,0 +1,27 @@ +/* +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 diff + +import "fmt" + +// PrintWantGot takes a diff string generated by cmp.Diff and returns it +// in a consistent format for reuse across all of our tests. This +// func assumes that the order of arguments passed to cmp.Diff was +// (want, got) or, in other words, the expectedResult then the actualResult. +func PrintWantGot(diff string) string { + return fmt.Sprintf("(-want, +got): %s", diff) +} diff --git a/vendor/github.com/tektoncd/pipeline/test/parse/yaml.go b/vendor/github.com/tektoncd/pipeline/test/parse/yaml.go new file mode 100644 index 0000000000..6693a6d124 --- /dev/null +++ b/vendor/github.com/tektoncd/pipeline/test/parse/yaml.go @@ -0,0 +1,151 @@ +/* + Copyright 2021 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 parse + +import ( + "testing" + + "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1alpha1" + resourcev1alpha1 "github.com/tektoncd/pipeline/pkg/apis/resource/v1alpha1" + + "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" + "github.com/tektoncd/pipeline/pkg/client/clientset/versioned/scheme" + "k8s.io/apimachinery/pkg/runtime" +) + +// MustParseTaskRun takes YAML and parses it into a *v1beta1.TaskRun +func MustParseTaskRun(t *testing.T, yaml string) *v1beta1.TaskRun { + var tr v1beta1.TaskRun + yaml = `apiVersion: tekton.dev/v1beta1 +kind: TaskRun +` + yaml + mustParseYAML(t, yaml, &tr) + return &tr +} + +// MustParseAlphaTaskRun takes YAML and parses it into a *v1alpha1.TaskRun +func MustParseAlphaTaskRun(t *testing.T, yaml string) *v1alpha1.TaskRun { + var tr v1alpha1.TaskRun + yaml = `apiVersion: tekton.dev/v1alpha1 +kind: TaskRun +` + yaml + mustParseYAML(t, yaml, &tr) + return &tr +} + +// MustParseRun takes YAML and parses it into a *v1alpha1.Run +func MustParseRun(t *testing.T, yaml string) *v1alpha1.Run { + var r v1alpha1.Run + yaml = `apiVersion: tekton.dev/v1alpha1 +kind: Run +` + yaml + mustParseYAML(t, yaml, &r) + return &r +} + +// MustParseTask takes YAML and parses it into a *v1beta1.Task +func MustParseTask(t *testing.T, yaml string) *v1beta1.Task { + var task v1beta1.Task + yaml = `apiVersion: tekton.dev/v1beta1 +kind: Task +` + yaml + mustParseYAML(t, yaml, &task) + return &task +} + +// MustParseClusterTask takes YAML and parses it into a *v1beta1.ClusterTask +func MustParseClusterTask(t *testing.T, yaml string) *v1beta1.ClusterTask { + var clusterTask v1beta1.ClusterTask + yaml = `apiVersion: tekton.dev/v1beta1 +kind: ClusterTask +` + yaml + mustParseYAML(t, yaml, &clusterTask) + return &clusterTask +} + +// MustParseAlphaTask takes YAML and parses it into a *v1alpha1.Task +func MustParseAlphaTask(t *testing.T, yaml string) *v1alpha1.Task { + var task v1alpha1.Task + yaml = `apiVersion: tekton.dev/v1alpha1 +kind: Task +` + yaml + mustParseYAML(t, yaml, &task) + return &task +} + +// MustParsePipelineRun takes YAML and parses it into a *v1beta1.PipelineRun +func MustParsePipelineRun(t *testing.T, yaml string) *v1beta1.PipelineRun { + var pr v1beta1.PipelineRun + yaml = `apiVersion: tekton.dev/v1beta1 +kind: PipelineRun +` + yaml + mustParseYAML(t, yaml, &pr) + return &pr +} + +// MustParseAlphaPipelineRun takes YAML and parses it into a *v1alpha1.PipelineRun +func MustParseAlphaPipelineRun(t *testing.T, yaml string) *v1alpha1.PipelineRun { + var pr v1alpha1.PipelineRun + yaml = `apiVersion: tekton.dev/v1alpha1 +kind: PipelineRun +` + yaml + mustParseYAML(t, yaml, &pr) + return &pr +} + +// MustParsePipeline takes YAML and parses it into a *v1beta1.Pipeline +func MustParsePipeline(t *testing.T, yaml string) *v1beta1.Pipeline { + var pipeline v1beta1.Pipeline + yaml = `apiVersion: tekton.dev/v1beta1 +kind: Pipeline +` + yaml + mustParseYAML(t, yaml, &pipeline) + return &pipeline +} + +// MustParseAlphaPipeline takes YAML and parses it into a *v1alpha1.Pipeline +func MustParseAlphaPipeline(t *testing.T, yaml string) *v1alpha1.Pipeline { + var pipeline v1alpha1.Pipeline + yaml = `apiVersion: tekton.dev/v1alpha1 +kind: Pipeline +` + yaml + mustParseYAML(t, yaml, &pipeline) + return &pipeline +} + +// MustParsePipelineResource takes YAML and parses it into a *resourcev1alpha1.PipelineResource +func MustParsePipelineResource(t *testing.T, yaml string) *resourcev1alpha1.PipelineResource { + var resource resourcev1alpha1.PipelineResource + yaml = `apiVersion: tekton.dev/v1alpha1 +kind: PipelineResource +` + yaml + mustParseYAML(t, yaml, &resource) + return &resource +} + +// MustParseCondition takes YAML and parses it into a *v1alpha1.Condition +func MustParseCondition(t *testing.T, yaml string) *v1alpha1.Condition { + var cond v1alpha1.Condition + yaml = `apiVersion: tekton.dev/v1alpha1 +kind: Condition +` + yaml + mustParseYAML(t, yaml, &cond) + return &cond +} + +func mustParseYAML(t *testing.T, yaml string, i runtime.Object) { + if _, _, err := scheme.Codecs.UniversalDeserializer().Decode([]byte(yaml), nil, i); err != nil { + t.Fatalf("mustParseYAML (%s): %v", yaml, err) + } +} diff --git a/vendor/modules.txt b/vendor/modules.txt index b55e7e189a..f3c7449ae5 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1419,6 +1419,8 @@ github.com/tektoncd/pipeline/pkg/remote github.com/tektoncd/pipeline/pkg/remote/oci github.com/tektoncd/pipeline/pkg/substitution github.com/tektoncd/pipeline/test +github.com/tektoncd/pipeline/test/diff +github.com/tektoncd/pipeline/test/parse github.com/tektoncd/pipeline/test/v1alpha1 # github.com/tektoncd/plumbing v0.0.0-20220329085922-d765a5cba75f ## explicit; go 1.13