diff --git a/cmd/integration/integration.go b/cmd/integration/integration.go index 8aba9bdfe1b..7d8c79f9f64 100644 --- a/cmd/integration/integration.go +++ b/cmd/integration/integration.go @@ -77,36 +77,6 @@ var ( type fakeKubeletClient struct{} -func (fakeKubeletClient) GetPodStatus(host, podNamespace, podName string) (api.PodStatusResult, error) { - glog.V(3).Infof("Trying to get container info for %v/%v/%v", host, podNamespace, podName) - // This is a horrible hack to get around the fact that we can't provide - // different port numbers per kubelet... - var c client.PodInfoGetter - switch host { - case "localhost": - c = &client.HTTPKubeletClient{ - Client: http.DefaultClient, - Port: 10250, - } - case "127.0.0.1": - c = &client.HTTPKubeletClient{ - Client: http.DefaultClient, - Port: 10251, - } - default: - glog.Fatalf("Can't get info for: '%v', '%v - %v'", host, podNamespace, podName) - } - r, err := c.GetPodStatus("127.0.0.1", podNamespace, podName) - if err != nil { - return r, err - } - r.Status.PodIP = "1.2.3.4" - for i := range r.Status.ContainerStatuses { - r.Status.ContainerStatuses[i].Ready = true - } - return r, nil -} - func (fakeKubeletClient) GetConnectionInfo(host string) (string, uint, http.RoundTripper, error) { return "", 0, nil, errors.New("Not Implemented") } @@ -265,8 +235,7 @@ func makeTempDirOrDie(prefix string, baseDir string) string { // podsOnMinions returns true when all of the selected pods exist on a minion. func podsOnMinions(c *client.Client, podNamespace string, labelSelector labels.Selector) wait.ConditionFunc { - podInfo := fakeKubeletClient{} - // wait for minions to indicate they have info about the desired pods + // Wait until all pods are running on the node. return func() (bool, error) { pods, err := c.Pods(podNamespace).List(labelSelector, fields.Everything()) if err != nil { @@ -274,14 +243,14 @@ func podsOnMinions(c *client.Client, podNamespace string, labelSelector labels.S return false, nil } for i := range pods.Items { - host, id, namespace := pods.Items[i].Spec.Host, pods.Items[i].Name, pods.Items[i].Namespace - glog.Infof("Check whether pod %s.%s exists on node %q", id, namespace, host) - if len(host) == 0 { - glog.Infof("Pod %s.%s is not bound to a host yet", id, namespace) + pod := pods.Items[i] + podString := fmt.Sprintf("%q/%q", pod.Namespace, pod.Name) + glog.Infof("Check whether pod %q exists on node %q", podString, pod.Spec.Host) + if len(pod.Spec.Host) == 0 { + glog.Infof("Pod %q is not bound to a host yet", podString) return false, nil } - if _, err := podInfo.GetPodStatus(host, namespace, id); err != nil { - glog.Infof("GetPodStatus error: %v", err) + if pod.Status.Phase != api.PodRunning { return false, nil } } diff --git a/pkg/client/kubelet.go b/pkg/client/kubelet.go index 6e50ab34b09..e2076319267 100644 --- a/pkg/client/kubelet.go +++ b/pkg/client/kubelet.go @@ -18,27 +18,18 @@ package client import ( "errors" - "fmt" - "io/ioutil" "net" "net/http" "net/url" "strconv" - "github.com/GoogleCloudPlatform/kubernetes/pkg/api" - "github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest" "github.com/GoogleCloudPlatform/kubernetes/pkg/probe" httprobe "github.com/GoogleCloudPlatform/kubernetes/pkg/probe/http" - "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" ) -// ErrPodInfoNotAvailable may be returned when the requested pod info is not available. -var ErrPodInfoNotAvailable = errors.New("no pod info available") - // KubeletClient is an interface for all kubelet functionality type KubeletClient interface { KubeletHealthChecker - PodInfoGetter ConnectionInfoGetter } @@ -47,19 +38,11 @@ type KubeletHealthChecker interface { HealthCheck(host string) (probe.Result, error) } -// PodInfoGetter is an interface for things that can get information about a pod's containers. -// Injectable for easy testing. -type PodInfoGetter interface { - // GetPodStatus returns information about all containers which are part - // Returns an api.PodStatus, or an error if one occurs. - GetPodStatus(host, podNamespace, podID string) (api.PodStatusResult, error) -} - type ConnectionInfoGetter interface { GetConnectionInfo(host string) (scheme string, port uint, transport http.RoundTripper, error error) } -// HTTPKubeletClient is the default implementation of PodInfoGetter and KubeletHealthchecker, accesses the kubelet over HTTP. +// HTTPKubeletClient is the default implementation of KubeletHealthchecker, accesses the kubelet over HTTP. type HTTPKubeletClient struct { Client *http.Client Port uint @@ -120,39 +103,6 @@ func (c *HTTPKubeletClient) url(host, path, query string) string { }).String() } -// GetPodInfo gets information about the specified pod. -func (c *HTTPKubeletClient) GetPodStatus(host, podNamespace, podID string) (api.PodStatusResult, error) { - status := api.PodStatusResult{} - query := url.Values{"podID": {podID}, "podNamespace": {podNamespace}} - response, err := c.getEntity(host, "/api/v1beta1/podInfo", query.Encode(), &status) - if response != nil && response.StatusCode == http.StatusNotFound { - return status, ErrPodInfoNotAvailable - } - return status, err -} - -// getEntity might return a nil response. -func (c *HTTPKubeletClient) getEntity(host, path, query string, entity runtime.Object) (*http.Response, error) { - request, err := http.NewRequest("GET", c.url(host, path, query), nil) - if err != nil { - return nil, err - } - response, err := c.Client.Do(request) - if err != nil { - return response, err - } - defer response.Body.Close() - if response.StatusCode >= 300 || response.StatusCode < 200 { - return response, fmt.Errorf("kubelet %q server responded with HTTP error code %d", host, response.StatusCode) - } - body, err := ioutil.ReadAll(response.Body) - if err != nil { - return response, err - } - err = latest.Codec.DecodeInto(body, entity) - return response, err -} - func (c *HTTPKubeletClient) HealthCheck(host string) (probe.Result, error) { return httprobe.DoHTTPProbe(c.url(host, "/healthz", ""), c.Client) } @@ -162,11 +112,6 @@ func (c *HTTPKubeletClient) HealthCheck(host string) (probe.Result, error) { // no kubelets. type FakeKubeletClient struct{} -// GetPodInfo is a fake implementation of PodInfoGetter.GetPodInfo. -func (c FakeKubeletClient) GetPodStatus(host, podNamespace string, podID string) (api.PodStatusResult, error) { - return api.PodStatusResult{}, errors.New("Not Implemented") -} - func (c FakeKubeletClient) HealthCheck(host string) (probe.Result, error) { return probe.Unknown, errors.New("Not Implemented") } diff --git a/pkg/client/kubelet_test.go b/pkg/client/kubelet_test.go index 1b02d0a546a..375a58bdba8 100644 --- a/pkg/client/kubelet_test.go +++ b/pkg/client/kubelet_test.go @@ -25,20 +25,12 @@ import ( "strings" "testing" - "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/probe" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" ) func TestHTTPKubeletClient(t *testing.T) { - expectObj := api.PodStatusResult{ - Status: api.PodStatus{ - ContainerStatuses: []api.ContainerStatus{ - {Name: "myID1"}, - {Name: "myID2"}, - }, - }, - } + expectObj := probe.Success body, err := json.Marshal(expectObj) if err != nil { t.Errorf("unexpected error: %v", err) @@ -63,76 +55,21 @@ func TestHTTPKubeletClient(t *testing.T) { t.Errorf("unexpected error: %v", err) } - podInfoGetter := &HTTPKubeletClient{ + c := &HTTPKubeletClient{ Client: http.DefaultClient, Port: uint(port), } - gotObj, err := podInfoGetter.GetPodStatus(parts[0], api.NamespaceDefault, "foo") + gotObj, err := c.HealthCheck(parts[0]) if err != nil { t.Errorf("unexpected error: %v", err) } - - // reflect.DeepEqual(expectObj, gotObj) doesn't handle blank times well - if len(gotObj.Status.ContainerStatuses) != len(expectObj.Status.ContainerStatuses) { - t.Errorf("Unexpected response. Expected: %#v, received %#v", expectObj, gotObj) - } -} - -func TestHTTPKubeletClientNotFound(t *testing.T) { - expectObj := api.PodContainerInfo{ - ContainerInfo: []api.ContainerStatus{ - { - Name: "myID", - }, - }, - } - _, err := json.Marshal(expectObj) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - - fakeHandler := util.FakeHandler{ - StatusCode: 404, - ResponseBody: "Pod not found", - } - testServer := httptest.NewServer(&fakeHandler) - defer testServer.Close() - - hostURL, err := url.Parse(testServer.URL) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - - parts := strings.Split(hostURL.Host, ":") - - port, err := strconv.Atoi(parts[1]) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - - podInfoGetter := &HTTPKubeletClient{ - Client: http.DefaultClient, - Port: uint(port), - } - _, err = podInfoGetter.GetPodStatus(parts[0], api.NamespaceDefault, "foo") - if err != ErrPodInfoNotAvailable { - t.Errorf("Expected %#v, Got %#v", ErrPodInfoNotAvailable, err) + if gotObj != expectObj { + t.Errorf("expected: %#v, got %#v", expectObj, gotObj) } } func TestHTTPKubeletClientError(t *testing.T) { - expectObj := api.PodContainerInfo{ - ContainerInfo: []api.ContainerStatus{ - { - Name: "myID", - }, - }, - } - _, err := json.Marshal(expectObj) - if err != nil { - t.Errorf("unexpected error: %v", err) - } - + expectObj := probe.Failure fakeHandler := util.FakeHandler{ StatusCode: 500, ResponseBody: "Internal server error", @@ -152,13 +89,13 @@ func TestHTTPKubeletClientError(t *testing.T) { t.Errorf("unexpected error: %v", err) } - podInfoGetter := &HTTPKubeletClient{ + c := &HTTPKubeletClient{ Client: http.DefaultClient, Port: uint(port), } - _, err = podInfoGetter.GetPodStatus(parts[0], api.NamespaceDefault, "foo") - if err == nil || !strings.Contains(err.Error(), "HTTP error code 500") { - t.Errorf("unexpected error: %v", err) + gotObj, err := c.HealthCheck(parts[0]) + if gotObj != expectObj { + t.Errorf("expected: %#v, got %#v", expectObj, gotObj) } } diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index 698e0f73090..7068ce81de1 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -1546,7 +1546,7 @@ func (kl *Kubelet) validateContainerStatus(podStatus *api.PodStatus, containerNa // or all of them. func (kl *Kubelet) GetKubeletContainerLogs(podFullName, containerName, tail string, follow, previous bool, stdout, stderr io.Writer) error { // TODO(vmarmol): Refactor to not need the pod status and verification. - podStatus, err := kl.GetPodStatus(podFullName) + podStatus, err := kl.getPodStatus(podFullName) if err != nil { return fmt.Errorf("failed to get status for pod %q - %v", podFullName, err) } @@ -1872,9 +1872,9 @@ func getPodReadyCondition(spec *api.PodSpec, statuses []api.ContainerStatus) []a return ready } -// GetPodStatus returns information of the containers in the pod from the +// getPodStatus returns information of the containers in the pod from the // container runtime. -func (kl *Kubelet) GetPodStatus(podFullName string) (api.PodStatus, error) { +func (kl *Kubelet) getPodStatus(podFullName string) (api.PodStatus, error) { // Check to see if we have a cached version of the status. cachedPodStatus, found := kl.statusManager.GetPodStatus(podFullName) if found { diff --git a/pkg/kubelet/kubelet_test.go b/pkg/kubelet/kubelet_test.go index 102a8664cc1..fa2d2bfe2cc 100644 --- a/pkg/kubelet/kubelet_test.go +++ b/pkg/kubelet/kubelet_test.go @@ -3010,7 +3010,7 @@ func TestHandlePortConflicts(t *testing.T) { kl.handleNotFittingPods(pods) // Check pod status stored in the status map. - status, err := kl.GetPodStatus(conflictedPodName) + status, err := kl.getPodStatus(conflictedPodName) if err != nil { t.Fatalf("status of pod %q is not found in the status map: %#v", conflictedPodName, err) } @@ -3020,7 +3020,7 @@ func TestHandlePortConflicts(t *testing.T) { // Check if we can retrieve the pod status from GetPodStatus(). kl.podManager.SetPods(pods) - status, err = kl.GetPodStatus(conflictedPodName) + status, err = kl.getPodStatus(conflictedPodName) if err != nil { t.Fatalf("unable to retrieve pod status for pod %q: %#v.", conflictedPodName, err) } @@ -3062,7 +3062,7 @@ func TestHandleNodeSelector(t *testing.T) { kl.handleNotFittingPods(pods) // Check pod status stored in the status map. - status, err := kl.GetPodStatus(notfittingPodName) + status, err := kl.getPodStatus(notfittingPodName) if err != nil { t.Fatalf("status of pod %q is not found in the status map: %#v", notfittingPodName, err) } @@ -3072,7 +3072,7 @@ func TestHandleNodeSelector(t *testing.T) { // Check if we can retrieve the pod status from GetPodStatus(). kl.podManager.SetPods(pods) - status, err = kl.GetPodStatus(notfittingPodName) + status, err = kl.getPodStatus(notfittingPodName) if err != nil { t.Fatalf("unable to retrieve pod status for pod %q: %#v.", notfittingPodName, err) } @@ -3120,7 +3120,7 @@ func TestHandleMemExceeded(t *testing.T) { kl.handleNotFittingPods(pods) // Check pod status stored in the status map. - status, err := kl.GetPodStatus(notfittingPodName) + status, err := kl.getPodStatus(notfittingPodName) if err != nil { t.Fatalf("status of pod %q is not found in the status map: %#v", notfittingPodName, err) } @@ -3130,7 +3130,7 @@ func TestHandleMemExceeded(t *testing.T) { // Check if we can retrieve the pod status from GetPodStatus(). kl.podManager.SetPods(pods) - status, err = kl.GetPodStatus(notfittingPodName) + status, err = kl.getPodStatus(notfittingPodName) if err != nil { t.Fatalf("unable to retrieve pod status for pod %q: %#v.", notfittingPodName, err) } @@ -3153,12 +3153,12 @@ func TestPurgingObsoleteStatusMapEntries(t *testing.T) { } // Run once to populate the status map. kl.handleNotFittingPods(pods) - if _, err := kl.GetPodStatus(kubecontainer.BuildPodFullName("pod2", "")); err != nil { + if _, err := kl.getPodStatus(kubecontainer.BuildPodFullName("pod2", "")); err != nil { t.Fatalf("expected to have status cached for %q: %v", "pod2", err) } // Sync with empty pods so that the entry in status map will be removed. kl.SyncPods([]*api.Pod{}, emptyPodUIDs, map[string]*api.Pod{}, time.Now()) - if _, err := kl.GetPodStatus(kubecontainer.BuildPodFullName("pod2", "")); err == nil { + if _, err := kl.getPodStatus(kubecontainer.BuildPodFullName("pod2", "")); err == nil { t.Fatalf("expected to not have status cached for %q: %v", "pod2", err) } } @@ -4167,7 +4167,7 @@ func TestGetPodStatusWithLastTermination(t *testing.T) { // Check if we can retrieve the pod status from GetPodStatus(). podName := kubecontainer.GetPodFullName(pods[0]) - status, err := kubelet.GetPodStatus(podName) + status, err := kubelet.getPodStatus(podName) if err != nil { t.Fatalf("unable to retrieve pod status for pod %q: %#v.", podName, err) } else { @@ -4240,7 +4240,7 @@ func TestGetPodCreationFailureReason(t *testing.T) { t.Errorf("unexpected error: %v", err) } - status, err := kubelet.GetPodStatus(kubecontainer.GetPodFullName(pod)) + status, err := kubelet.getPodStatus(kubecontainer.GetPodFullName(pod)) if err != nil { t.Errorf("unexpected error %v", err) } @@ -4306,7 +4306,7 @@ func TestGetPodPullImageFailureReason(t *testing.T) { t.Errorf("unexpected error: %v", err) } - status, err := kubelet.GetPodStatus(kubecontainer.GetPodFullName(pod)) + status, err := kubelet.getPodStatus(kubecontainer.GetPodFullName(pod)) if err != nil { t.Errorf("unexpected error %v", err) } diff --git a/pkg/kubelet/server.go b/pkg/kubelet/server.go index 550e3182374..d0881ea9ff5 100644 --- a/pkg/kubelet/server.go +++ b/pkg/kubelet/server.go @@ -36,7 +36,6 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/healthz" "github.com/GoogleCloudPlatform/kubernetes/pkg/httplog" kubecontainer "github.com/GoogleCloudPlatform/kubernetes/pkg/kubelet/container" - "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/types" "github.com/GoogleCloudPlatform/kubernetes/pkg/util/flushwriter" "github.com/GoogleCloudPlatform/kubernetes/pkg/util/httpstream" @@ -104,7 +103,6 @@ type HostInterface interface { GetCachedMachineInfo() (*cadvisorApi.MachineInfo, error) GetPods() []*api.Pod GetPodByName(namespace, name string) (*api.Pod, bool) - GetPodStatus(name string) (api.PodStatus, 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 GetKubeletContainerLogs(podFullName, containerName, tail string, follow, previous bool, stdout, stderr io.Writer) error @@ -134,8 +132,6 @@ func (s *Server) InstallDefaultHandlers() { healthz.NamedCheck("docker", s.dockerHealthCheck), healthz.NamedCheck("hostname", s.hostnameHealthCheck), ) - s.mux.HandleFunc("/podInfo", s.handlePodInfoOld) - s.mux.HandleFunc("/api/v1beta1/podInfo", s.handlePodInfoVersioned) s.mux.HandleFunc("/pods", s.handlePods) s.mux.HandleFunc("/stats/", s.handleStats) s.mux.HandleFunc("/spec/", s.handleSpec) @@ -280,50 +276,6 @@ func (s *Server) handlePods(w http.ResponseWriter, req *http.Request) { w.Write(data) } -func (s *Server) handlePodInfoOld(w http.ResponseWriter, req *http.Request) { - s.handlePodStatus(w, req, false) -} - -func (s *Server) handlePodInfoVersioned(w http.ResponseWriter, req *http.Request) { - s.handlePodStatus(w, req, true) -} - -// handlePodStatus handles podInfo requests against the Kubelet -func (s *Server) handlePodStatus(w http.ResponseWriter, req *http.Request, versioned bool) { - u, err := url.ParseRequestURI(req.RequestURI) - if err != nil { - s.error(w, err) - return - } - podID := u.Query().Get("podID") - podNamespace := u.Query().Get("podNamespace") - if len(podID) == 0 { - http.Error(w, "Missing 'podID=' query entry.", http.StatusBadRequest) - return - } - if len(podNamespace) == 0 { - http.Error(w, "Missing 'podNamespace=' query entry.", http.StatusBadRequest) - return - } - pod, ok := s.host.GetPodByName(podNamespace, podID) - if !ok { - http.Error(w, "Pod does not exist", http.StatusNotFound) - return - } - status, err := s.host.GetPodStatus(kubecontainer.GetPodFullName(pod)) - if err != nil { - s.error(w, err) - return - } - data, err := exportPodStatus(status, versioned) - if err != nil { - s.error(w, err) - return - } - w.Header().Add("Content-type", "application/json") - w.Write(data) -} - // handleStats handles stats requests against the Kubelet. func (s *Server) handleStats(w http.ResponseWriter, req *http.Request) { s.serveStats(w, req) @@ -739,23 +691,3 @@ func (s *Server) serveStats(w http.ResponseWriter, req *http.Request) { w.Write(data) return } - -func exportPodStatus(status api.PodStatus, versioned bool) ([]byte, error) { - if versioned { - // TODO: support arbitrary versions here - codec, err := findCodec("v1beta1") - if err != nil { - return nil, err - } - return codec.Encode(&api.PodStatusResult{Status: status}) - } - return json.Marshal(status) -} - -func findCodec(version string) (runtime.Codec, error) { - versions, err := latest.InterfacesFor(version) - if err != nil { - return nil, err - } - return versions.Codec, nil -} diff --git a/pkg/kubelet/server_test.go b/pkg/kubelet/server_test.go index e6d46b05805..c0c7814ee49 100644 --- a/pkg/kubelet/server_test.go +++ b/pkg/kubelet/server_test.go @@ -43,7 +43,6 @@ import ( type fakeKubelet struct { podByNameFunc func(namespace, name string) (*api.Pod, bool) - statusFunc func(name string) (api.PodStatus, error) containerInfoFunc func(podFullName string, uid types.UID, containerName string, req *cadvisorApi.ContainerInfoRequest) (*cadvisorApi.ContainerInfo, error) rawInfoFunc func(query *cadvisorApi.ContainerInfoRequest) (map[string]*cadvisorApi.ContainerInfo, error) machineInfoFunc func() (*cadvisorApi.MachineInfo, error) @@ -62,10 +61,6 @@ func (fk *fakeKubelet) GetPodByName(namespace, name string) (*api.Pod, bool) { return fk.podByNameFunc(namespace, name) } -func (fk *fakeKubelet) GetPodStatus(name string) (api.PodStatus, error) { - return fk.statusFunc(name) -} - func (fk *fakeKubelet) GetContainerInfo(podFullName string, uid types.UID, containerName string, req *cadvisorApi.ContainerInfoRequest) (*cadvisorApi.ContainerInfo, error) { return fk.containerInfoFunc(podFullName, uid, containerName, req) } @@ -161,36 +156,6 @@ func getPodName(name, namespace string) string { return name + "_" + namespace } -func TestPodStatus(t *testing.T) { - fw := newServerTest() - expected := api.PodStatus{ - ContainerStatuses: []api.ContainerStatus{ - {Name: "goodpod"}, - }, - } - fw.fakeKubelet.statusFunc = func(name string) (api.PodStatus, error) { - if name == "goodpod_default" { - return expected, nil - } - return api.PodStatus{}, fmt.Errorf("bad pod %s", name) - } - resp, err := http.Get(fw.testHTTPServer.URL + "/podInfo?podID=goodpod&podNamespace=default") - if err != nil { - t.Errorf("Got error GETing: %v", err) - } - got, err := readResp(resp) - if err != nil { - t.Errorf("Error reading body: %v", err) - } - expectedBytes, err := json.Marshal(expected) - if err != nil { - t.Fatalf("Unexpected marshal error %v", err) - } - if got != string(expectedBytes) { - t.Errorf("Expected: '%v', got: '%v'", expected, got) - } -} - func TestContainerInfo(t *testing.T) { fw := newServerTest() expectedInfo := &cadvisorApi.ContainerInfo{}