Allow clients to request most recent container logs

Many users attempt to use 'kubectl logs' in order to find the logs
for a container, but receive no logs or an error telling them their
container is not running. The fix in this case is to run with '--previous',
but  this does not match user expectations for the logs command.

This commit changes the behavior of the Kubelet to return the logs of
the currently running container or the previous running container unless
the user provides the "previous" flag. If the user specifies "follow"
the logs of the most recent container will be displayed, and if it is
a terminated container the logs will come to an end (the user can
repeatedly invoke 'kubectl logs --follow' and see the same output).

Clean up error messages in the kubelet log path to be consistent and
give users a more predictable experience.

Have the Kubelet return 400 on invalid requests
This commit is contained in:
Clayton Coleman
2016-01-28 22:27:56 -05:00
parent 8448b60f51
commit d6d4a17db6
3 changed files with 89 additions and 62 deletions

View File

@@ -24,6 +24,7 @@ import (
"net"
"net/http"
"net/http/pprof"
"reflect"
"strconv"
"strings"
"sync"
@@ -416,7 +417,7 @@ func (s *Server) getContainerLogs(request *restful.Request, response *restful.Re
pod, ok := s.host.GetPodByName(podNamespace, podID)
if !ok {
response.WriteError(http.StatusNotFound, fmt.Errorf("Pod %q does not exist", podID))
response.WriteError(http.StatusNotFound, fmt.Errorf("pod %q does not exist\n", podID))
return
}
// Check if containerName is valid.
@@ -427,12 +428,12 @@ func (s *Server) getContainerLogs(request *restful.Request, response *restful.Re
}
}
if !containerExists {
response.WriteError(http.StatusNotFound, fmt.Errorf("Container %q not found in Pod %q", containerName, podID))
response.WriteError(http.StatusNotFound, fmt.Errorf("container %q not found in pod %q\n", containerName, podID))
return
}
if _, ok := response.ResponseWriter.(http.Flusher); !ok {
response.WriteError(http.StatusInternalServerError, fmt.Errorf("unable to convert %v into http.Flusher", response))
response.WriteError(http.StatusInternalServerError, fmt.Errorf("unable to convert %v into http.Flusher, cannot show logs\n", reflect.TypeOf(response)))
return
}
fw := flushwriter.Wrap(response.ResponseWriter)
@@ -442,7 +443,7 @@ func (s *Server) getContainerLogs(request *restful.Request, response *restful.Re
response.Header().Set("Transfer-Encoding", "chunked")
if err := s.host.GetKubeletContainerLogs(kubecontainer.GetPodFullName(pod), containerName, logOptions, fw, fw); err != nil {
if err != limitwriter.ErrMaximumWrite {
response.WriteError(http.StatusInternalServerError, err)
response.WriteError(http.StatusBadRequest, err)
}
return
}