Use I/O stream for provider logs interface

Providers must still update the implementaiton to actually gain any
benefit here, but this makes the provider interface a bit more sane.
This commit is contained in:
Brian Goff
2019-04-15 12:25:51 -07:00
parent ce5f049401
commit 3cc051f7c2
16 changed files with 212 additions and 101 deletions

View File

@@ -29,3 +29,29 @@ func handleError(f handlerFunc) http.HandlerFunc {
}
}
}
func flushOnWrite(w io.Writer) io.Writer {
if fw, ok := w.(writeFlusher); ok {
return &flushWriter{fw}
}
return w
}
type flushWriter struct {
w writeFlusher
}
type writeFlusher interface {
Flush() error
Write([]byte) (int, error)
}
func (fw *flushWriter) Write(p []byte) (int, error) {
n, err := fw.w.Write(p)
if n > 0 {
if err := fw.w.Flush(); err != nil {
return n, err
}
}
return n, err
}

View File

@@ -9,11 +9,13 @@ import (
"github.com/cpuguy83/strongerrors"
"github.com/gorilla/mux"
"github.com/pkg/errors"
"github.com/virtual-kubelet/virtual-kubelet/log"
"github.com/virtual-kubelet/virtual-kubelet/providers"
)
// ContainerLogsBackend is used in place of backend implementations for getting container logs
type ContainerLogsBackend interface {
GetContainerLogs(ctx context.Context, namespace, podName, containerName string, tail int) (string, error)
GetContainerLogs(ctx context.Context, namespace, podName, containerName string, opts providers.ContainerLogOpts) (io.ReadCloser, error)
}
// PodLogsHandlerFunc creates an http handler function from a provider to serve logs from a pod
@@ -40,12 +42,27 @@ func PodLogsHandlerFunc(p ContainerLogsBackend) http.HandlerFunc {
tail = t
}
podsLogs, err := p.GetContainerLogs(ctx, namespace, pod, container, tail)
// TODO(@cpuguy83): support v1.PodLogOptions
// The kubelet decoding here is not straight forward, so this needs to be disected
opts := providers.ContainerLogOpts{
Tail: tail,
}
logs, err := p.GetContainerLogs(ctx, namespace, pod, container, opts)
if err != nil {
return errors.Wrap(err, "error getting container logs?)")
}
if _, err := io.WriteString(w, podsLogs); err != nil {
defer logs.Close()
req.Header.Set("Transfer-Encoding", "chunked")
if _, ok := w.(writeFlusher); !ok {
log.G(ctx).Debug("http response writer does not support flushes")
}
if _, err := io.Copy(flushOnWrite(w), logs); err != nil {
return strongerrors.Unknown(errors.Wrap(err, "error writing response to client"))
}
return nil