diff --git a/pkg/kubelet/container/runtime.go b/pkg/kubelet/container/runtime.go index 6fa2073da49..a8a49c36756 100644 --- a/pkg/kubelet/container/runtime.go +++ b/pkg/kubelet/container/runtime.go @@ -19,6 +19,7 @@ package container import ( "fmt" "io" + "reflect" "strings" "github.com/GoogleCloudPlatform/kubernetes/pkg/api" @@ -282,6 +283,11 @@ func (p *Pod) FindContainerByName(containerName string) *Container { return nil } +// IsEmpty returns true if the pod is empty. +func (p *Pod) IsEmpty() bool { + return reflect.DeepEqual(p, &Pod{}) +} + // GetPodFullName returns a name that uniquely identifies a pod. func GetPodFullName(pod *api.Pod) string { // Use underscore as the delimiter because it is not allowed in pod name diff --git a/pkg/kubelet/dockertools/manager.go b/pkg/kubelet/dockertools/manager.go index 157a957c2f7..f1c3e8e5751 100644 --- a/pkg/kubelet/dockertools/manager.go +++ b/pkg/kubelet/dockertools/manager.go @@ -1006,6 +1006,10 @@ func (dm *DockerManager) ExecInContainer(containerId string, cmd []string, stdin return dm.execHandler.ExecInContainer(dm.client, container, cmd, stdin, stdout, stderr, tty) } +func noPodInfraContainerError(podName, podNamespace string) error { + return fmt.Errorf("cannot find pod infra container in pod %q", kubecontainer.BuildPodFullName(podName, podNamespace)) +} + // PortForward executes socat in the pod's network namespace and copies // data between stream (representing the user's local connection on their // computer) and the specified port in the container. @@ -1017,7 +1021,7 @@ func (dm *DockerManager) ExecInContainer(containerId string, cmd []string, stdin func (dm *DockerManager) PortForward(pod *kubecontainer.Pod, port uint16, stream io.ReadWriteCloser) error { podInfraContainer := pod.FindContainerByName(PodInfraContainerName) if podInfraContainer == nil { - return fmt.Errorf("cannot find pod infra container in pod %q", kubecontainer.BuildPodFullName(pod.Name, pod.Namespace)) + return noPodInfraContainerError(pod.Name, pod.Namespace) } container, err := dm.client.InspectContainer(string(podInfraContainer.ID)) if err != nil { diff --git a/pkg/kubelet/dockertools/manager_test.go b/pkg/kubelet/dockertools/manager_test.go index 30db5b4aca8..cb92bd5d1d8 100644 --- a/pkg/kubelet/dockertools/manager_test.go +++ b/pkg/kubelet/dockertools/manager_test.go @@ -1914,3 +1914,26 @@ func TestSyncPodEventHandlerFails(t *testing.T) { t.Errorf("Wrong stopped container, expected: bar, get: %q", dockerName.ContainerName) } } + +func TestPortForwardNoSuchContainer(t *testing.T) { + dm, _ := newTestDockerManager() + + podName, podNamespace := "podName", "podNamespace" + err := dm.PortForward( + &kubecontainer.Pod{ + ID: "podID", + Name: podName, + Namespace: podNamespace, + Containers: nil, + }, + 5000, + nil, + ) + if err == nil { + t.Fatal("unexpected non-error") + } + expectedErr := noPodInfraContainerError(podName, podNamespace) + if !reflect.DeepEqual(err, expectedErr) { + t.Fatalf("expected %v, but saw %v", expectedErr, err) + } +} diff --git a/pkg/kubelet/kubelet.go b/pkg/kubelet/kubelet.go index bb39740833d..f2eb5eeed4f 100644 --- a/pkg/kubelet/kubelet.go +++ b/pkg/kubelet/kubelet.go @@ -2235,6 +2235,9 @@ func (kl *Kubelet) PortForward(podFullName string, podUID types.UID, port uint16 return err } pod := kubecontainer.Pods(pods).FindPod(podFullName, podUID) + if pod.IsEmpty() { + return fmt.Errorf("pod not found (%q)", podFullName) + } return kl.runner.PortForward(&pod, port, stream) } diff --git a/pkg/kubelet/kubelet_test.go b/pkg/kubelet/kubelet_test.go index 601b558e1dc..c1c4d0a2b35 100644 --- a/pkg/kubelet/kubelet_test.go +++ b/pkg/kubelet/kubelet_test.go @@ -934,6 +934,7 @@ func TestGetContainerInfoWithNoMatchingContainers(t *testing.T) { type fakeContainerCommandRunner struct { Cmd []string ID string + PodID types.UID E error Stdin io.Reader Stdout io.WriteCloser @@ -960,11 +961,7 @@ func (f *fakeContainerCommandRunner) ExecInContainer(id string, cmd []string, in } func (f *fakeContainerCommandRunner) PortForward(pod *kubecontainer.Pod, port uint16, stream io.ReadWriteCloser) error { - podInfraContainer := pod.FindContainerByName(dockertools.PodInfraContainerName) - if podInfraContainer == nil { - return fmt.Errorf("cannot find pod infra container in pod %q", kubecontainer.BuildPodFullName(pod.Name, pod.Namespace)) - } - f.ID = string(podInfraContainer.ID) + f.PodID = pod.ID f.Port = port f.Stream = stream return nil @@ -2123,73 +2120,32 @@ func TestPortForwardNoSuchPod(t *testing.T) { } } -func TestPortForwardNoSuchContainer(t *testing.T) { +func TestPortForward(t *testing.T) { testKubelet := newTestKubeletWithFakeRuntime(t) kubelet := testKubelet.kubelet fakeRuntime := testKubelet.fakeRuntime - fakeCommandRunner := fakeContainerCommandRunner{} - kubelet.runner = &fakeCommandRunner podName := "podFoo" podNamespace := "nsFoo" - var port uint16 = 5000 - + podID := types.UID("12345678") fakeRuntime.PodList = []*kubecontainer.Pod{ { - ID: "12345678", + ID: podID, Name: podName, Namespace: podNamespace, Containers: []*kubecontainer.Container{ - {Name: "bar", - ID: "barID"}, + { + Name: "foo", + ID: "containerFoo", + }, }, }, } - - err := kubelet.PortForward( - kubecontainer.GetPodFullName(&api.Pod{ObjectMeta: api.ObjectMeta{ - UID: "12345678", - Name: podName, - Namespace: podNamespace, - }}), - "", - port, - nil, - ) - if err == nil { - t.Fatal("unexpected non-error") - } - if fakeCommandRunner.ID != "" { - t.Fatal("unexpected invocation of runner.PortForward") - } -} - -func TestPortForward(t *testing.T) { fakeCommandRunner := fakeContainerCommandRunner{} - testKubelet := newTestKubelet(t) - kubelet := testKubelet.kubelet - fakeDocker := testKubelet.fakeDocker kubelet.runner = &fakeCommandRunner - podName := "podFoo" - podNamespace := "nsFoo" - containerID := "containerFoo" var port uint16 = 5000 stream := &fakeReadWriteCloser{} - - infraContainerID := "infra" - - fakeDocker.ContainerList = []docker.APIContainers{ - { - ID: infraContainerID, - Names: []string{"/k8s_POD" + "_" + podName + "_" + podNamespace + "_12345678_42"}, - }, - { - ID: containerID, - Names: []string{"/k8s_" + containerID + "_" + podName + "_" + podNamespace + "_12345678_42"}, - }, - } - err := kubelet.PortForward( kubecontainer.GetPodFullName(&api.Pod{ObjectMeta: api.ObjectMeta{ UID: "12345678", @@ -2203,7 +2159,7 @@ func TestPortForward(t *testing.T) { if err != nil { t.Fatalf("unexpected error: %s", err) } - if e, a := infraContainerID, fakeCommandRunner.ID; e != a { + if e, a := podID, fakeCommandRunner.PodID; e != a { t.Fatalf("container id: expected %q, got %q", e, a) } if e, a := port, fakeCommandRunner.Port; e != a {