Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Making taskrun logs interactive. #491

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions docs/cmd/tkn_taskrun_logs.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@ tkn taskrun logs -f foo -n bar
### Options

```
-a, --all show all logs including init steps injected by tekton
-f, --follow stream live logs
-h, --help help for logs
-a, --all show all logs including init steps injected by tekton
-f, --follow stream live logs
-h, --help help for logs
--limit int lists number of taskruns (default 5)
```

### Options inherited from parent commands
Expand Down
4 changes: 4 additions & 0 deletions docs/man/man1/tkn-taskrun-logs.1
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ Show taskruns logs
\fB\-h\fP, \fB\-\-help\fP[=false]
help for logs

.PP
\fB\-\-limit\fP=5
lists number of taskruns


.SH OPTIONS INHERITED FROM PARENT COMMANDS
.PP
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/pipelinerun/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,5 +129,5 @@ func askRunName(opts *options.LogOptions) error {
return nil
}

return opts.Ask("pipelinerun", prs)
return opts.Ask(options.ResourceNamePipelineRun, prs)
}
5 changes: 3 additions & 2 deletions pkg/cmd/task/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/tektoncd/cli/pkg/cmd/taskrun"
"github.com/tektoncd/cli/pkg/flags"
"github.com/tektoncd/cli/pkg/helper/labels"
"github.com/tektoncd/cli/pkg/helper/options"
"github.com/tektoncd/cli/pkg/helper/params"
"github.com/tektoncd/cli/pkg/helper/task"
validate "github.com/tektoncd/cli/pkg/helper/validate"
Expand Down Expand Up @@ -244,14 +245,14 @@ func startTask(opt startOptions, args []string) error {
}

fmt.Fprintf(opt.stream.Out, "Waiting for logs to be available...\n")
runLogOpts := &taskrun.LogOptions{
runLogOpts := &options.LogOptions{
TaskrunName: trCreated.Name,
Stream: opt.stream,
Follow: true,
Params: opt.cliparams,
AllSteps: false,
}
return runLogOpts.Run()
return taskrun.Run(runLogOpts)
}

