From 4cdb1bf9ce80eee83121ae3145e563f18dc1db15 Mon Sep 17 00:00:00 2001 From: Yifan Gu Date: Mon, 13 Apr 2015 10:02:58 -0700 Subject: [PATCH] kubelet: Introduce PodInfraContainerChanged(). Update tests. --- pkg/kubelet/kubelet_test.go | 666 +++++++++++++++++++++++++----------- 1 file changed, 475 insertions(+), 191 deletions(-) diff --git a/pkg/kubelet/kubelet_test.go b/pkg/kubelet/kubelet_test.go index e279594bca4..155afa9a9be 100644 --- a/pkg/kubelet/kubelet_test.go +++ b/pkg/kubelet/kubelet_test.go @@ -70,7 +70,6 @@ type TestKubelet struct { func newTestKubelet(t *testing.T) *TestKubelet { fakeDocker := &dockertools.FakeDockerClient{Errors: make(map[string]error), RemovedImages: util.StringSet{}} - fakeRecorder := &record.FakeRecorder{} fakeKubeClient := &testclient.Fake{} kubelet := &Kubelet{} @@ -436,6 +435,22 @@ func TestKillContainer(t *testing.T) { var emptyPodUIDs map[types.UID]metrics.SyncPodType +func generatePodInfraContainerHash(pod *api.Pod) uint64 { + var ports []api.ContainerPort + if !pod.Spec.HostNetwork { + for _, container := range pod.Spec.Containers { + ports = append(ports, container.Ports...) + } + } + + container := &api.Container{ + Name: dockertools.PodInfraContainerName, + Image: dockertools.PodInfraContainerImage, + Ports: ports, + } + return dockertools.HashContainer(container) +} + func TestSyncPodsDoesNothing(t *testing.T) { testKubelet := newTestKubelet(t) testKubelet.fakeCadvisor.On("MachineInfo").Return(&cadvisorApi.MachineInfo{}, nil) @@ -444,18 +459,6 @@ func TestSyncPodsDoesNothing(t *testing.T) { waitGroup := testKubelet.waitGroup container := api.Container{Name: "bar"} - fakeDocker.ContainerList = []docker.APIContainers{ - { - // format is // k8s____ - Names: []string{"/k8s_bar." + strconv.FormatUint(dockertools.HashContainer(&container), 16) + "_foo_new_12345678_0"}, - ID: "1234", - }, - { - // pod infra container - Names: []string{"/k8s_POD_foo_new_12345678_0"}, - ID: "9876", - }, - } pods := []api.Pod{ { ObjectMeta: api.ObjectMeta{ @@ -470,6 +473,32 @@ func TestSyncPodsDoesNothing(t *testing.T) { }, }, } + + fakeDocker.ContainerList = []docker.APIContainers{ + { + // format is // k8s____ + Names: []string{"/k8s_bar." + strconv.FormatUint(dockertools.HashContainer(&container), 16) + "_foo_new_12345678_0"}, + ID: "1234", + }, + { + // pod infra container + Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(&pods[0]), 16) + "_foo_new_12345678_0"}, + ID: "9876", + }, + } + fakeDocker.ContainerMap = map[string]*docker.Container{ + "1234": { + ID: "1234", + HostConfig: &docker.HostConfig{}, + Config: &docker.Config{}, + }, + "9876": { + ID: "9876", + HostConfig: &docker.HostConfig{}, + Config: &docker.Config{}, + }, + } + kubelet.podManager.SetPods(pods) waitGroup.Add(1) err := kubelet.SyncPods(pods, emptyPodUIDs, map[string]api.Pod{}, time.Now()) @@ -477,7 +506,14 @@ func TestSyncPodsDoesNothing(t *testing.T) { t.Errorf("unexpected error: %v", err) } waitGroup.Wait() - verifyCalls(t, fakeDocker, []string{"list", "list", "list", "inspect_container", "inspect_container", "list", "inspect_container", "inspect_container"}) + verifyCalls(t, fakeDocker, []string{ + "list", "list", + // Check the pod infra contianer. + "inspect_container", + // Get pod status. + "list", "inspect_container", "inspect_container", + // Get pod status. + "list", "inspect_container", "inspect_container"}) } func TestSyncPodsWithTerminationLog(t *testing.T) { @@ -513,7 +549,15 @@ func TestSyncPodsWithTerminationLog(t *testing.T) { } waitGroup.Wait() verifyCalls(t, fakeDocker, []string{ - "list", "list", "list", "inspect_image", "create", "start", "inspect_container", "create", "start", "list", "inspect_container", "inspect_container"}) + "list", "list", + // Get pod status. + "list", "inspect_image", + // Create pod infra container. + "create", "start", "inspect_container", + // Create container. + "create", "start", + // Get pod status. + "list", "inspect_container", "inspect_container"}) fakeDocker.Lock() parts := strings.Split(fakeDocker.Container.HostConfig.Binds[0], ":") @@ -565,7 +609,15 @@ func TestSyncPodsCreatesNetAndContainer(t *testing.T) { waitGroup.Wait() verifyCalls(t, fakeDocker, []string{ - "list", "list", "list", "inspect_image", "create", "start", "inspect_container", "create", "start", "list", "inspect_container", "inspect_container"}) + "list", "list", + // Get pod status. + "list", "inspect_image", + // Create pod infra container. + "create", "start", "inspect_container", + // Create container. + "create", "start", + // Get pod status. + "list", "inspect_container", "inspect_container"}) fakeDocker.Lock() @@ -620,7 +672,15 @@ func TestSyncPodsCreatesNetAndContainerPullsImage(t *testing.T) { waitGroup.Wait() verifyCalls(t, fakeDocker, []string{ - "list", "list", "list", "inspect_image", "create", "start", "inspect_container", "create", "start", "list", "inspect_container", "inspect_container"}) + "list", "list", + // Get pod status. + "list", "inspect_image", + // Create pod infra container. + "create", "start", "inspect_container", + // Create container. + "create", "start", + // Get pod status. + "list", "inspect_container", "inspect_container"}) fakeDocker.Lock() @@ -642,13 +702,6 @@ func TestSyncPodsWithPodInfraCreatesContainer(t *testing.T) { kubelet := testKubelet.kubelet fakeDocker := testKubelet.fakeDocker waitGroup := testKubelet.waitGroup - fakeDocker.ContainerList = []docker.APIContainers{ - { - // pod infra container - Names: []string{"/k8s_POD_foo_new_12345678_0"}, - ID: "9876", - }, - } pods := []api.Pod{ { ObjectMeta: api.ObjectMeta{ @@ -663,6 +716,20 @@ func TestSyncPodsWithPodInfraCreatesContainer(t *testing.T) { }, }, } + fakeDocker.ContainerList = []docker.APIContainers{ + { + // pod infra container + Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(&pods[0]), 16) + "_foo_new_12345678_0"}, + ID: "9876", + }, + } + fakeDocker.ContainerMap = map[string]*docker.Container{ + "9876": { + ID: "9876", + Config: &docker.Config{}, + HostConfig: &docker.HostConfig{}, + }, + } waitGroup.Add(1) kubelet.podManager.SetPods(pods) err := kubelet.SyncPods(pods, emptyPodUIDs, map[string]api.Pod{}, time.Now()) @@ -672,7 +739,15 @@ func TestSyncPodsWithPodInfraCreatesContainer(t *testing.T) { waitGroup.Wait() verifyCalls(t, fakeDocker, []string{ - "list", "list", "list", "inspect_container", "inspect_image", "create", "start", "list", "inspect_container", "inspect_container"}) + "list", "list", + // Check the pod infra container. + "inspect_container", + // Get pod status. + "list", "inspect_container", "inspect_image", + // Create container. + "create", "start", + // Get pod status. + "list", "inspect_container", "inspect_container"}) fakeDocker.Lock() if len(fakeDocker.Created) != 1 || @@ -690,13 +765,6 @@ func TestSyncPodsWithPodInfraCreatesContainerCallsHandler(t *testing.T) { waitGroup := testKubelet.waitGroup fakeHttp := fakeHTTP{} kubelet.httpClient = &fakeHttp - fakeDocker.ContainerList = []docker.APIContainers{ - { - // pod infra container - Names: []string{"/k8s_POD_foo_new_12345678_0"}, - ID: "9876", - }, - } pods := []api.Pod{ { ObjectMeta: api.ObjectMeta{ @@ -722,6 +790,20 @@ func TestSyncPodsWithPodInfraCreatesContainerCallsHandler(t *testing.T) { }, }, } + fakeDocker.ContainerList = []docker.APIContainers{ + { + // pod infra container + Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(&pods[0]), 16) + "_foo_new_12345678_0"}, + ID: "9876", + }, + } + fakeDocker.ContainerMap = map[string]*docker.Container{ + "9876": { + ID: "9876", + Config: &docker.Config{}, + HostConfig: &docker.HostConfig{}, + }, + } waitGroup.Add(1) kubelet.podManager.SetPods(pods) err := kubelet.SyncPods(pods, emptyPodUIDs, map[string]api.Pod{}, time.Now()) @@ -731,7 +813,15 @@ func TestSyncPodsWithPodInfraCreatesContainerCallsHandler(t *testing.T) { waitGroup.Wait() verifyCalls(t, fakeDocker, []string{ - "list", "list", "list", "inspect_container", "inspect_image", "create", "start", "list", "inspect_container", "inspect_container"}) + "list", "list", + // Check the pod infra container. + "inspect_container", + // Get pod status. + "list", "inspect_container", "inspect_image", + // Create container. + "create", "start", + // Get pod status. + "list", "inspect_container", "inspect_container"}) fakeDocker.Lock() if len(fakeDocker.Created) != 1 || @@ -750,23 +840,7 @@ func TestSyncPodsDeletesWithNoPodInfraContainer(t *testing.T) { kubelet := testKubelet.kubelet fakeDocker := testKubelet.fakeDocker waitGroup := testKubelet.waitGroup - fakeDocker.ContainerList = []docker.APIContainers{ - { - // format is // k8s___ - Names: []string{"/k8s_bar1_foo1_new_12345678_0"}, - ID: "1234", - }, - { - // format is // k8s___ - Names: []string{"/k8s_bar2_foo2_new_87654321_0"}, - ID: "5678", - }, - { - // format is // k8s___ - Names: []string{"/k8s_POD_foo2_new_87654321_0"}, - ID: "8765", - }, - } + pods := []api.Pod{ { ObjectMeta: api.ObjectMeta{ @@ -793,6 +867,41 @@ func TestSyncPodsDeletesWithNoPodInfraContainer(t *testing.T) { }, }, } + fakeDocker.ContainerList = []docker.APIContainers{ + { + // format is // k8s___ + Names: []string{"/k8s_bar1_foo1_new_12345678_0"}, + ID: "1234", + }, + { + // format is // k8s___ + Names: []string{"/k8s_bar2_foo2_new_87654321_0"}, + ID: "5678", + }, + { + // format is // k8s___ + Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(&pods[0]), 16) + "_foo2_new_87654321_0"}, + ID: "8765", + }, + } + fakeDocker.ContainerMap = map[string]*docker.Container{ + "1234": { + ID: "1234", + Config: &docker.Config{}, + HostConfig: &docker.HostConfig{}, + }, + "5678": { + ID: "5678", + Config: &docker.Config{}, + HostConfig: &docker.HostConfig{}, + }, + "8765": { + ID: "8765", + Config: &docker.Config{}, + HostConfig: &docker.HostConfig{}, + }, + } + waitGroup.Add(2) kubelet.podManager.SetPods(pods) err := kubelet.SyncPods(pods, emptyPodUIDs, map[string]api.Pod{}, time.Now()) @@ -804,11 +913,26 @@ func TestSyncPodsDeletesWithNoPodInfraContainer(t *testing.T) { verifyUnorderedCalls(t, fakeDocker, []string{ "list", // foo1 - "list", "list", "inspect_container", "stop", "create", "start", "inspect_container", "create", "start", "list", "inspect_container", "inspect_container", + "list", + // Get pod status. + "list", "inspect_container", + // Kill the container since pod infra container is not running. + "stop", + // Create pod infra container. + "create", "start", "inspect_container", + // Create container. + "create", "start", + // Get pod status. + "list", "inspect_container", "inspect_container", "inspect_container", // foo2 - "list", "list", "inspect_container", "inspect_container", "list", "inspect_container", "inspect_container", - }) + "list", + // Check the pod infra container. + "inspect_container", + // Get pod status. + "list", "inspect_container", "inspect_container", + // Get pod status. + "list", "inspect_container", "inspect_container"}) // A map iteration is used to delete containers, so must not depend on // order here. @@ -909,153 +1033,231 @@ func TestSyncPodsDeletes(t *testing.T) { } } -func TestSyncPodDeletesDuplicate(t *testing.T) { +func TestSyncPodsDeletesDuplicate(t *testing.T) { testKubelet := newTestKubelet(t) + testKubelet.fakeCadvisor.On("MachineInfo").Return(&cadvisorApi.MachineInfo{}, nil) kubelet := testKubelet.kubelet fakeDocker := testKubelet.fakeDocker - dockerContainers := dockertools.DockerContainers{ - "1234": &docker.APIContainers{ + waitGroup := testKubelet.waitGroup + + pods := []api.Pod{ + { + ObjectMeta: api.ObjectMeta{ + UID: "12345678", + Name: "bar", + Namespace: "new", + }, + Spec: api.PodSpec{ + Containers: []api.Container{ + {Name: "foo"}, + }, + }, + }, + } + + fakeDocker.ContainerList = []docker.APIContainers{ + { // the k8s prefix is required for the kubelet to manage the container Names: []string{"/k8s_foo_bar_new_12345678_1111"}, ID: "1234", }, - "9876": &docker.APIContainers{ + { // pod infra container - Names: []string{"/k8s_POD_bar_new_12345678_2222"}, + Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(&pods[0]), 16) + "_bar_new_12345678_2222"}, ID: "9876", }, - "4567": &docker.APIContainers{ + { // Duplicate for the same container. Names: []string{"/k8s_foo_bar_new_12345678_3333"}, ID: "4567", }, } - bound := api.Pod{ - ObjectMeta: api.ObjectMeta{ - UID: "12345678", - Name: "bar", - Namespace: "new", + fakeDocker.ContainerMap = map[string]*docker.Container{ + "1234": { + ID: "1234", + Config: &docker.Config{}, + HostConfig: &docker.HostConfig{}, }, - Spec: api.PodSpec{ - Containers: []api.Container{ - {Name: "foo"}, - }, + "9876": { + ID: "9876", + Config: &docker.Config{}, + HostConfig: &docker.HostConfig{}, + }, + "4567": { + ID: "4567", + Config: &docker.Config{}, + HostConfig: &docker.HostConfig{}, }, } - pods := []api.Pod{bound} + kubelet.podManager.SetPods(pods) - err := kubelet.syncPod(&bound, nil, dockerContainersToPod(dockerContainers)) + waitGroup.Add(1) + err := kubelet.SyncPods(pods, emptyPodUIDs, map[string]api.Pod{}, time.Now()) if err != nil { t.Errorf("unexpected error: %v", err) } + waitGroup.Wait() - verifyCalls(t, fakeDocker, []string{"list", "inspect_image", "stop", "list", "inspect_image"}) + verifyCalls(t, fakeDocker, []string{ + "list", "list", + // Check the pod infra container. + "inspect_container", + // Get pod status. + "list", "inspect_container", "inspect_container", "inspect_container", + // Kill the duplicated container. + "stop", + // Get pod status. + "list", "inspect_container", "inspect_container", "inspect_container"}) // Expect one of the duplicates to be killed. if len(fakeDocker.Stopped) != 1 || (fakeDocker.Stopped[0] != "1234" && fakeDocker.Stopped[0] != "4567") { t.Errorf("Wrong containers were stopped: %v", fakeDocker.Stopped) } } -func TestSyncPodBadHash(t *testing.T) { +func TestSyncPodsBadHash(t *testing.T) { testKubelet := newTestKubelet(t) + testKubelet.fakeCadvisor.On("MachineInfo").Return(&cadvisorApi.MachineInfo{}, nil) kubelet := testKubelet.kubelet fakeDocker := testKubelet.fakeDocker - dockerContainers := dockertools.DockerContainers{ - "1234": &docker.APIContainers{ + waitGroup := testKubelet.waitGroup + + pods := []api.Pod{ + { + ObjectMeta: api.ObjectMeta{ + UID: "12345678", + Name: "foo", + Namespace: "new", + }, + Spec: api.PodSpec{ + Containers: []api.Container{ + {Name: "bar"}, + }, + }, + }, + } + + fakeDocker.ContainerList = []docker.APIContainers{ + { // the k8s prefix is required for the kubelet to manage the container Names: []string{"/k8s_bar.1234_foo_new_12345678_42"}, ID: "1234", }, - "9876": &docker.APIContainers{ + { // pod infra container - Names: []string{"/k8s_POD_foo_new_12345678_42"}, + Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(&pods[0]), 16) + "_foo_new_12345678_42"}, ID: "9876", }, } - bound := api.Pod{ - ObjectMeta: api.ObjectMeta{ - UID: "12345678", - Name: "foo", - Namespace: "new", + fakeDocker.ContainerMap = map[string]*docker.Container{ + "1234": { + ID: "1234", + Config: &docker.Config{}, + HostConfig: &docker.HostConfig{}, }, - Spec: api.PodSpec{ - Containers: []api.Container{ - {Name: "bar"}, - }, + "9876": { + ID: "9876", + Config: &docker.Config{}, + HostConfig: &docker.HostConfig{}, }, } - pods := []api.Pod{bound} + kubelet.podManager.SetPods(pods) - err := kubelet.syncPod(&bound, nil, dockerContainersToPod(dockerContainers)) + waitGroup.Add(1) + err := kubelet.SyncPods(pods, emptyPodUIDs, map[string]api.Pod{}, time.Now()) if err != nil { t.Errorf("unexpected error: %v", err) } + waitGroup.Wait() - verifyCalls(t, fakeDocker, []string{"list", "inspect_image", "stop", "stop", "create", "start", - "inspect_container", "create", "start", "list", "inspect_container", "inspect_container"}) + verifyCalls(t, fakeDocker, []string{ + "list", "list", + // Check the pod infra container. + "inspect_container", + // Get pod status. + "list", "inspect_container", "inspect_container", + // Kill and restart the bad hash container. + "stop", "create", "start", + // Get pod status. + "list", "inspect_container", "inspect_container", "inspect_container"}) - // A map interation is used to delete containers, so must not depend on - // order here. - expectedToStop := map[string]bool{ - "1234": true, - "9876": true, - } - if len(fakeDocker.Stopped) != 2 || - (!expectedToStop[fakeDocker.Stopped[0]] && - !expectedToStop[fakeDocker.Stopped[1]]) { - t.Errorf("Wrong containers were stopped: %v", fakeDocker.Stopped) + if err := fakeDocker.AssertStopped([]string{"1234"}); err != nil { + t.Errorf("%v", err) } } -func TestSyncPodUnhealthy(t *testing.T) { +func TestSyncPodsUnhealthy(t *testing.T) { testKubelet := newTestKubelet(t) + testKubelet.fakeCadvisor.On("MachineInfo").Return(&cadvisorApi.MachineInfo{}, nil) kubelet := testKubelet.kubelet fakeDocker := testKubelet.fakeDocker - dockerContainers := dockertools.DockerContainers{ - "1234": &docker.APIContainers{ - // the k8s prefix is required for the kubelet to manage the container - Names: []string{"/k8s_bar_foo_new_12345678_42"}, - ID: "1234", - }, - "9876": &docker.APIContainers{ - // pod infra container - Names: []string{"/k8s_POD_foo_new_12345678_42"}, - ID: "9876", - }, - } - bound := api.Pod{ - ObjectMeta: api.ObjectMeta{ - UID: "12345678", - Name: "foo", - Namespace: "new", - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - {Name: "bar", - LivenessProbe: &api.Probe{ - // Always returns healthy == false + waitGroup := testKubelet.waitGroup + + pods := []api.Pod{ + { + ObjectMeta: api.ObjectMeta{ + UID: "12345678", + Name: "foo", + Namespace: "new", + }, + Spec: api.PodSpec{ + Containers: []api.Container{ + {Name: "bar", + LivenessProbe: &api.Probe{ + // Always returns healthy == false + }, }, }, }, }, } - pods := []api.Pod{bound} + + fakeDocker.ContainerList = []docker.APIContainers{ + { + // the k8s prefix is required for the kubelet to manage the container + Names: []string{"/k8s_bar_foo_new_12345678_42"}, + ID: "1234", + }, + { + // pod infra container + Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(&pods[0]), 16) + "_foo_new_12345678_42"}, + ID: "9876", + }, + } + fakeDocker.ContainerMap = map[string]*docker.Container{ + "1234": { + ID: "1234", + Config: &docker.Config{}, + HostConfig: &docker.HostConfig{}, + }, + "9876": { + ID: "9876", + Config: &docker.Config{}, + HostConfig: &docker.HostConfig{}, + }, + } kubelet.podManager.SetPods(pods) - err := kubelet.syncPod(&bound, nil, dockerContainersToPod(dockerContainers)) + waitGroup.Add(1) + err := kubelet.SyncPods(pods, emptyPodUIDs, map[string]api.Pod{}, time.Now()) if err != nil { t.Errorf("unexpected error: %v", err) } + waitGroup.Wait() - verifyCalls(t, fakeDocker, []string{"list", "inspect_image", "stop", "create", "start", "list", "inspect_container"}) + verifyCalls(t, fakeDocker, []string{ + "list", "list", + // Check the pod infra container. + "inspect_container", + // Get pod status. + "list", "inspect_container", "inspect_container", + // Kill the unhealthy container. + "stop", + // Restart the unhealthy container. + "create", "start", + // Get pod status. + "list", "inspect_container", "inspect_container", "inspect_container"}) - // A map interation is used to delete containers, so must not depend on - // order here. - expectedToStop := map[string]bool{ - "1234": true, - } - if len(fakeDocker.Stopped) != len(expectedToStop) || - !expectedToStop[fakeDocker.Stopped[0]] { - t.Errorf("Wrong containers were stopped: %v", fakeDocker.Stopped) + if err := fakeDocker.AssertStopped([]string{"1234"}); err != nil { + t.Errorf("%v", err) } } @@ -1597,33 +1799,32 @@ func TestNewHandler(t *testing.T) { func TestSyncPodEventHandlerFails(t *testing.T) { testKubelet := newTestKubelet(t) + testKubelet.fakeCadvisor.On("MachineInfo").Return(&cadvisorApi.MachineInfo{}, nil) kubelet := testKubelet.kubelet fakeDocker := testKubelet.fakeDocker + waitGroup := testKubelet.waitGroup + kubelet.httpClient = &fakeHTTP{ err: fmt.Errorf("test error"), } - dockerContainers := dockertools.DockerContainers{ - "9876": &docker.APIContainers{ - // pod infra container - Names: []string{"/k8s_POD_foo_new_12345678_42"}, - ID: "9876", - }, - } - bound := api.Pod{ - ObjectMeta: api.ObjectMeta{ - UID: "12345678", - Name: "foo", - Namespace: "new", - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - {Name: "bar", - Lifecycle: &api.Lifecycle{ - PostStart: &api.Handler{ - HTTPGet: &api.HTTPGetAction{ - Host: "does.no.exist", - Port: util.IntOrString{IntVal: 8080, Kind: util.IntstrInt}, - Path: "bar", + + pods := []api.Pod{ + { + ObjectMeta: api.ObjectMeta{ + UID: "12345678", + Name: "foo", + Namespace: "new", + }, + Spec: api.PodSpec{ + Containers: []api.Container{ + {Name: "bar", + Lifecycle: &api.Lifecycle{ + PostStart: &api.Handler{ + HTTPGet: &api.HTTPGetAction{ + Host: "does.no.exist", + Port: util.IntOrString{IntVal: 8080, Kind: util.IntstrInt}, + Path: "bar", + }, }, }, }, @@ -1631,18 +1832,53 @@ func TestSyncPodEventHandlerFails(t *testing.T) { }, }, } - pods := []api.Pod{bound} + + fakeDocker.ContainerList = []docker.APIContainers{ + { + // pod infra container + Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(&pods[0]), 16) + "_foo_new_12345678_42"}, + ID: "9876", + }, + } + fakeDocker.ContainerMap = map[string]*docker.Container{ + "9876": { + ID: "9876", + Config: &docker.Config{}, + HostConfig: &docker.HostConfig{}, + }, + } kubelet.podManager.SetPods(pods) - err := kubelet.syncPod(&bound, nil, dockerContainersToPod(dockerContainers)) + waitGroup.Add(1) + err := kubelet.SyncPods(pods, emptyPodUIDs, map[string]api.Pod{}, time.Now()) if err != nil { t.Errorf("unexpected error: %v", err) } + waitGroup.Wait() - verifyCalls(t, fakeDocker, []string{"list", "inspect_image", "create", "start", "stop", "list", "inspect_image"}) + verifyCalls(t, fakeDocker, []string{ + "list", "list", + // Check the pod infra container. + "inspect_container", + // Get pod status. + "list", "inspect_container", "inspect_image", + // Create the container. + "create", "start", + // Kill the container since event handler fails. + "stop", + // Get pod status. + "list", "inspect_container", "inspect_container"}) + // TODO(yifan): Check the stopped container's name. if len(fakeDocker.Stopped) != 1 { t.Errorf("Wrong containers were stopped: %v", fakeDocker.Stopped) } + dockerName, _, err := dockertools.ParseDockerName(fakeDocker.Stopped[0]) + if err != nil { + t.Errorf("Unexpected error: %v", err) + } + if dockerName.ContainerName != "bar" { + t.Errorf("Wrong stopped container, expected: bar, get: %q", dockerName.ContainerName) + } } func TestSyncPodsWithPullPolicy(t *testing.T) { @@ -3550,11 +3786,23 @@ func TestSyncPodsWithRestartPolicy(t *testing.T) { {Name: "succeeded"}, {Name: "failed"}, } + pods := []api.Pod{ + { + ObjectMeta: api.ObjectMeta{ + UID: "12345678", + Name: "foo", + Namespace: "new", + }, + Spec: api.PodSpec{ + Containers: containers, + }, + }, + } runningAPIContainers := []docker.APIContainers{ { // pod infra container - Names: []string{"/k8s_POD_foo_new_12345678_0"}, + Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(&pods[0]), 16) + "_foo_new_12345678_0"}, ID: "9876", }, } @@ -3572,6 +3820,15 @@ func TestSyncPodsWithRestartPolicy(t *testing.T) { } containerMap := map[string]*docker.Container{ + "9876": { + ID: "9876", + Name: "POD", + Config: &docker.Config{}, + State: docker.State{ + StartedAt: time.Now(), + Running: true, + }, + }, "1234": { ID: "1234", Name: "succeeded", @@ -3602,19 +3859,43 @@ func TestSyncPodsWithRestartPolicy(t *testing.T) { }{ { api.RestartPolicyAlways, - []string{"list", "list", "list", "inspect_container", "inspect_container", "inspect_container", "create", "start", "create", "start", "list", "inspect_container", "inspect_container", "inspect_container", "inspect_container", "inspect_container"}, + []string{"list", "list", + // Check the pod infra container. + "inspect_container", + // Get pod status. + "list", "inspect_container", "inspect_container", "inspect_container", + // Restart both containers. + "create", "start", "create", "start", + // Get pod status. + "list", "inspect_container", "inspect_container", "inspect_container", "inspect_container", "inspect_container"}, []string{"succeeded", "failed"}, []string{}, }, { api.RestartPolicyOnFailure, - []string{"list", "list", "list", "inspect_container", "inspect_container", "inspect_container", "create", "start", "list", "inspect_container", "inspect_container", "inspect_container", "inspect_container"}, + []string{"list", "list", + // Check the pod infra container. + "inspect_container", + // Get pod status. + "list", "inspect_container", "inspect_container", "inspect_container", + // Restart the failed container. + "create", "start", + // Get pod status. + "list", "inspect_container", "inspect_container", "inspect_container", "inspect_container"}, []string{"failed"}, []string{}, }, { api.RestartPolicyNever, - []string{"list", "list", "list", "inspect_container", "inspect_container", "inspect_container", "stop", "list", "inspect_container", "inspect_container"}, + []string{"list", "list", + // Check the pod infra container. + "inspect_container", + // Get pod status. + "list", "inspect_container", "inspect_container", "inspect_container", + // Stop the last pod infra container. + "stop", + // Get pod status. + "list", "inspect_container", "inspect_container", "inspect_container"}, []string{}, []string{"9876"}, }, @@ -3625,19 +3906,8 @@ func TestSyncPodsWithRestartPolicy(t *testing.T) { fakeDocker.ExitedContainerList = exitedAPIContainers fakeDocker.ContainerMap = containerMap fakeDocker.ClearCalls() - pods := []api.Pod{ - { - ObjectMeta: api.ObjectMeta{ - UID: "12345678", - Name: "foo", - Namespace: "new", - }, - Spec: api.PodSpec{ - Containers: containers, - RestartPolicy: tt.policy, - }, - }, - } + pods[0].Spec.RestartPolicy = tt.policy + kubelet.podManager.SetPods(pods) waitGroup.Add(1) err := kubelet.SyncPods(pods, emptyPodUIDs, map[string]api.Pod{}, time.Now()) @@ -3670,13 +3940,6 @@ func TestGetPodStatusWithLastTermination(t *testing.T) { {Name: "failed"}, } - runningAPIContainers := []docker.APIContainers{ - { - // pod infra container - Names: []string{"/k8s_POD_foo_new_12345678_0"}, - ID: "9876", - }, - } exitedAPIContainers := []docker.APIContainers{ { // format is // k8s___ @@ -3691,10 +3954,22 @@ func TestGetPodStatusWithLastTermination(t *testing.T) { } containerMap := map[string]*docker.Container{ + "9876": { + ID: "9876", + Name: "POD", + Config: &docker.Config{}, + HostConfig: &docker.HostConfig{}, + State: docker.State{ + StartedAt: time.Now(), + FinishedAt: time.Now(), + Running: true, + }, + }, "1234": { - ID: "1234", - Name: "succeeded", - Config: &docker.Config{}, + ID: "1234", + Name: "succeeded", + Config: &docker.Config{}, + HostConfig: &docker.HostConfig{}, State: docker.State{ ExitCode: 0, StartedAt: time.Now(), @@ -3702,9 +3977,10 @@ func TestGetPodStatusWithLastTermination(t *testing.T) { }, }, "5678": { - ID: "5678", - Name: "failed", - Config: &docker.Config{}, + ID: "5678", + Name: "failed", + Config: &docker.Config{}, + HostConfig: &docker.HostConfig{}, State: docker.State{ ExitCode: 42, StartedAt: time.Now(), @@ -3740,7 +4016,6 @@ func TestGetPodStatusWithLastTermination(t *testing.T) { } for i, tt := range tests { - fakeDocker.ContainerList = runningAPIContainers fakeDocker.ExitedContainerList = exitedAPIContainers fakeDocker.ContainerMap = containerMap fakeDocker.ClearCalls() @@ -3757,6 +4032,13 @@ func TestGetPodStatusWithLastTermination(t *testing.T) { }, }, } + fakeDocker.ContainerList = []docker.APIContainers{ + { + // pod infra container + Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(&pods[0]), 16) + "_foo_new_12345678_0"}, + ID: "9876", + }, + } kubelet.podManager.SetPods(pods) waitGroup.Add(1) err := kubelet.SyncPods(pods, emptyPodUIDs, map[string]api.Pod{}, time.Now()) @@ -3798,7 +4080,9 @@ func TestGetPodCreationFailureReason(t *testing.T) { kubelet := testKubelet.kubelet fakeDocker := testKubelet.fakeDocker failureReason := "creation failure" - fakeDocker.Errors["create"] = fmt.Errorf("%s", failureReason) + fakeDocker.Errors = map[string]error{ + "create": fmt.Errorf("%s", failureReason), + } fakeDocker.ContainerList = []docker.APIContainers{} pod := api.Pod{ ObjectMeta: api.ObjectMeta{