Add a kubelet /runningpods endpoint

/runningpods returns a list of pods currently running on the kubelet. The list
is composed by examining the container runtime, and may be different from the
desired pods to run known by kubelet.

This is useful for tests to verify that pods are indeed deleted on nodes.
This commit is contained in:
Yu-Ju Hong
2015-06-23 16:01:12 -07:00
parent 819b78087c
commit de75a42cb2
4 changed files with 71 additions and 4 deletions

View File

@@ -284,6 +284,24 @@ func (p *Pod) FindContainerByName(containerName string) *Container {
return nil return nil
} }
// ToAPIPod converts Pod to api.Pod. Note that if a field in api.Pod has no
// corresponding field in Pod, the field would not be populated.
func (p *Pod) ToAPIPod() *api.Pod {
var pod api.Pod
pod.UID = p.ID
pod.Name = p.Name
pod.Namespace = p.Namespace
pod.Status = p.Status
for _, c := range p.Containers {
var container api.Container
container.Name = c.Name
container.Image = c.Image
pod.Spec.Containers = append(pod.Spec.Containers, container)
}
return &pod
}
// IsEmpty returns true if the pod is empty. // IsEmpty returns true if the pod is empty.
func (p *Pod) IsEmpty() bool { func (p *Pod) IsEmpty() bool {
return reflect.DeepEqual(p, &Pod{}) return reflect.DeepEqual(p, &Pod{})

View File

@@ -1850,6 +1850,23 @@ func (kl *Kubelet) GetPods() []*api.Pod {
return kl.podManager.GetPods() return kl.podManager.GetPods()
} }
// GetRunningPods returns all pods running on kubelet from looking at the
// container runtime cache. This function converts kubecontainer.Pod to
// api.Pod, so only the fields that exist in both kubecontainer.Pod and
// api.Pod are considered meaningful.
func (kl *Kubelet) GetRunningPods() ([]*api.Pod, error) {
pods, err := kl.runtimeCache.GetPods()
if err != nil {
return nil, err
}
apiPods := make([]*api.Pod, 0, len(pods))
for _, pod := range pods {
apiPods = append(apiPods, pod.ToAPIPod())
}
return apiPods, nil
}
func (kl *Kubelet) GetPodByFullName(podFullName string) (*api.Pod, bool) { func (kl *Kubelet) GetPodByFullName(podFullName string) (*api.Pod, bool) {
return kl.podManager.GetPodByFullName(podFullName) return kl.podManager.GetPodByFullName(podFullName)
} }

View File

@@ -101,6 +101,7 @@ type HostInterface interface {
GetRawContainerInfo(containerName string, req *cadvisorApi.ContainerInfoRequest, subcontainers bool) (map[string]*cadvisorApi.ContainerInfo, error) GetRawContainerInfo(containerName string, req *cadvisorApi.ContainerInfoRequest, subcontainers bool) (map[string]*cadvisorApi.ContainerInfo, error)
GetCachedMachineInfo() (*cadvisorApi.MachineInfo, error) GetCachedMachineInfo() (*cadvisorApi.MachineInfo, error)
GetPods() []*api.Pod GetPods() []*api.Pod
GetRunningPods() ([]*api.Pod, error)
GetPodByName(namespace, name string) (*api.Pod, bool) GetPodByName(namespace, name string) (*api.Pod, bool)
RunInContainer(name string, uid types.UID, container string, cmd []string) ([]byte, error) RunInContainer(name string, uid types.UID, container string, cmd []string) ([]byte, error)
ExecInContainer(name string, uid types.UID, container string, cmd []string, in io.Reader, out, err io.WriteCloser, tty bool) error ExecInContainer(name string, uid types.UID, container string, cmd []string, in io.Reader, out, err io.WriteCloser, tty bool) error
@@ -148,6 +149,8 @@ func (s *Server) InstallDebuggingHandlers() {
s.mux.HandleFunc("/logs/", s.handleLogs) s.mux.HandleFunc("/logs/", s.handleLogs)
s.mux.HandleFunc("/containerLogs/", s.handleContainerLogs) s.mux.HandleFunc("/containerLogs/", s.handleContainerLogs)
s.mux.Handle("/metrics", prometheus.Handler()) s.mux.Handle("/metrics", prometheus.Handler())
// The /runningpods endpoint is used for testing only.
s.mux.HandleFunc("/runningpods", s.handleRunningPods)
s.mux.HandleFunc("/debug/pprof/", pprof.Index) s.mux.HandleFunc("/debug/pprof/", pprof.Index)
s.mux.HandleFunc("/debug/pprof/profile", pprof.Profile) s.mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
@@ -280,14 +283,38 @@ func (s *Server) handleContainerLogs(w http.ResponseWriter, req *http.Request) {
} }
} }
// handlePods returns a list of pod bound to the Kubelet and their spec // encodePods creates an api.PodList object from pods and returns the encoded
func (s *Server) handlePods(w http.ResponseWriter, req *http.Request) { // PodList.
pods := s.host.GetPods() func encodePods(pods []*api.Pod) (data []byte, err error) {
podList := new(api.PodList) podList := new(api.PodList)
for _, pod := range pods { for _, pod := range pods {
podList.Items = append(podList.Items, *pod) podList.Items = append(podList.Items, *pod)
} }
data, err := latest.Codec.Encode(podList) return latest.Codec.Encode(podList)
}
// handlePods returns a list of pods bound to the Kubelet and their spec.
func (s *Server) handlePods(w http.ResponseWriter, req *http.Request) {
pods := s.host.GetPods()
data, err := encodePods(pods)
if err != nil {
s.error(w, err)
return
}
w.Header().Add("Content-type", "application/json")
w.Write(data)
}
// handleRunningPods returns a list of pods running on Kubelet. The list is
// provided by the container runtime, and is different from the list returned
// by handlePods, which is a set of desired pods to run.
func (s *Server) handleRunningPods(w http.ResponseWriter, req *http.Request) {
pods, err := s.host.GetRunningPods()
if err != nil {
s.error(w, err)
return
}
data, err := encodePods(pods)
if err != nil { if err != nil {
s.error(w, err) s.error(w, err)
return return

View File

@@ -47,6 +47,7 @@ type fakeKubelet struct {
rawInfoFunc func(query *cadvisorApi.ContainerInfoRequest) (map[string]*cadvisorApi.ContainerInfo, error) rawInfoFunc func(query *cadvisorApi.ContainerInfoRequest) (map[string]*cadvisorApi.ContainerInfo, error)
machineInfoFunc func() (*cadvisorApi.MachineInfo, error) machineInfoFunc func() (*cadvisorApi.MachineInfo, error)
podsFunc func() []*api.Pod podsFunc func() []*api.Pod
runningPodsFunc func() ([]*api.Pod, error)
logFunc func(w http.ResponseWriter, req *http.Request) logFunc func(w http.ResponseWriter, req *http.Request)
runFunc func(podFullName string, uid types.UID, containerName string, cmd []string) ([]byte, error) runFunc func(podFullName string, uid types.UID, containerName string, cmd []string) ([]byte, error)
containerVersionFunc func() (kubecontainer.Version, error) containerVersionFunc func() (kubecontainer.Version, error)
@@ -91,6 +92,10 @@ func (fk *fakeKubelet) GetPods() []*api.Pod {
return fk.podsFunc() return fk.podsFunc()
} }
func (fk *fakeKubelet) GetRunningPods() ([]*api.Pod, error) {
return fk.runningPodsFunc()
}
func (fk *fakeKubelet) ServeLogs(w http.ResponseWriter, req *http.Request) { func (fk *fakeKubelet) ServeLogs(w http.ResponseWriter, req *http.Request) {
fk.logFunc(w, req) fk.logFunc(w, req)
} }