func mergeRes(r []v1alpha1.TaskResourceBinding, optRes []string) ([]v1alpha1.TaskResourceBinding, error) {
Expand Down
73 changes: 45 additions & 28 deletions pkg/cmd/taskrun/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,23 @@ package taskrun

import (
"fmt"
"strings"

"github.com/spf13/cobra"
"github.com/tektoncd/cli/pkg/cli"
"github.com/tektoncd/cli/pkg/helper/options"
"github.com/tektoncd/cli/pkg/helper/pods"
"github.com/tektoncd/cli/pkg/helper/pods/stream"
trlist "github.com/tektoncd/cli/pkg/helper/taskrun/list"
validate "github.com/tektoncd/cli/pkg/helper/validate"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const (
msgTRNotFoundErr = "Unable to get Taskrun"
)

// LogOptions provides options on what logs to fetch. An empty LogOptions
// implies fetching all logs including init steps
type LogOptions struct {
TaskrunName string
AllSteps bool
Follow bool
Stream *cli.Stream
Params cli.Params
Streamer stream.NewStreamerFunc
}

func logCommand(p cli.Params) *cobra.Command {
opts := LogOptions{Params: p}
opts := &options.LogOptions{Params: p}
eg := `
# show the logs of TaskRun named "foo" from the namespace "bar"
tkn taskrun logs foo -n bar
Expand All @@ -56,9 +48,11 @@ tkn taskrun logs -f foo -n bar
Annotations: map[string]string{
"commandType": "main",
},
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
opts.TaskrunName = args[0]
if len(args) != 0 {
opts.TaskrunName = args[0]
}

opts.Stream = &cli.Stream{
Out: cmd.OutOrStdout(),
Err: cmd.OutOrStderr(),
Expand All @@ -68,47 +62,70 @@ tkn taskrun logs -f foo -n bar
return err
}

return opts.Run()
return Run(opts)
},
}

c.Flags().BoolVarP(&opts.AllSteps, "all", "a", false, "show all logs including init steps injected by tekton")
c.Flags().BoolVarP(&opts.Follow, "follow", "f", false, "stream live logs")
c.Flags().IntVarP(&opts.Limit, "limit", "", 5, "lists number of taskruns")

_ = c.MarkZshCompPositionalArgumentCustom(1, "__tkn_get_taskrun")
return c
}

func (lo *LogOptions) Run() error {
if lo.TaskrunName == "" {
return fmt.Errorf("missing mandatory argument taskrun name")
func Run(opts *options.LogOptions) error {
if opts.TaskrunName == "" {
if err := askRunName(opts); err != nil {
return err
}
}

streamer := pods.NewStream
if lo.Streamer != nil {
streamer = lo.Streamer
if opts.Streamer != nil {
streamer = opts.Streamer
}

cs, err := lo.Params.Clients()
cs, err := opts.Params.Clients()
if err != nil {
return err
}

lr := &LogReader{
Run: lo.TaskrunName,
Ns: lo.Params.Namespace(),
Run: opts.TaskrunName,
Ns: opts.Params.Namespace(),
Clients: cs,
Streamer: streamer,
Stream: lo.Stream,
Follow: lo.Follow,
AllSteps: lo.AllSteps,
Stream: opts.Stream,
Follow: opts.Follow,
AllSteps: opts.AllSteps,
}

logC, errC, err := lr.Read()
if err != nil {
return err
}

NewLogWriter().Write(lo.Stream, logC, errC)
NewLogWriter().Write(opts.Stream, logC, errC)
return nil
}

func askRunName(opts *options.LogOptions) error {
lOpts := metav1.ListOptions{}

trs, err := trlist.GetAllTaskRuns(opts.Params, lOpts, opts.Limit)
if err != nil {
return err
}

if len(trs) == 0 {
return fmt.Errorf("No taskruns found")
}

if len(trs) == 1 {
opts.TaskrunName = strings.Fields(trs[0])[0]
return nil
}

return opts.Ask(options.ResourceNameTaskRun, trs)
}
96 changes: 88 additions & 8 deletions pkg/cmd/taskrun/logs_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,15 @@ import (

"github.com/jonboulle/clockwork"
"github.com/tektoncd/cli/pkg/cli"
"github.com/tektoncd/cli/pkg/helper/options"
"github.com/tektoncd/cli/pkg/helper/pods/fake"
"github.com/tektoncd/cli/pkg/helper/pods/stream"
"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/reconciler/pipelinerun/resources"
pipelinetest "github.com/tektoncd/pipeline/test"
ptest "github.com/tektoncd/pipeline/test"
tb "github.com/tektoncd/pipeline/test/builder"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -62,11 +64,88 @@ func TestLog_invalid_namespace(t *testing.T) {
}

func TestLog_no_taskrun_arg(t *testing.T) {
c := Command(&test.Params{})
cs, _ := test.SeedTestData(t, pipelinetest.Data{
Namespaces: []*corev1.Namespace{
{
ObjectMeta: metav1.ObjectMeta{
Name: "ns",
},
},
},
})

_, err := test.ExecuteCommand(c, "logs", "-n", "ns")
if err == nil {
t.Error("Expecting an error but it's empty")
cs2, _ := test.SeedTestData(t, pipelinetest.Data{
Tasks: []*v1alpha1.Task{
tb.Task("task", "ns", cb.TaskCreationTime(clockwork.NewFakeClock().Now())),
},
TaskRuns: []*v1alpha1.TaskRun{
tb.TaskRun("taskrun1", "ns",
tb.TaskRunLabel("tekton.dev/task", "task"),
tb.TaskRunSpec(tb.TaskRunTaskRef("task")),
tb.TaskRunStatus(
tb.PodName("pod"),
tb.TaskRunStartTime(clockwork.NewFakeClock().Now()),
tb.StatusCondition(apis.Condition{
Status: corev1.ConditionTrue,
Reason: resources.ReasonSucceeded,
}),
tb.StepState(
cb.StepName("step1"),
tb.StateTerminated(0),
),
),
),
},
Namespaces: []*corev1.Namespace{
{
ObjectMeta: metav1.ObjectMeta{
Name: "ns",
},
},
},
Pods: []*corev1.Pod{
tb.Pod("pod", "ns",
tb.PodSpec(
tb.PodContainer("step1", "step1:latest"),
),
cb.PodStatus(
cb.PodPhase(corev1.PodSucceeded),
),
),
},
})

testParams := []struct {
name string
input ptest.Clients
wantError bool
}{
{
name: "found no data",
input: cs,
wantError: true,
},
{
name: "found single data",
input: cs2,
wantError: false,
},
}

for _, tp := range testParams {
t.Run(tp.name, func(t *testing.T) {
trlo := logOpts("", "ns", tp.input, fake.Streamer(fake.Logs()), false, false)
_, err := fetchLogs(trlo)
if tp.wantError {
if err == nil {
t.Error("Expecting an error but it's empty")
}
} else {
if err != nil {
t.Errorf("unexpected Error")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
t.Errorf("unexpected Error")
t.Errorf("Unexpected error")

}
}
})
}
}

Expand Down Expand Up @@ -748,27 +827,28 @@ func TestLog_taskrun_follow_mode_no_output_provided(t *testing.T) {
test.AssertOutput(t, expected, err.Error())
}

func logOpts(run, ns string, cs pipelinetest.Clients, streamer stream.NewStreamerFunc, allSteps bool, follow bool) *LogOptions {
func logOpts(run, ns string, cs pipelinetest.Clients, streamer stream.NewStreamerFunc, allSteps bool, follow bool) *options.LogOptions {
p := test.Params{
Kube: cs.Kube,
Tekton: cs.Pipeline,
}
p.SetNamespace(ns)

return &LogOptions{
return &options.LogOptions{
TaskrunName: run,
AllSteps: allSteps,
Follow: follow,
Params: &p,
Streamer: streamer,
Limit: 5,
}
}

func fetchLogs(lo *LogOptions) (string, error) {
func fetchLogs(lo *options.LogOptions) (string, error) {
out := new(bytes.Buffer)
lo.Stream = &cli.Stream{Out: out, Err: out}

err := lo.Run()
err := Run(lo)

return out.String(), err
}
4 changes: 4 additions & 0 deletions pkg/helper/options/logs.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
const (
ResourceNamePipeline = "pipeline"
ResourceNamePipelineRun = "pipelinerun"
ResourceNameTaskRun = "taskrun"
)

type LogOptions struct {
Expand All @@ -36,6 +37,7 @@ type LogOptions struct {
Params cli.Params
PipelineName string
PipelineRunName string
TaskrunName string
Stream *cli.Stream
Streamer stream.NewStreamerFunc
Tasks []string
Expand Down Expand Up @@ -85,6 +87,8 @@ func (opts *LogOptions) Ask(resource string, options []string) error {
opts.PipelineName = ans
case ResourceNamePipelineRun:
opts.PipelineRunName = strings.Fields(ans)[0]
case ResourceNameTaskRun:
opts.TaskrunName = strings.Fields(ans)[0]
}

return nil
Expand Down
Loading