Skip to content

Commit

Permalink
Add support for Pipeline minimal embedded status
Browse files Browse the repository at this point in the history
Fixes tektoncd#1618

Signed-off-by: Andrew Bayer <[email protected]>
  • Loading branch information
abayer committed Jun 29, 2022
1 parent a7a818a commit 7123767
Show file tree
Hide file tree
Showing 10 changed files with 804 additions and 61 deletions.
58 changes: 36 additions & 22 deletions pkg/cmd/pipelinerun/logs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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,
},
Expand Down Expand Up @@ -307,7 +308,7 @@ func TestPipelinerunLogs(t *testing.T) {
Namespace: ns,
Name: tr2Name,
},
Spec: v1alpha1.TaskRunSpec{
Spec: v1beta1.TaskRunSpec{
TaskRef: &v1beta1.TaskRef{
Name: task2Name,
},
Expand Down Expand Up @@ -347,23 +348,36 @@ 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",
},
},
},
},
Status: duckv1beta1.Status{
Expand All @@ -377,23 +391,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,
},
},
Expand Down Expand Up @@ -532,19 +546,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"
Expand Down
96 changes: 92 additions & 4 deletions pkg/pipelinerun/pipelinerun.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -71,16 +73,28 @@ 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 {
fmt.Fprintf(os.Stderr, "Failed to list pipelineruns from %s namespace \n", ns)
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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
}
Loading

0 comments on commit 7123767

Please sign in to comment.