refactor: output logs for completed containers

Previously, a container that exited immediately would just show an error message, which is probably not what we want.

If the pod has exited, we will display the logs on stdout for the user and then exit appropriately.

This change also refactors how log streaming works so that we respect exiting when the stream has no content (such as when the container has exited). Previously, the container would just hang around forever due to not being properly canceled. Due to this refactor, the prefix is now split out into a separate writer.
This commit is contained in:
Jose Diaz-Gonzalez
2024-11-04 02:49:20 -05:00
parent 2368161132
commit ec41dd2e70
4 changed files with 211 additions and 106 deletions

View File

@@ -2,6 +2,7 @@ package common
import (
"fmt"
"io"
"os"
"strconv"
"strings"
@@ -46,6 +47,30 @@ func (w *writer) Write(bytes []byte) (int, error) {
return len(bytes), nil
}
// PrefixingWriter is a writer that prefixes all writes with a given prefix
type PrefixingWriter struct {
Prefix []byte
Writer io.Writer
}
// Write writes the given bytes to the writer with the prefix
func (pw *PrefixingWriter) Write(p []byte) (int, error) {
if len(p) == 0 {
return 0, nil
}
// Perform an "atomic" write of a prefix and p to make sure that it doesn't interleave
// sub-line when used concurrently with io.PipeWrite.
n, err := pw.Writer.Write(append(pw.Prefix, p...))
if n > len(p) {
// To comply with the io.Writer interface requirements we must
// return a number of bytes written from p (0 <= n <= len(p)),
// so we are ignoring the length of the prefix here.
return len(p), err
}
return n, err
}
// LogFail is the failure log formatter
// prints text to stderr and exits with status 1
func LogFail(text string) {