diff --git a/pkg/kubelet/dockertools/docker.go b/pkg/kubelet/dockertools/docker.go index 1413681cb6f..999934ac272 100644 --- a/pkg/kubelet/dockertools/docker.go +++ b/pkg/kubelet/dockertools/docker.go @@ -205,6 +205,9 @@ func GetRecentDockerContainersWithNameAndUUID(client DockerInterface, podFullNam } // GetKubeletDockerContainerLogs returns logs of specific container +// By default the function will return snapshot of the container log +// Log streaming is possible if 'follow' param is set to true +// Log tailing is possible when number of tailed lines are set and only if 'follow' is false func GetKubeletDockerContainerLogs(client DockerInterface, containerID, tail string, follow bool, writer io.Writer) (err error) { opts := docker.LogsOptions{ Container: containerID, @@ -214,9 +217,10 @@ func GetKubeletDockerContainerLogs(client DockerInterface, containerID, tail str ErrorStream: writer, Timestamps: true, RawTerminal: true, + Follow: follow, } - if opts.Follow = follow; follow == false { + if !follow { opts.Tail = tail } diff --git a/pkg/kubelet/handlers.go b/pkg/kubelet/handlers.go index 2936b963176..f2d8a3f3d3d 100644 --- a/pkg/kubelet/handlers.go +++ b/pkg/kubelet/handlers.go @@ -98,17 +98,17 @@ func (h *httpActionHandler) Run(podFullName, uuid string, container *api.Contain return err } -// flusherWriter provides wrapper for responseWriter with HTTP streaming capabilities +// FlusherWriter provides wrapper for responseWriter with HTTP streaming capabilities type FlushWriter struct { flusher http.Flusher writer io.Writer } -// Write is a flushWriter implementation of the io.Writer that sends any buffered data to the client. +// Write is a FlushWriter implementation of the io.Writer that sends any buffered data to the client. func (fw *FlushWriter) Write(p []byte) (n int, err error) { n, err = fw.writer.Write(p) if err != nil { - return n, err + return } if fw.flusher != nil { fw.flusher.Flush() diff --git a/pkg/kubelet/server.go b/pkg/kubelet/server.go index c910f0cb86d..0174de37341 100644 --- a/pkg/kubelet/server.go +++ b/pkg/kubelet/server.go @@ -145,7 +145,7 @@ func (s *Server) handleContainers(w http.ResponseWriter, req *http.Request) { } -// handleContainerLogs handles containerLogs request againts the Kubelet +// handleContainerLogs handles containerLogs request against the Kubelet func (s *Server) handleContainerLogs(w http.ResponseWriter, req *http.Request) { defer req.Body.Close() u, err := url.ParseRequestURI(req.RequestURI) @@ -153,27 +153,21 @@ func (s *Server) handleContainerLogs(w http.ResponseWriter, req *http.Request) { s.error(w, err) return } + uriValues := u.Query() - - containerID := uriValues.Get("containerID") - follow := uriValues.Get("follow") == "1" - tail := uriValues.Get("tail") - + containerID := uriValues.Get("containerid") if len(containerID) == 0 { - w.WriteHeader(http.StatusBadRequest) - http.Error(w, "Missing 'containerID=' query entry.", http.StatusBadRequest) + http.Error(w, `{"message": "Missing containerID= query entry."}`, http.StatusBadRequest) return } - logWriter := httplog.LogOf(req, w) - w = httplog.Unlogged(w) + follow, _ := strconv.ParseBool(uriValues.Get("follow")) + tail := uriValues.Get("tail") + fw := FlushWriter{writer: w} if flusher, ok := w.(http.Flusher); ok { fw.flusher = flusher - } else { - logWriter.Addf("unable to get Flusher") - http.NotFound(w, req) - return } + w.Header().Set("Transfer-Encoding", "chunked") w.WriteHeader(http.StatusOK) err = s.host.GetKubeletContainerLogs(containerID, tail, follow, &fw) diff --git a/pkg/kubelet/server_test.go b/pkg/kubelet/server_test.go index baec2523ecd..8c7abe410f6 100644 --- a/pkg/kubelet/server_test.go +++ b/pkg/kubelet/server_test.go @@ -45,10 +45,6 @@ type fakeKubelet struct { containerLogsFunc func(containerID, tail string, follow bool, writer io.Writer) error } -func (fk *fakeKubelet) GetKubeletContainerLogs(containerID, tail string, follow bool, writer io.Writer) error { - return fk.containerLogsFunc(containerID, tail, follow, writer) -} - func (fk *fakeKubelet) GetPodInfo(name, uuid string) (api.PodInfo, error) { return fk.infoFunc(name) } @@ -69,6 +65,10 @@ func (fk *fakeKubelet) ServeLogs(w http.ResponseWriter, req *http.Request) { fk.logFunc(w, req) } +func (fk *fakeKubelet) GetKubeletContainerLogs(containerID, tail string, follow bool, writer io.Writer) error { + return fk.containerLogsFunc(containerID, tail, follow, writer) +} + func (fk *fakeKubelet) RunInContainer(podFullName, uuid, containerName string, cmd []string) ([]byte, error) { return fk.runFunc(podFullName, uuid, containerName, cmd) }