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:
@@ -284,6 +284,24 @@ func (p *Pod) FindContainerByName(containerName string) *Container {
|
||||
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.
|
||||
func (p *Pod) IsEmpty() bool {
|
||||
return reflect.DeepEqual(p, &Pod{})
|
||||
|
@@ -1850,6 +1850,23 @@ func (kl *Kubelet) GetPods() []*api.Pod {
|
||||
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) {
|
||||
return kl.podManager.GetPodByFullName(podFullName)
|
||||
}
|
||||
|
@@ -101,6 +101,7 @@ type HostInterface interface {
|
||||
GetRawContainerInfo(containerName string, req *cadvisorApi.ContainerInfoRequest, subcontainers bool) (map[string]*cadvisorApi.ContainerInfo, error)
|
||||
GetCachedMachineInfo() (*cadvisorApi.MachineInfo, error)
|
||||
GetPods() []*api.Pod
|
||||
GetRunningPods() ([]*api.Pod, error)
|
||||
GetPodByName(namespace, name string) (*api.Pod, bool)
|
||||
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
|
||||
@@ -148,6 +149,8 @@ func (s *Server) InstallDebuggingHandlers() {
|
||||
s.mux.HandleFunc("/logs/", s.handleLogs)
|
||||
s.mux.HandleFunc("/containerLogs/", s.handleContainerLogs)
|
||||
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/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
|
||||
func (s *Server) handlePods(w http.ResponseWriter, req *http.Request) {
|
||||
pods := s.host.GetPods()
|
||||
// encodePods creates an api.PodList object from pods and returns the encoded
|
||||
// PodList.
|
||||
func encodePods(pods []*api.Pod) (data []byte, err error) {
|
||||
podList := new(api.PodList)
|
||||
for _, pod := range pods {
|
||||
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 {
|
||||
s.error(w, err)
|
||||
return
|
||||
|
@@ -47,6 +47,7 @@ type fakeKubelet struct {
|
||||
rawInfoFunc func(query *cadvisorApi.ContainerInfoRequest) (map[string]*cadvisorApi.ContainerInfo, error)
|
||||
machineInfoFunc func() (*cadvisorApi.MachineInfo, error)
|
||||
podsFunc func() []*api.Pod
|
||||
runningPodsFunc func() ([]*api.Pod, error)
|
||||
logFunc func(w http.ResponseWriter, req *http.Request)
|
||||
runFunc func(podFullName string, uid types.UID, containerName string, cmd []string) ([]byte, error)
|
||||
containerVersionFunc func() (kubecontainer.Version, error)
|
||||
@@ -91,6 +92,10 @@ func (fk *fakeKubelet) GetPods() []*api.Pod {
|
||||
return fk.podsFunc()
|
||||
}
|
||||
|
||||
func (fk *fakeKubelet) GetRunningPods() ([]*api.Pod, error) {
|
||||
return fk.runningPodsFunc()
|
||||
}
|
||||
|
||||
func (fk *fakeKubelet) ServeLogs(w http.ResponseWriter, req *http.Request) {
|
||||
fk.logFunc(w, req)
|
||||
}
|
||||
|
Reference in New Issue
Block a user