Skip to content

Commit

Permalink
Bug 1771549: oc debug pod logs to stderr if container exit code != 0
Browse files Browse the repository at this point in the history
  • Loading branch information
sallyom committed Feb 3, 2020
1 parent 686b1c6 commit 7707ef9
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 20 deletions.
62 changes: 50 additions & 12 deletions pkg/cli/debug/debug.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package debug

import (
"bytes"
"context"
"fmt"
"io"
"io/ioutil"
"os"
"reflect"
"strings"
Expand Down Expand Up @@ -453,20 +456,40 @@ func (o *DebugOptions) RunDebug() error {
}
return fmt.Errorf(msg)
// switch to logging output
case err == krun.ErrPodCompleted, err == conditions.ErrContainerTerminated, !o.Attach.Stdin:
return logs.LogsOptions{
Object: pod,
Options: &corev1.PodLogOptions{
Container: o.Attach.ContainerName,
Follow: true,
},
RESTClientGetter: o.RESTClientGetter,
ConsumeRequestFn: logs.DefaultConsumeRequest,
IOStreams: o.IOStreams,
LogsForObject: o.LogsForObject,
}.RunLogs()
case err == krun.ErrPodCompleted, err == conditions.ErrContainerTerminated:
o.logsOptions(pod)
case err == conditions.ErrNonZeroExitCode:
r, w := io.Pipe()
streams := genericclioptions.IOStreams{
In: r,
Out: w,
ErrOut: ioutil.Discard,
}
go func() {
fmt.Fprintf(w, "%v", logs.LogsOptions{
Object: pod,
Options: &corev1.PodLogOptions{
Container: o.Attach.ContainerName,
Follow: true,
},
RESTClientGetter: o.RESTClientGetter,
ConsumeRequestFn: logs.DefaultConsumeRequest,
IOStreams: streams,
LogsForObject: o.LogsForObject,
}.RunLogs())
w.Close()
}()
buf := new(bytes.Buffer)
buf.ReadFrom(r)
trimmed := strings.TrimSuffix(buf.String(), "<nil>")
if trimmed == "" {
return err
}
return fmt.Errorf(trimmed)
case err != nil:
return err
case !o.Attach.Stdin:
o.logsOptions(pod)
default:
// TODO this doesn't do us much good for remote debugging sessions, but until we get a local port
// set up to proxy, this is what we've got.
Expand All @@ -477,6 +500,7 @@ func (o *DebugOptions) RunDebug() error {
// TODO: attach can race with pod completion, allow attach to switch to logs
return o.Attach.Run()
}
return nil
})
}

Expand Down Expand Up @@ -962,6 +986,20 @@ func (o *DebugOptions) approximatePodTemplateForObject(object runtime.Object) (*
return nil, fmt.Errorf("unable to extract pod template from type %v", reflect.TypeOf(object))
}

func (o *DebugOptions) logsOptions(pod *corev1.Pod) error {
return logs.LogsOptions{
Object: pod,
Options: &corev1.PodLogOptions{
Container: o.Attach.ContainerName,
Follow: true,
},
RESTClientGetter: o.RESTClientGetter,
ConsumeRequestFn: logs.DefaultConsumeRequest,
IOStreams: o.IOStreams,
LogsForObject: o.LogsForObject,
}.RunLogs()
}

func setNodeName(template *corev1.PodTemplateSpec, nodeName string) *corev1.PodTemplateSpec {
template.Spec.NodeName = nodeName
return template
Expand Down
13 changes: 5 additions & 8 deletions pkg/helpers/conditions/conditions.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@ package conditions

import (
"fmt"
"os"

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/watch"
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
Expand All @@ -18,6 +16,7 @@ import (
// ErrContainerTerminated is returned by PodContainerRunning in the intermediate
// state where the pod indicates it's still running, but its container is already terminated
var ErrContainerTerminated = fmt.Errorf("container terminated")
var ErrNonZeroExitCode = fmt.Errorf("non-zero exit code")

// PodContainerRunning returns false until the named container has ContainerStatus running (at least once),
// and will return an error if the pod is deleted, runs to completion, or the container pod is not available.
Expand All @@ -34,7 +33,9 @@ func PodContainerRunning(containerName string, coreClient corev1client.CoreV1Int
for _, s := range t.Status.ContainerStatuses {
if s.State.Waiting != nil {
if s.State.Waiting.Reason == "CreateContainerError" {
klog.V(0).Info(s.State.Waiting.Message)
if s.State.Waiting.Message != "" {
klog.V(0).Info(s.State.Waiting.Message)
}
return false, fmt.Errorf(s.State.Waiting.Message)
}
}
Expand All @@ -45,11 +46,7 @@ func PodContainerRunning(containerName string, coreClient corev1client.CoreV1Int
exitCode := s.State.Terminated.ExitCode
if exitCode != 0 {
klog.V(0).Infof("non-zero exit code(%d) from container %s", exitCode, s.Name)
// delete the existing pod
if err := coreClient.Pods(t.Namespace).Delete(t.Name, metav1.NewDeleteOptions(0)); err != nil && !errors.IsNotFound(err) {
return false, fmt.Errorf("unable to delete existing debug pod %q: %v", s.Name, err)
}
os.Exit(int(exitCode))
return false, ErrNonZeroExitCode
}
}
}
Expand Down

0 comments on commit 7707ef9

Please sign in to comment.