Introduce PodStatusResult, and deprecate PodContainerInfo.

This commit is contained in:
Dawn Chen 2015-01-13 18:11:24 -08:00
parent 53bef57b34
commit 15e9fa8a9d
19 changed files with 189 additions and 98 deletions

View File

@ -62,7 +62,7 @@ var (
type fakeKubeletClient struct{} type fakeKubeletClient struct{}
func (fakeKubeletClient) GetPodInfo(host, podNamespace, podID string) (api.PodContainerInfo, error) { func (fakeKubeletClient) GetPodStatus(host, podNamespace, podID string) (api.PodStatusResult, error) {
glog.V(3).Infof("Trying to get container info for %v/%v/%v", host, podNamespace, podID) glog.V(3).Infof("Trying to get container info for %v/%v/%v", host, podNamespace, podID)
// This is a horrible hack to get around the fact that we can't provide // This is a horrible hack to get around the fact that we can't provide
// different port numbers per kubelet... // different port numbers per kubelet...
@ -81,7 +81,7 @@ func (fakeKubeletClient) GetPodInfo(host, podNamespace, podID string) (api.PodCo
default: default:
glog.Fatalf("Can't get info for: '%v', '%v - %v'", host, podNamespace, podID) glog.Fatalf("Can't get info for: '%v', '%v - %v'", host, podNamespace, podID)
} }
return c.GetPodInfo("localhost", podNamespace, podID) return c.GetPodStatus("localhost", podNamespace, podID)
} }
func (fakeKubeletClient) HealthCheck(host string) (health.Status, error) { func (fakeKubeletClient) HealthCheck(host string) (health.Status, error) {
@ -223,7 +223,7 @@ func podsOnMinions(c *client.Client, pods api.PodList) wait.ConditionFunc {
if len(host) == 0 { if len(host) == 0 {
return false, nil return false, nil
} }
if _, err := podInfo.GetPodInfo(host, namespace, id); err != nil { if _, err := podInfo.GetPodStatus(host, namespace, id); err != nil {
return false, nil return false, nil
} }
} }

View File

@ -25,9 +25,9 @@ var Scheme = runtime.NewScheme()
func init() { func init() {
Scheme.AddKnownTypes("", Scheme.AddKnownTypes("",
&PodContainerInfo{},
&PodList{},
&Pod{}, &Pod{},
&PodList{},
&PodStatusResult{},
&ReplicationControllerList{}, &ReplicationControllerList{},
&ReplicationController{}, &ReplicationController{},
&ServiceList{}, &ServiceList{},
@ -55,9 +55,9 @@ func init() {
Scheme.AddKnownTypeWithName("", "ServerOpList", &OperationList{}) Scheme.AddKnownTypeWithName("", "ServerOpList", &OperationList{})
} }
func (*PodContainerInfo) IsAnAPIObject() {}
func (*Pod) IsAnAPIObject() {} func (*Pod) IsAnAPIObject() {}
func (*PodList) IsAnAPIObject() {} func (*PodList) IsAnAPIObject() {}
func (*PodStatusResult) IsAnAPIObject() {}
func (*ReplicationController) IsAnAPIObject() {} func (*ReplicationController) IsAnAPIObject() {}
func (*ReplicationControllerList) IsAnAPIObject() {} func (*ReplicationControllerList) IsAnAPIObject() {}
func (*Service) IsAnAPIObject() {} func (*Service) IsAnAPIObject() {}

View File

@ -418,6 +418,7 @@ type ContainerStatus struct {
type PodInfo map[string]ContainerStatus type PodInfo map[string]ContainerStatus
// PodContainerInfo is a wrapper for PodInfo that can be encode/decoded // PodContainerInfo is a wrapper for PodInfo that can be encode/decoded
// DEPRECATED: Replaced with PodStatusResult
type PodContainerInfo struct { type PodContainerInfo struct {
TypeMeta `json:",inline"` TypeMeta `json:",inline"`
ObjectMeta `json:"metadata,omitempty"` ObjectMeta `json:"metadata,omitempty"`
@ -503,6 +504,15 @@ type PodStatus struct {
Info PodInfo `json:"info,omitempty"` Info PodInfo `json:"info,omitempty"`
} }
// PodStatusResult is a wrapper for PodStatus returned by kubelet that can be encode/decoded
type PodStatusResult struct {
TypeMeta `json:",inline"`
ObjectMeta `json:"metadata,omitempty"`
// Status represents the current information about a pod. This data may not be up
// to date.
Status PodStatus `json:"status,omitempty"`
}
// Pod is a collection of containers, used as either input (create, update) or as output (list, get). // Pod is a collection of containers, used as either input (create, update) or as output (list, get).
type Pod struct { type Pod struct {
TypeMeta `json:",inline"` TypeMeta `json:",inline"`

View File

@ -314,6 +314,30 @@ func init() {
} }
return nil return nil
}, },
func(in *newer.PodStatusResult, out *PodStatusResult, s conversion.Scope) error {
if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil {
return err
}
if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil {
return err
}
if err := s.Convert(&in.Status, &out.State, 0); err != nil {
return err
}
return nil
},
func(in *PodStatusResult, out *newer.PodStatusResult, s conversion.Scope) error {
if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil {
return err
}
if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil {
return err
}
if err := s.Convert(&in.State, &out.Status, 0); err != nil {
return err
}
return nil
},
func(in *newer.ReplicationController, out *ReplicationController, s conversion.Scope) error { func(in *newer.ReplicationController, out *ReplicationController, s conversion.Scope) error {
if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil { if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil {

View File

@ -27,7 +27,7 @@ var Codec = runtime.CodecFor(api.Scheme, "v1beta1")
func init() { func init() {
api.Scheme.AddKnownTypes("v1beta1", api.Scheme.AddKnownTypes("v1beta1",
&Pod{}, &Pod{},
&PodContainerInfo{}, &PodStatusResult{},
&PodList{}, &PodList{},
&ReplicationController{}, &ReplicationController{},
&ReplicationControllerList{}, &ReplicationControllerList{},
@ -57,7 +57,7 @@ func init() {
} }
func (*Pod) IsAnAPIObject() {} func (*Pod) IsAnAPIObject() {}
func (*PodContainerInfo) IsAnAPIObject() {} func (*PodStatusResult) IsAnAPIObject() {}
func (*PodList) IsAnAPIObject() {} func (*PodList) IsAnAPIObject() {}
func (*ReplicationController) IsAnAPIObject() {} func (*ReplicationController) IsAnAPIObject() {}
func (*ReplicationControllerList) IsAnAPIObject() {} func (*ReplicationControllerList) IsAnAPIObject() {}

View File

@ -412,6 +412,11 @@ type PodState struct {
Info PodInfo `json:"info,omitempty" description:"map of container name to container status"` Info PodInfo `json:"info,omitempty" description:"map of container name to container status"`
} }
type PodStatusResult struct {
TypeMeta `json:",inline"`
State PodState `json:"state,omitempty" description:"current state of the pod"`
}
// PodList is a list of Pods. // PodList is a list of Pods.
type PodList struct { type PodList struct {
TypeMeta `json:",inline"` TypeMeta `json:",inline"`

View File

@ -345,6 +345,31 @@ func init() {
return nil return nil
}, },
func(in *newer.PodStatusResult, out *PodStatusResult, s conversion.Scope) error {
if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil {
return err
}
if err := s.Convert(&in.ObjectMeta, &out.TypeMeta, 0); err != nil {
return err
}
if err := s.Convert(&in.Status, &out.State, 0); err != nil {
return err
}
return nil
},
func(in *PodStatusResult, out *newer.PodStatusResult, s conversion.Scope) error {
if err := s.Convert(&in.TypeMeta, &out.TypeMeta, 0); err != nil {
return err
}
if err := s.Convert(&in.TypeMeta, &out.ObjectMeta, 0); err != nil {
return err
}
if err := s.Convert(&in.State, &out.Status, 0); err != nil {
return err
}
return nil
},
func(in *newer.PodSpec, out *PodState, s conversion.Scope) error { func(in *newer.PodSpec, out *PodState, s conversion.Scope) error {
if err := s.Convert(&in, &out.Manifest, 0); err != nil { if err := s.Convert(&in, &out.Manifest, 0); err != nil {
return err return err

View File

@ -27,7 +27,7 @@ var Codec = runtime.CodecFor(api.Scheme, "v1beta2")
func init() { func init() {
api.Scheme.AddKnownTypes("v1beta2", api.Scheme.AddKnownTypes("v1beta2",
&Pod{}, &Pod{},
&PodContainerInfo{}, &PodStatusResult{},
&PodList{}, &PodList{},
&ReplicationController{}, &ReplicationController{},
&ReplicationControllerList{}, &ReplicationControllerList{},
@ -57,7 +57,7 @@ func init() {
} }
func (*Pod) IsAnAPIObject() {} func (*Pod) IsAnAPIObject() {}
func (*PodContainerInfo) IsAnAPIObject() {} func (*PodStatusResult) IsAnAPIObject() {}
func (*PodList) IsAnAPIObject() {} func (*PodList) IsAnAPIObject() {}
func (*ReplicationController) IsAnAPIObject() {} func (*ReplicationController) IsAnAPIObject() {}
func (*ReplicationControllerList) IsAnAPIObject() {} func (*ReplicationControllerList) IsAnAPIObject() {}

View File

@ -375,6 +375,11 @@ type PodState struct {
Info PodInfo `json:"info,omitempty" description:"map of container name to container status"` Info PodInfo `json:"info,omitempty" description:"map of container name to container status"`
} }
type PodStatusResult struct {
TypeMeta `json:",inline"`
State PodState `json:"state,omitempty" description:"current state of the pod"`
}
// PodList is a list of Pods. // PodList is a list of Pods.
type PodList struct { type PodList struct {
TypeMeta `json:",inline"` TypeMeta `json:",inline"`

View File

@ -26,9 +26,9 @@ var Codec = runtime.CodecFor(api.Scheme, "v1beta3")
func init() { func init() {
api.Scheme.AddKnownTypes("v1beta3", api.Scheme.AddKnownTypes("v1beta3",
&PodContainerInfo{},
&Pod{}, &Pod{},
&PodList{}, &PodList{},
&PodStatusResult{},
&PodTemplate{}, &PodTemplate{},
&PodTemplateList{}, &PodTemplateList{},
&BoundPod{}, &BoundPod{},
@ -56,9 +56,9 @@ func init() {
api.Scheme.AddKnownTypeWithName("v1beta3", "ServerOpList", &OperationList{}) api.Scheme.AddKnownTypeWithName("v1beta3", "ServerOpList", &OperationList{})
} }
func (*PodContainerInfo) IsAnAPIObject() {}
func (*Pod) IsAnAPIObject() {} func (*Pod) IsAnAPIObject() {}
func (*PodList) IsAnAPIObject() {} func (*PodList) IsAnAPIObject() {}
func (*PodStatusResult) IsAnAPIObject() {}
func (*PodTemplate) IsAnAPIObject() {} func (*PodTemplate) IsAnAPIObject() {}
func (*PodTemplateList) IsAnAPIObject() {} func (*PodTemplateList) IsAnAPIObject() {}
func (*BoundPod) IsAnAPIObject() {} func (*BoundPod) IsAnAPIObject() {}

View File

@ -435,13 +435,6 @@ type ContainerStatus struct {
// PodInfo contains one entry for every container with available info. // PodInfo contains one entry for every container with available info.
type PodInfo map[string]ContainerStatus type PodInfo map[string]ContainerStatus
// PodContainerInfo is a wrapper for PodInfo that can be encode/decoded
type PodContainerInfo struct {
TypeMeta `json:",inline"`
ObjectMeta `json:"metadata,omitempty"`
ContainerInfo PodInfo `json:"containerInfo" description:"information about each container in this pod"`
}
type RestartPolicyAlways struct{} type RestartPolicyAlways struct{}
// TODO(dchen1107): Define what kinds of failures should restart. // TODO(dchen1107): Define what kinds of failures should restart.
@ -511,6 +504,15 @@ type PodStatus struct {
Info PodInfo `json:"info,omitempty"` Info PodInfo `json:"info,omitempty"`
} }
// PodStatusResult is a wrapper for PodStatus returned by kubelet that can be encode/decoded
type PodStatusResult struct {
TypeMeta `json:",inline"`
ObjectMeta `json:"metadata,omitempty"`
// Status represents the current information about a pod. This data may not be up
// to date.
Status PodStatus `json:"status,omitempty"`
}
// Pod is a collection of containers that can run on a host. This resource is created // Pod is a collection of containers that can run on a host. This resource is created
// by clients and scheduled onto hosts. BoundPod represents the state of this resource // by clients and scheduled onto hosts. BoundPod represents the state of this resource
// to hosts. // to hosts.

View File

@ -46,9 +46,9 @@ type KubeletHealthChecker interface {
// PodInfoGetter is an interface for things that can get information about a pod's containers. // PodInfoGetter is an interface for things that can get information about a pod's containers.
// Injectable for easy testing. // Injectable for easy testing.
type PodInfoGetter interface { type PodInfoGetter interface {
// GetPodInfo returns information about all containers which are part // GetPodStatus returns information about all containers which are part
// Returns an api.PodInfo, or an error if one occurs. // Returns an api.PodStatus, or an error if one occurs.
GetPodInfo(host, podNamespace, podID string) (api.PodContainerInfo, error) GetPodStatus(host, podNamespace, podID string) (api.PodStatusResult, error)
} }
// HTTPKubeletClient is the default implementation of PodInfoGetter and KubeletHealthchecker, accesses the kubelet over HTTP. // HTTPKubeletClient is the default implementation of PodInfoGetter and KubeletHealthchecker, accesses the kubelet over HTTP.
@ -95,7 +95,7 @@ func (c *HTTPKubeletClient) url(host string) string {
} }
// GetPodInfo gets information about the specified pod. // GetPodInfo gets information about the specified pod.
func (c *HTTPKubeletClient) GetPodInfo(host, podNamespace, podID string) (api.PodContainerInfo, error) { func (c *HTTPKubeletClient) GetPodStatus(host, podNamespace, podID string) (api.PodStatusResult, error) {
request, err := http.NewRequest( request, err := http.NewRequest(
"GET", "GET",
fmt.Sprintf( fmt.Sprintf(
@ -104,28 +104,28 @@ func (c *HTTPKubeletClient) GetPodInfo(host, podNamespace, podID string) (api.Po
podID, podID,
podNamespace), podNamespace),
nil) nil)
info := api.PodContainerInfo{} status := api.PodStatusResult{}
if err != nil { if err != nil {
return info, err return status, err
} }
response, err := c.Client.Do(request) response, err := c.Client.Do(request)
if err != nil { if err != nil {
return info, err return status, err
} }
defer response.Body.Close() defer response.Body.Close()
if response.StatusCode == http.StatusNotFound { if response.StatusCode == http.StatusNotFound {
return info, ErrPodInfoNotAvailable return status, ErrPodInfoNotAvailable
} }
body, err := ioutil.ReadAll(response.Body) body, err := ioutil.ReadAll(response.Body)
if err != nil { if err != nil {
return info, err return status, err
} }
// Check that this data can be unmarshalled // Check that this data can be unmarshalled
err = latest.Codec.DecodeInto(body, &info) err = latest.Codec.DecodeInto(body, &status)
if err != nil { if err != nil {
return info, err return status, err
} }
return info, nil return status, nil
} }
func (c *HTTPKubeletClient) HealthCheck(host string) (health.Status, error) { func (c *HTTPKubeletClient) HealthCheck(host string) (health.Status, error) {
@ -138,8 +138,8 @@ func (c *HTTPKubeletClient) HealthCheck(host string) (health.Status, error) {
type FakeKubeletClient struct{} type FakeKubeletClient struct{}
// GetPodInfo is a fake implementation of PodInfoGetter.GetPodInfo. // GetPodInfo is a fake implementation of PodInfoGetter.GetPodInfo.
func (c FakeKubeletClient) GetPodInfo(host, podNamespace string, podID string) (api.PodContainerInfo, error) { func (c FakeKubeletClient) GetPodStatus(host, podNamespace string, podID string) (api.PodStatusResult, error) {
return api.PodContainerInfo{}, errors.New("Not Implemented") return api.PodStatusResult{}, errors.New("Not Implemented")
} }
func (c FakeKubeletClient) HealthCheck(host string) (health.Status, error) { func (c FakeKubeletClient) HealthCheck(host string) (health.Status, error) {

View File

@ -31,9 +31,12 @@ import (
) )
func TestHTTPKubeletClient(t *testing.T) { func TestHTTPKubeletClient(t *testing.T) {
expectObj := api.PodContainerInfo{ expectObj := api.PodStatusResult{
ContainerInfo: map[string]api.ContainerStatus{ Status: api.PodStatus{
"myID": {}, Info: map[string]api.ContainerStatus{
"myID1": {},
"myID2": {},
},
}, },
} }
body, err := json.Marshal(expectObj) body, err := json.Marshal(expectObj)
@ -64,13 +67,13 @@ func TestHTTPKubeletClient(t *testing.T) {
Client: http.DefaultClient, Client: http.DefaultClient,
Port: uint(port), Port: uint(port),
} }
gotObj, err := podInfoGetter.GetPodInfo(parts[0], api.NamespaceDefault, "foo") gotObj, err := podInfoGetter.GetPodStatus(parts[0], api.NamespaceDefault, "foo")
if err != nil { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
} }
// reflect.DeepEqual(expectObj, gotObj) doesn't handle blank times well // reflect.DeepEqual(expectObj, gotObj) doesn't handle blank times well
if len(gotObj.ContainerInfo) != len(expectObj.ContainerInfo) { if len(gotObj.Status.Info) != len(expectObj.Status.Info) {
t.Errorf("Unexpected response. Expected: %#v, received %#v", expectObj, gotObj) t.Errorf("Unexpected response. Expected: %#v, received %#v", expectObj, gotObj)
} }
} }
@ -109,7 +112,7 @@ func TestHTTPKubeletClientNotFound(t *testing.T) {
Client: http.DefaultClient, Client: http.DefaultClient,
Port: uint(port), Port: uint(port),
} }
_, err = podInfoGetter.GetPodInfo(parts[0], api.NamespaceDefault, "foo") _, err = podInfoGetter.GetPodStatus(parts[0], api.NamespaceDefault, "foo")
if err != ErrPodInfoNotAvailable { if err != ErrPodInfoNotAvailable {
t.Errorf("Expected %#v, Got %#v", ErrPodInfoNotAvailable, err) t.Errorf("Expected %#v, Got %#v", ErrPodInfoNotAvailable, err)
} }

View File

@ -71,17 +71,17 @@ func ResolvePort(portReference util.IntOrString, container *api.Container) (int,
func (h *httpActionHandler) Run(podFullName string, uid types.UID, container *api.Container, handler *api.Handler) error { func (h *httpActionHandler) Run(podFullName string, uid types.UID, container *api.Container, handler *api.Handler) error {
host := handler.HTTPGet.Host host := handler.HTTPGet.Host
if len(host) == 0 { if len(host) == 0 {
var info api.PodInfo var status api.PodStatus
info, err := h.kubelet.GetPodInfo(podFullName, uid) status, err := h.kubelet.GetPodStatus(podFullName, uid)
if err != nil { if err != nil {
glog.Errorf("unable to get pod info, event handlers may be invalid.") glog.Errorf("unable to get pod info, event handlers may be invalid.")
return err return err
} }
netInfo, found := info[networkContainerName] netInfo, found := status.Info[networkContainerName]
if found { if found {
host = netInfo.PodIP host = netInfo.PodIP
} else { } else {
return fmt.Errorf("failed to find networking container: %v", info) return fmt.Errorf("failed to find networking container: %v", status)
} }
} }
var port int var port int

View File

@ -1010,12 +1010,11 @@ func (kl *Kubelet) syncPod(pod *api.BoundPod, dockerContainers dockertools.Docke
return err return err
} }
podStatus := api.PodStatus{} podStatus, err := kl.GetPodStatus(podFullName, uid)
info, err := kl.GetPodInfo(podFullName, uid)
if err != nil { if err != nil {
glog.Errorf("Unable to get pod with name %q and uid %q info, health checks may be invalid", podFullName, uid) glog.Errorf("Unable to get pod with name %q and uid %q info, health checks may be invalid", podFullName, uid)
} }
netInfo, found := info[networkContainerName] netInfo, found := podStatus.Info[networkContainerName]
if found { if found {
podStatus.PodIP = netInfo.PodIP podStatus.PodIP = netInfo.PodIP
} }
@ -1340,11 +1339,11 @@ func (kl *Kubelet) syncLoop(updates <-chan PodUpdate, handler SyncHandler) {
} }
// GetKubeletContainerLogs returns logs from the container // GetKubeletContainerLogs returns logs from the container
// The second parameter of GetPodInfo and FindPodContainer methods represents pod UUID, which is allowed to be blank // The second parameter of GetPodStatus and FindPodContainer methods represents pod UUID, which is allowed to be blank
// TODO: this method is returning logs of random container attempts, when it should be returning the most recent attempt // TODO: this method is returning logs of random container attempts, when it should be returning the most recent attempt
// or all of them. // or all of them.
func (kl *Kubelet) GetKubeletContainerLogs(podFullName, containerName, tail string, follow bool, stdout, stderr io.Writer) error { func (kl *Kubelet) GetKubeletContainerLogs(podFullName, containerName, tail string, follow bool, stdout, stderr io.Writer) error {
_, err := kl.GetPodInfo(podFullName, "") _, err := kl.GetPodStatus(podFullName, "")
if err == dockertools.ErrNoContainersInPod { if err == dockertools.ErrNoContainersInPod {
return fmt.Errorf("pod not found (%q)\n", podFullName) return fmt.Errorf("pod not found (%q)\n", podFullName)
} }
@ -1376,8 +1375,8 @@ func (kl *Kubelet) GetPodByName(namespace, name string) (*api.BoundPod, bool) {
return nil, false return nil, false
} }
// GetPodInfo returns information from Docker about the containers in a pod // GetPodStatus returns information from Docker about the containers in a pod
func (kl *Kubelet) GetPodInfo(podFullName string, uid types.UID) (api.PodInfo, error) { func (kl *Kubelet) GetPodStatus(podFullName string, uid types.UID) (api.PodStatus, error) {
var manifest api.PodSpec var manifest api.PodSpec
for _, pod := range kl.pods { for _, pod := range kl.pods {
if GetPodFullName(&pod) == podFullName { if GetPodFullName(&pod) == podFullName {
@ -1385,7 +1384,14 @@ func (kl *Kubelet) GetPodInfo(podFullName string, uid types.UID) (api.PodInfo, e
break break
} }
} }
return dockertools.GetDockerPodInfo(kl.dockerClient, manifest, podFullName, uid)
info, err := dockertools.GetDockerPodInfo(kl.dockerClient, manifest, podFullName, uid)
// TODO(dchen1107): Determine PodPhase here
var podStatus api.PodStatus
podStatus.Info = info
return podStatus, err
} }
func (kl *Kubelet) healthy(podFullName string, podUID types.UID, status api.PodStatus, container api.Container, dockerContainer *docker.APIContainers) (health.Status, error) { func (kl *Kubelet) healthy(podFullName string, podUID types.UID, status api.PodStatus, container api.Container, dockerContainer *docker.APIContainers) (health.Status, error) {

View File

@ -67,7 +67,7 @@ type HostInterface interface {
GetMachineInfo() (*info.MachineInfo, error) GetMachineInfo() (*info.MachineInfo, error)
GetBoundPods() ([]api.BoundPod, error) GetBoundPods() ([]api.BoundPod, error)
GetPodByName(namespace, name string) (*api.BoundPod, bool) GetPodByName(namespace, name string) (*api.BoundPod, bool)
GetPodInfo(name string, uid types.UID) (api.PodInfo, error) GetPodStatus(name string, uid types.UID) (api.PodStatus, error)
RunInContainer(name string, uid types.UID, container string, cmd []string) ([]byte, error) RunInContainer(name string, uid types.UID, container string, cmd []string) ([]byte, error)
GetKubeletContainerLogs(podFullName, containerName, tail string, follow bool, stdout, stderr io.Writer) error GetKubeletContainerLogs(podFullName, containerName, tail string, follow bool, stdout, stderr io.Writer) error
ServeLogs(w http.ResponseWriter, req *http.Request) ServeLogs(w http.ResponseWriter, req *http.Request)
@ -189,15 +189,15 @@ func (s *Server) handleBoundPods(w http.ResponseWriter, req *http.Request) {
} }
func (s *Server) handlePodInfoOld(w http.ResponseWriter, req *http.Request) { func (s *Server) handlePodInfoOld(w http.ResponseWriter, req *http.Request) {
s.handlePodInfo(w, req, false) s.handlePodStatus(w, req, false)
} }
func (s *Server) handlePodInfoVersioned(w http.ResponseWriter, req *http.Request) { func (s *Server) handlePodInfoVersioned(w http.ResponseWriter, req *http.Request) {
s.handlePodInfo(w, req, true) s.handlePodStatus(w, req, true)
} }
// handlePodInfo handles podInfo requests against the Kubelet // handlePodStatus handles podInfo requests against the Kubelet
func (s *Server) handlePodInfo(w http.ResponseWriter, req *http.Request, versioned bool) { func (s *Server) handlePodStatus(w http.ResponseWriter, req *http.Request, versioned bool) {
u, err := url.ParseRequestURI(req.RequestURI) u, err := url.ParseRequestURI(req.RequestURI)
if err != nil { if err != nil {
s.error(w, err) s.error(w, err)
@ -221,12 +221,12 @@ func (s *Server) handlePodInfo(w http.ResponseWriter, req *http.Request, version
http.Error(w, "Pod does not exist", http.StatusNotFound) http.Error(w, "Pod does not exist", http.StatusNotFound)
return return
} }
info, err := s.host.GetPodInfo(GetPodFullName(pod), podUID) status, err := s.host.GetPodStatus(GetPodFullName(pod), podUID)
if err != nil { if err != nil {
s.error(w, err) s.error(w, err)
return return
} }
data, err := exportPodInfo(info, versioned) data, err := exportPodStatus(status, versioned)
if err != nil { if err != nil {
s.error(w, err) s.error(w, err)
return return
@ -373,16 +373,16 @@ func (s *Server) serveStats(w http.ResponseWriter, req *http.Request) {
return return
} }
func exportPodInfo(info api.PodInfo, versioned bool) ([]byte, error) { func exportPodStatus(status api.PodStatus, versioned bool) ([]byte, error) {
if versioned { if versioned {
// TODO: support arbitrary versions here // TODO: support arbitrary versions here
codec, err := findCodec("v1beta1") codec, err := findCodec("v1beta1")
if err != nil { if err != nil {
return nil, err return nil, err
} }
return codec.Encode(&api.PodContainerInfo{ContainerInfo: info}) return codec.Encode(&api.PodStatusResult{Status: status})
} }
return json.Marshal(info) return json.Marshal(status)
} }
func findCodec(version string) (runtime.Codec, error) { func findCodec(version string) (runtime.Codec, error) {

View File

@ -35,7 +35,7 @@ import (
type fakeKubelet struct { type fakeKubelet struct {
podByNameFunc func(namespace, name string) (*api.BoundPod, bool) podByNameFunc func(namespace, name string) (*api.BoundPod, bool)
infoFunc func(name string) (api.PodInfo, error) statusFunc func(name string) (api.PodStatus, error)
containerInfoFunc func(podFullName string, uid types.UID, containerName string, req *info.ContainerInfoRequest) (*info.ContainerInfo, error) containerInfoFunc func(podFullName string, uid types.UID, containerName string, req *info.ContainerInfoRequest) (*info.ContainerInfo, error)
rootInfoFunc func(query *info.ContainerInfoRequest) (*info.ContainerInfo, error) rootInfoFunc func(query *info.ContainerInfoRequest) (*info.ContainerInfo, error)
machineInfoFunc func() (*info.MachineInfo, error) machineInfoFunc func() (*info.MachineInfo, error)
@ -49,8 +49,8 @@ func (fk *fakeKubelet) GetPodByName(namespace, name string) (*api.BoundPod, bool
return fk.podByNameFunc(namespace, name) return fk.podByNameFunc(namespace, name)
} }
func (fk *fakeKubelet) GetPodInfo(name string, uid types.UID) (api.PodInfo, error) { func (fk *fakeKubelet) GetPodStatus(name string, uid types.UID) (api.PodStatus, error) {
return fk.infoFunc(name) return fk.statusFunc(name)
} }
func (fk *fakeKubelet) GetContainerInfo(podFullName string, uid types.UID, containerName string, req *info.ContainerInfoRequest) (*info.ContainerInfo, error) { func (fk *fakeKubelet) GetContainerInfo(podFullName string, uid types.UID, containerName string, req *info.ContainerInfoRequest) (*info.ContainerInfo, error) {
@ -128,16 +128,18 @@ func readResp(resp *http.Response) (string, error) {
return string(body), err return string(body), err
} }
func TestPodInfo(t *testing.T) { func TestPodStatus(t *testing.T) {
fw := newServerTest() fw := newServerTest()
expected := api.PodInfo{ expected := api.PodStatus{
"goodpod": api.ContainerStatus{}, Info: map[string]api.ContainerStatus{
"goodpod": {},
},
} }
fw.fakeKubelet.infoFunc = func(name string) (api.PodInfo, error) { fw.fakeKubelet.statusFunc = func(name string) (api.PodStatus, error) {
if name == "goodpod.default.etcd" { if name == "goodpod.default.etcd" {
return expected, nil return expected, nil
} }
return nil, fmt.Errorf("bad pod %s", name) return api.PodStatus{}, fmt.Errorf("bad pod %s", name)
} }
resp, err := http.Get(fw.testHTTPServer.URL + "/podInfo?podID=goodpod&podNamespace=default") resp, err := http.Get(fw.testHTTPServer.URL + "/podInfo?podID=goodpod&podNamespace=default")
if err != nil { if err != nil {

View File

@ -144,13 +144,13 @@ func (p *PodCache) computePodStatus(pod *api.Pod) (api.PodStatus, error) {
return newStatus, nil return newStatus, nil
} }
info, err := p.containerInfo.GetPodInfo(pod.Status.Host, pod.Namespace, pod.Name) result, err := p.containerInfo.GetPodStatus(pod.Status.Host, pod.Namespace, pod.Name)
newStatus.HostIP = p.ipCache.GetInstanceIP(pod.Status.Host) newStatus.HostIP = p.ipCache.GetInstanceIP(pod.Status.Host)
if err != nil { if err != nil {
newStatus.Phase = api.PodUnknown newStatus.Phase = api.PodUnknown
} else { } else {
newStatus.Info = info.ContainerInfo newStatus.Info = result.Status.Info
newStatus.Phase = getPhase(&pod.Spec, newStatus.Info) newStatus.Phase = getPhase(&pod.Spec, newStatus.Info)
if netContainerInfo, ok := newStatus.Info["net"]; ok { if netContainerInfo, ok := newStatus.Info["net"]; ok {
if netContainerInfo.PodIP != "" { if netContainerInfo.PodIP != "" {

View File

@ -36,7 +36,7 @@ type podInfoCall struct {
type podInfoResponse struct { type podInfoResponse struct {
useCount int useCount int
data api.PodContainerInfo data api.PodStatusResult
err error err error
} }
@ -48,11 +48,11 @@ type FakePodInfoGetter struct {
// default data/error to return, or you can add // default data/error to return, or you can add
// responses to specific calls-- that will take precedence. // responses to specific calls-- that will take precedence.
data api.PodContainerInfo data api.PodStatusResult
err error err error
} }
func (f *FakePodInfoGetter) GetPodInfo(host, namespace, name string) (api.PodContainerInfo, error) { func (f *FakePodInfoGetter) GetPodStatus(host, namespace, name string) (api.PodStatusResult, error) {
f.lock.Lock() f.lock.Lock()
defer f.lock.Unlock() defer f.lock.Unlock()
@ -147,7 +147,7 @@ type podCacheTestConfig struct {
ipFunc func(string) string // Construct will set a default if nil ipFunc func(string) string // Construct will set a default if nil
nodes []api.Node nodes []api.Node
pods []api.Pod pods []api.Pod
kubeletContainerInfo api.PodInfo kubeletContainerInfo api.PodStatus
// Construct will fill in these fields // Construct will fill in these fields
fakePodInfo *FakePodInfoGetter fakePodInfo *FakePodInfoGetter
@ -162,8 +162,8 @@ func (c *podCacheTestConfig) Construct() *PodCache {
} }
} }
c.fakePodInfo = &FakePodInfoGetter{ c.fakePodInfo = &FakePodInfoGetter{
data: api.PodContainerInfo{ data: api.PodStatusResult{
ContainerInfo: c.kubeletContainerInfo, Status: c.kubeletContainerInfo,
}, },
} }
c.fakeNodes = &client.Fake{ c.fakeNodes = &client.Fake{
@ -209,7 +209,8 @@ func TestPodUpdateAllContainers(t *testing.T) {
} }
return "" return ""
}, },
kubeletContainerInfo: api.PodInfo{"bar": api.ContainerStatus{}}, kubeletContainerInfo: api.PodStatus{
Info: api.PodInfo{"bar": api.ContainerStatus{}}},
nodes: []api.Node{*makeNode("machine")}, nodes: []api.Node{*makeNode("machine")},
pods: []api.Pod{*pod, *pod2}, pods: []api.Pod{*pod, *pod2},
} }
@ -233,7 +234,7 @@ func TestPodUpdateAllContainers(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("Unexpected error: %+v", err) t.Fatalf("Unexpected error: %+v", err)
} }
if e, a := config.kubeletContainerInfo, status.Info; !reflect.DeepEqual(e, a) { if e, a := config.kubeletContainerInfo.Info, status.Info; !reflect.DeepEqual(e, a) {
t.Errorf("Unexpected mismatch. Expected: %+v, Got: %+v", e, a) t.Errorf("Unexpected mismatch. Expected: %+v, Got: %+v", e, a)
} }
if e, a := "1.2.3.5", status.HostIP; e != a { if e, a := "1.2.3.5", status.HostIP; e != a {
@ -252,7 +253,7 @@ func TestPodUpdateAllContainers(t *testing.T) {
func TestFillPodStatusNoHost(t *testing.T) { func TestFillPodStatusNoHost(t *testing.T) {
pod := makePod(api.NamespaceDefault, "foo", "", "bar") pod := makePod(api.NamespaceDefault, "foo", "", "bar")
config := podCacheTestConfig{ config := podCacheTestConfig{
kubeletContainerInfo: api.PodInfo{}, kubeletContainerInfo: api.PodStatus{},
nodes: []api.Node{*makeNode("machine")}, nodes: []api.Node{*makeNode("machine")},
pods: []api.Pod{*pod}, pods: []api.Pod{*pod},
} }
@ -271,7 +272,7 @@ func TestFillPodStatusNoHost(t *testing.T) {
func TestFillPodStatusMissingMachine(t *testing.T) { func TestFillPodStatusMissingMachine(t *testing.T) {
pod := makePod(api.NamespaceDefault, "foo", "machine", "bar") pod := makePod(api.NamespaceDefault, "foo", "machine", "bar")
config := podCacheTestConfig{ config := podCacheTestConfig{
kubeletContainerInfo: api.PodInfo{}, kubeletContainerInfo: api.PodStatus{},
nodes: []api.Node{}, nodes: []api.Node{},
pods: []api.Pod{*pod}, pods: []api.Pod{*pod},
} }
@ -292,7 +293,12 @@ func TestFillPodStatus(t *testing.T) {
expectedIP := "1.2.3.4" expectedIP := "1.2.3.4"
expectedTime, _ := time.Parse("2013-Feb-03", "2013-Feb-03") expectedTime, _ := time.Parse("2013-Feb-03", "2013-Feb-03")
config := podCacheTestConfig{ config := podCacheTestConfig{
kubeletContainerInfo: api.PodInfo{ kubeletContainerInfo: api.PodStatus{
Phase: api.PodPending,
Host: "machine",
HostIP: "ip of machine",
PodIP: expectedIP,
Info: api.PodInfo{
"net": { "net": {
State: api.ContainerState{ State: api.ContainerState{
Running: &api.ContainerStateRunning{ Running: &api.ContainerStateRunning{
@ -303,30 +309,6 @@ func TestFillPodStatus(t *testing.T) {
PodIP: expectedIP, PodIP: expectedIP,
}, },
}, },
nodes: []api.Node{*makeNode("machine")},
pods: []api.Pod{*pod},
}
cache := config.Construct()
err := cache.updatePodStatus(&config.pods[0])
if err != nil {
t.Fatalf("Unexpected error: %+v", err)
}
status, err := cache.GetPodStatus(pod.Namespace, pod.Name)
if e, a := config.kubeletContainerInfo, status.Info; !reflect.DeepEqual(e, a) {
t.Errorf("Expected: %+v, Got %+v", e, a)
}
if status.PodIP != expectedIP {
t.Errorf("Expected %s, Got %s\n%+v", expectedIP, status.PodIP, status)
}
}
func TestFillPodInfoNoData(t *testing.T) {
pod := makePod(api.NamespaceDefault, "foo", "machine", "bar")
expectedIP := ""
config := podCacheTestConfig{
kubeletContainerInfo: api.PodInfo{
"net": {},
}, },
nodes: []api.Node{*makeNode("machine")}, nodes: []api.Node{*makeNode("machine")},
pods: []api.Pod{*pod}, pods: []api.Pod{*pod},
@ -338,7 +320,34 @@ func TestFillPodInfoNoData(t *testing.T) {
} }
status, err := cache.GetPodStatus(pod.Namespace, pod.Name) status, err := cache.GetPodStatus(pod.Namespace, pod.Name)
if e, a := config.kubeletContainerInfo, status.Info; !reflect.DeepEqual(e, a) { if e, a := &config.kubeletContainerInfo, status; !reflect.DeepEqual(e, a) {
t.Errorf("Expected: %+v, Got %+v", e, a)
}
}
func TestFillPodInfoNoData(t *testing.T) {
pod := makePod(api.NamespaceDefault, "foo", "machine", "bar")
expectedIP := ""
config := podCacheTestConfig{
kubeletContainerInfo: api.PodStatus{
Phase: api.PodPending,
Host: "machine",
HostIP: "ip of machine",
Info: api.PodInfo{
"net": {},
},
},
nodes: []api.Node{*makeNode("machine")},
pods: []api.Pod{*pod},
}
cache := config.Construct()
err := cache.updatePodStatus(&config.pods[0])
if err != nil {
t.Fatalf("Unexpected error: %+v", err)
}
status, err := cache.GetPodStatus(pod.Namespace, pod.Name)
if e, a := &config.kubeletContainerInfo, status; !reflect.DeepEqual(e, a) {
t.Errorf("Expected: %+v, Got %+v", e, a) t.Errorf("Expected: %+v, Got %+v", e, a)
} }
if status.PodIP != expectedIP { if status.PodIP != expectedIP {
@ -411,7 +420,7 @@ func TestPodPhaseWithBadNode(t *testing.T) {
} }
for _, test := range tests { for _, test := range tests {
config := podCacheTestConfig{ config := podCacheTestConfig{
kubeletContainerInfo: test.pod.Status.Info, kubeletContainerInfo: test.pod.Status,
nodes: []api.Node{}, nodes: []api.Node{},
pods: []api.Pod{*test.pod}, pods: []api.Pod{*test.pod},
} }