Skip to content

Commit 36cfef7

Browse files
authored
Print logs if Pipeline Run fails (#943)
Signed-off-by: Zbynek Roubalik <[email protected]>
1 parent a91bcc5 commit 36cfef7

File tree

2 files changed

+64
-1
lines changed

2 files changed

+64
-1
lines changed

Diff for: k8s/logs.go

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package k8s
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"io"
7+
8+
corev1 "k8s.io/api/core/v1"
9+
)
10+
11+
// GetPodLogs returns logs from a specified Container in a Pod, if container is empty string,
12+
// then the first container in the pod is selected.
13+
func GetPodLogs(ctx context.Context, namespace, podName, containerName string) (string, error) {
14+
podLogOpts := corev1.PodLogOptions{}
15+
if containerName != "" {
16+
podLogOpts.Container = containerName
17+
}
18+
19+
client, namespace, _ := NewClientAndResolvedNamespace(namespace)
20+
request := client.CoreV1().Pods(namespace).GetLogs(podName, &podLogOpts)
21+
22+
containerLogStream, err := request.Stream(ctx)
23+
if err != nil {
24+
return "", err
25+
}
26+
defer containerLogStream.Close()
27+
28+
buffer := new(bytes.Buffer)
29+
_, err = io.Copy(buffer, containerLogStream)
30+
if err != nil {
31+
return "", err
32+
}
33+
34+
return buffer.String(), nil
35+
}

Diff for: pipelines/tekton/pipeplines_provider.go

+29-1
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,8 @@ func (pp *PipelinesProvider) Run(ctx context.Context, f fn.Function) error {
139139
}
140140

141141
if pr.Status.GetCondition(apis.ConditionSucceeded).Status == corev1.ConditionFalse {
142-
return fmt.Errorf("function pipeline run has failed, please inspect logs of Tekton PipelineRun \"%s\"", pr.Name)
142+
message := getFailedPipelineRunLog(ctx, pr, pp.namespace)
143+
return fmt.Errorf("function pipeline run has failed with message: \n\n%s", message)
143144
}
144145

145146
kClient, err := knative.NewServingClient(pp.namespace)
@@ -251,3 +252,30 @@ func (pp *PipelinesProvider) watchPipelineRunProgress(pr *v1beta1.PipelineRun) e
251252

252253
return nil
253254
}
255+
256+
// getFailedPipelineRunLog returns log message for a failed PipelineRun,
257+
// returns log from a container where the failing TaskRun is running, if available.
258+
func getFailedPipelineRunLog(ctx context.Context, pr *v1beta1.PipelineRun, namespace string) string {
259+
// Reason "Failed" usually means there is a specific failure in some step,
260+
// let's find the failed step and try to get log directly from the container.
261+
// If we are not able to get the container's log, we return the generic message from the PipelineRun.Status.
262+
message := pr.Status.GetCondition(apis.ConditionSucceeded).Message
263+
if pr.Status.GetCondition(apis.ConditionSucceeded).Reason == "Failed" {
264+
for _, t := range pr.Status.TaskRuns {
265+
if t.Status.GetCondition(apis.ConditionSucceeded).Status == corev1.ConditionFalse {
266+
for _, s := range t.Status.Steps {
267+
if s.Terminated != nil && s.Terminated.ExitCode == 1 {
268+
podLogs, err := k8s.GetPodLogs(ctx, namespace, t.Status.PodName, s.ContainerName)
269+
if err == nil {
270+
return podLogs
271+
}
272+
return message
273+
}
274+
}
275+
276+
}
277+
}
278+
}
279+
280+
return message
281+
}

0 commit comments

Comments
 (0)