kubelet: Introduce PodInfraContainerChanged().

Update tests.
This commit is contained in:
Yifan Gu 2015-04-13 10:02:58 -07:00
parent d14cb8f1dd
commit 4cdb1bf9ce

View File

@ -70,7 +70,6 @@ type TestKubelet struct {
func newTestKubelet(t *testing.T) *TestKubelet { func newTestKubelet(t *testing.T) *TestKubelet {
fakeDocker := &dockertools.FakeDockerClient{Errors: make(map[string]error), RemovedImages: util.StringSet{}} fakeDocker := &dockertools.FakeDockerClient{Errors: make(map[string]error), RemovedImages: util.StringSet{}}
fakeRecorder := &record.FakeRecorder{} fakeRecorder := &record.FakeRecorder{}
fakeKubeClient := &testclient.Fake{} fakeKubeClient := &testclient.Fake{}
kubelet := &Kubelet{} kubelet := &Kubelet{}
@ -436,6 +435,22 @@ func TestKillContainer(t *testing.T) {
var emptyPodUIDs map[types.UID]metrics.SyncPodType 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) { func TestSyncPodsDoesNothing(t *testing.T) {
testKubelet := newTestKubelet(t) testKubelet := newTestKubelet(t)
testKubelet.fakeCadvisor.On("MachineInfo").Return(&cadvisorApi.MachineInfo{}, nil) testKubelet.fakeCadvisor.On("MachineInfo").Return(&cadvisorApi.MachineInfo{}, nil)
@ -444,18 +459,6 @@ func TestSyncPodsDoesNothing(t *testing.T) {
waitGroup := testKubelet.waitGroup waitGroup := testKubelet.waitGroup
container := api.Container{Name: "bar"} container := api.Container{Name: "bar"}
fakeDocker.ContainerList = []docker.APIContainers{
{
// format is // k8s_<container-id>_<pod-fullname>_<pod-uid>_<random>
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{ pods := []api.Pod{
{ {
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
@ -470,6 +473,32 @@ func TestSyncPodsDoesNothing(t *testing.T) {
}, },
}, },
} }
fakeDocker.ContainerList = []docker.APIContainers{
{
// format is // k8s_<container-id>_<pod-fullname>_<pod-uid>_<random>
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) kubelet.podManager.SetPods(pods)
waitGroup.Add(1) waitGroup.Add(1)
err := kubelet.SyncPods(pods, emptyPodUIDs, map[string]api.Pod{}, time.Now()) 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) t.Errorf("unexpected error: %v", err)
} }
waitGroup.Wait() 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) { func TestSyncPodsWithTerminationLog(t *testing.T) {
@ -513,7 +549,15 @@ func TestSyncPodsWithTerminationLog(t *testing.T) {
} }
waitGroup.Wait() waitGroup.Wait()
verifyCalls(t, fakeDocker, []string{ 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() fakeDocker.Lock()
parts := strings.Split(fakeDocker.Container.HostConfig.Binds[0], ":") parts := strings.Split(fakeDocker.Container.HostConfig.Binds[0], ":")
@ -565,7 +609,15 @@ func TestSyncPodsCreatesNetAndContainer(t *testing.T) {
waitGroup.Wait() waitGroup.Wait()
verifyCalls(t, fakeDocker, []string{ 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() fakeDocker.Lock()
@ -620,7 +672,15 @@ func TestSyncPodsCreatesNetAndContainerPullsImage(t *testing.T) {
waitGroup.Wait() waitGroup.Wait()
verifyCalls(t, fakeDocker, []string{ 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() fakeDocker.Lock()
@ -642,13 +702,6 @@ func TestSyncPodsWithPodInfraCreatesContainer(t *testing.T) {
kubelet := testKubelet.kubelet kubelet := testKubelet.kubelet
fakeDocker := testKubelet.fakeDocker fakeDocker := testKubelet.fakeDocker
waitGroup := testKubelet.waitGroup waitGroup := testKubelet.waitGroup
fakeDocker.ContainerList = []docker.APIContainers{
{
// pod infra container
Names: []string{"/k8s_POD_foo_new_12345678_0"},
ID: "9876",
},
}
pods := []api.Pod{ pods := []api.Pod{
{ {
ObjectMeta: api.ObjectMeta{ 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) waitGroup.Add(1)
kubelet.podManager.SetPods(pods) kubelet.podManager.SetPods(pods)
err := kubelet.SyncPods(pods, emptyPodUIDs, map[string]api.Pod{}, time.Now()) err := kubelet.SyncPods(pods, emptyPodUIDs, map[string]api.Pod{}, time.Now())
@ -672,7 +739,15 @@ func TestSyncPodsWithPodInfraCreatesContainer(t *testing.T) {
waitGroup.Wait() waitGroup.Wait()
verifyCalls(t, fakeDocker, []string{ 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() fakeDocker.Lock()
if len(fakeDocker.Created) != 1 || if len(fakeDocker.Created) != 1 ||
@ -690,13 +765,6 @@ func TestSyncPodsWithPodInfraCreatesContainerCallsHandler(t *testing.T) {
waitGroup := testKubelet.waitGroup waitGroup := testKubelet.waitGroup
fakeHttp := fakeHTTP{} fakeHttp := fakeHTTP{}
kubelet.httpClient = &fakeHttp kubelet.httpClient = &fakeHttp
fakeDocker.ContainerList = []docker.APIContainers{
{
// pod infra container
Names: []string{"/k8s_POD_foo_new_12345678_0"},
ID: "9876",
},
}
pods := []api.Pod{ pods := []api.Pod{
{ {
ObjectMeta: api.ObjectMeta{ 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) waitGroup.Add(1)
kubelet.podManager.SetPods(pods) kubelet.podManager.SetPods(pods)
err := kubelet.SyncPods(pods, emptyPodUIDs, map[string]api.Pod{}, time.Now()) err := kubelet.SyncPods(pods, emptyPodUIDs, map[string]api.Pod{}, time.Now())
@ -731,7 +813,15 @@ func TestSyncPodsWithPodInfraCreatesContainerCallsHandler(t *testing.T) {
waitGroup.Wait() waitGroup.Wait()
verifyCalls(t, fakeDocker, []string{ 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() fakeDocker.Lock()
if len(fakeDocker.Created) != 1 || if len(fakeDocker.Created) != 1 ||
@ -750,23 +840,7 @@ func TestSyncPodsDeletesWithNoPodInfraContainer(t *testing.T) {
kubelet := testKubelet.kubelet kubelet := testKubelet.kubelet
fakeDocker := testKubelet.fakeDocker fakeDocker := testKubelet.fakeDocker
waitGroup := testKubelet.waitGroup waitGroup := testKubelet.waitGroup
fakeDocker.ContainerList = []docker.APIContainers{
{
// format is // k8s_<container-id>_<pod-fullname>_<pod-uid>
Names: []string{"/k8s_bar1_foo1_new_12345678_0"},
ID: "1234",
},
{
// format is // k8s_<container-id>_<pod-fullname>_<pod-uid>
Names: []string{"/k8s_bar2_foo2_new_87654321_0"},
ID: "5678",
},
{
// format is // k8s_<container-id>_<pod-fullname>_<pod-uid>
Names: []string{"/k8s_POD_foo2_new_87654321_0"},
ID: "8765",
},
}
pods := []api.Pod{ pods := []api.Pod{
{ {
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{
@ -793,6 +867,41 @@ func TestSyncPodsDeletesWithNoPodInfraContainer(t *testing.T) {
}, },
}, },
} }
fakeDocker.ContainerList = []docker.APIContainers{
{
// format is // k8s_<container-id>_<pod-fullname>_<pod-uid>
Names: []string{"/k8s_bar1_foo1_new_12345678_0"},
ID: "1234",
},
{
// format is // k8s_<container-id>_<pod-fullname>_<pod-uid>
Names: []string{"/k8s_bar2_foo2_new_87654321_0"},
ID: "5678",
},
{
// format is // k8s_<container-id>_<pod-fullname>_<pod-uid>
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) waitGroup.Add(2)
kubelet.podManager.SetPods(pods) kubelet.podManager.SetPods(pods)
err := kubelet.SyncPods(pods, emptyPodUIDs, map[string]api.Pod{}, time.Now()) err := kubelet.SyncPods(pods, emptyPodUIDs, map[string]api.Pod{}, time.Now())
@ -804,11 +913,26 @@ func TestSyncPodsDeletesWithNoPodInfraContainer(t *testing.T) {
verifyUnorderedCalls(t, fakeDocker, []string{ verifyUnorderedCalls(t, fakeDocker, []string{
"list", "list",
// foo1 // 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 // 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 // A map iteration is used to delete containers, so must not depend on
// order here. // 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 := newTestKubelet(t)
testKubelet.fakeCadvisor.On("MachineInfo").Return(&cadvisorApi.MachineInfo{}, nil)
kubelet := testKubelet.kubelet kubelet := testKubelet.kubelet
fakeDocker := testKubelet.fakeDocker fakeDocker := testKubelet.fakeDocker
dockerContainers := dockertools.DockerContainers{ waitGroup := testKubelet.waitGroup
"1234": &docker.APIContainers{
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 // the k8s prefix is required for the kubelet to manage the container
Names: []string{"/k8s_foo_bar_new_12345678_1111"}, Names: []string{"/k8s_foo_bar_new_12345678_1111"},
ID: "1234", ID: "1234",
}, },
"9876": &docker.APIContainers{ {
// pod infra container // 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", ID: "9876",
}, },
"4567": &docker.APIContainers{ {
// Duplicate for the same container. // Duplicate for the same container.
Names: []string{"/k8s_foo_bar_new_12345678_3333"}, Names: []string{"/k8s_foo_bar_new_12345678_3333"},
ID: "4567", ID: "4567",
}, },
} }
bound := api.Pod{ fakeDocker.ContainerMap = map[string]*docker.Container{
ObjectMeta: api.ObjectMeta{ "1234": {
UID: "12345678", ID: "1234",
Name: "bar", Config: &docker.Config{},
Namespace: "new", HostConfig: &docker.HostConfig{},
}, },
Spec: api.PodSpec{ "9876": {
Containers: []api.Container{ ID: "9876",
{Name: "foo"}, Config: &docker.Config{},
}, HostConfig: &docker.HostConfig{},
},
"4567": {
ID: "4567",
Config: &docker.Config{},
HostConfig: &docker.HostConfig{},
}, },
} }
pods := []api.Pod{bound}
kubelet.podManager.SetPods(pods) 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 { if err != nil {
t.Errorf("unexpected error: %v", err) 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. // Expect one of the duplicates to be killed.
if len(fakeDocker.Stopped) != 1 || (fakeDocker.Stopped[0] != "1234" && fakeDocker.Stopped[0] != "4567") { if len(fakeDocker.Stopped) != 1 || (fakeDocker.Stopped[0] != "1234" && fakeDocker.Stopped[0] != "4567") {
t.Errorf("Wrong containers were stopped: %v", fakeDocker.Stopped) t.Errorf("Wrong containers were stopped: %v", fakeDocker.Stopped)
} }
} }
func TestSyncPodBadHash(t *testing.T) { func TestSyncPodsBadHash(t *testing.T) {
testKubelet := newTestKubelet(t) testKubelet := newTestKubelet(t)
testKubelet.fakeCadvisor.On("MachineInfo").Return(&cadvisorApi.MachineInfo{}, nil)
kubelet := testKubelet.kubelet kubelet := testKubelet.kubelet
fakeDocker := testKubelet.fakeDocker fakeDocker := testKubelet.fakeDocker
dockerContainers := dockertools.DockerContainers{ waitGroup := testKubelet.waitGroup
"1234": &docker.APIContainers{
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 // the k8s prefix is required for the kubelet to manage the container
Names: []string{"/k8s_bar.1234_foo_new_12345678_42"}, Names: []string{"/k8s_bar.1234_foo_new_12345678_42"},
ID: "1234", ID: "1234",
}, },
"9876": &docker.APIContainers{ {
// pod infra container // 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", ID: "9876",
}, },
} }
bound := api.Pod{ fakeDocker.ContainerMap = map[string]*docker.Container{
ObjectMeta: api.ObjectMeta{ "1234": {
UID: "12345678", ID: "1234",
Name: "foo", Config: &docker.Config{},
Namespace: "new", HostConfig: &docker.HostConfig{},
}, },
Spec: api.PodSpec{ "9876": {
Containers: []api.Container{ ID: "9876",
{Name: "bar"}, Config: &docker.Config{},
}, HostConfig: &docker.HostConfig{},
}, },
} }
pods := []api.Pod{bound}
kubelet.podManager.SetPods(pods) 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 { if err != nil {
t.Errorf("unexpected error: %v", err) t.Errorf("unexpected error: %v", err)
} }
waitGroup.Wait()
verifyCalls(t, fakeDocker, []string{"list", "inspect_image", "stop", "stop", "create", "start", verifyCalls(t, fakeDocker, []string{
"inspect_container", "create", "start", "list", "inspect_container", "inspect_container"}) "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 if err := fakeDocker.AssertStopped([]string{"1234"}); err != nil {
// order here. t.Errorf("%v", err)
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)
} }
} }
func TestSyncPodUnhealthy(t *testing.T) { func TestSyncPodsUnhealthy(t *testing.T) {
testKubelet := newTestKubelet(t) testKubelet := newTestKubelet(t)
testKubelet.fakeCadvisor.On("MachineInfo").Return(&cadvisorApi.MachineInfo{}, nil)
kubelet := testKubelet.kubelet kubelet := testKubelet.kubelet
fakeDocker := testKubelet.fakeDocker fakeDocker := testKubelet.fakeDocker
dockerContainers := dockertools.DockerContainers{ waitGroup := testKubelet.waitGroup
"1234": &docker.APIContainers{
// the k8s prefix is required for the kubelet to manage the container pods := []api.Pod{
Names: []string{"/k8s_bar_foo_new_12345678_42"}, {
ID: "1234", ObjectMeta: api.ObjectMeta{
}, UID: "12345678",
"9876": &docker.APIContainers{ Name: "foo",
// pod infra container Namespace: "new",
Names: []string{"/k8s_POD_foo_new_12345678_42"}, },
ID: "9876", Spec: api.PodSpec{
}, Containers: []api.Container{
} {Name: "bar",
bound := api.Pod{ LivenessProbe: &api.Probe{
ObjectMeta: api.ObjectMeta{ // Always returns healthy == false
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) 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 { if err != nil {
t.Errorf("unexpected error: %v", err) 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 if err := fakeDocker.AssertStopped([]string{"1234"}); err != nil {
// order here. t.Errorf("%v", err)
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)
} }
} }
@ -1597,33 +1799,32 @@ func TestNewHandler(t *testing.T) {
func TestSyncPodEventHandlerFails(t *testing.T) { func TestSyncPodEventHandlerFails(t *testing.T) {
testKubelet := newTestKubelet(t) testKubelet := newTestKubelet(t)
testKubelet.fakeCadvisor.On("MachineInfo").Return(&cadvisorApi.MachineInfo{}, nil)
kubelet := testKubelet.kubelet kubelet := testKubelet.kubelet
fakeDocker := testKubelet.fakeDocker fakeDocker := testKubelet.fakeDocker
waitGroup := testKubelet.waitGroup
kubelet.httpClient = &fakeHTTP{ kubelet.httpClient = &fakeHTTP{
err: fmt.Errorf("test error"), err: fmt.Errorf("test error"),
} }
dockerContainers := dockertools.DockerContainers{
"9876": &docker.APIContainers{ pods := []api.Pod{
// pod infra container {
Names: []string{"/k8s_POD_foo_new_12345678_42"}, ObjectMeta: api.ObjectMeta{
ID: "9876", UID: "12345678",
}, Name: "foo",
} Namespace: "new",
bound := api.Pod{ },
ObjectMeta: api.ObjectMeta{ Spec: api.PodSpec{
UID: "12345678", Containers: []api.Container{
Name: "foo", {Name: "bar",
Namespace: "new", Lifecycle: &api.Lifecycle{
}, PostStart: &api.Handler{
Spec: api.PodSpec{ HTTPGet: &api.HTTPGetAction{
Containers: []api.Container{ Host: "does.no.exist",
{Name: "bar", Port: util.IntOrString{IntVal: 8080, Kind: util.IntstrInt},
Lifecycle: &api.Lifecycle{ Path: "bar",
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) 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 { if err != nil {
t.Errorf("unexpected error: %v", err) 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 { if len(fakeDocker.Stopped) != 1 {
t.Errorf("Wrong containers were stopped: %v", fakeDocker.Stopped) 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) { func TestSyncPodsWithPullPolicy(t *testing.T) {
@ -3550,11 +3786,23 @@ func TestSyncPodsWithRestartPolicy(t *testing.T) {
{Name: "succeeded"}, {Name: "succeeded"},
{Name: "failed"}, {Name: "failed"},
} }
pods := []api.Pod{
{
ObjectMeta: api.ObjectMeta{
UID: "12345678",
Name: "foo",
Namespace: "new",
},
Spec: api.PodSpec{
Containers: containers,
},
},
}
runningAPIContainers := []docker.APIContainers{ runningAPIContainers := []docker.APIContainers{
{ {
// pod infra container // 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", ID: "9876",
}, },
} }
@ -3572,6 +3820,15 @@ func TestSyncPodsWithRestartPolicy(t *testing.T) {
} }
containerMap := map[string]*docker.Container{ containerMap := map[string]*docker.Container{
"9876": {
ID: "9876",
Name: "POD",
Config: &docker.Config{},
State: docker.State{
StartedAt: time.Now(),
Running: true,
},
},
"1234": { "1234": {
ID: "1234", ID: "1234",
Name: "succeeded", Name: "succeeded",
@ -3602,19 +3859,43 @@ func TestSyncPodsWithRestartPolicy(t *testing.T) {
}{ }{
{ {
api.RestartPolicyAlways, 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{"succeeded", "failed"},
[]string{}, []string{},
}, },
{ {
api.RestartPolicyOnFailure, 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{"failed"},
[]string{}, []string{},
}, },
{ {
api.RestartPolicyNever, 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{},
[]string{"9876"}, []string{"9876"},
}, },
@ -3625,19 +3906,8 @@ func TestSyncPodsWithRestartPolicy(t *testing.T) {
fakeDocker.ExitedContainerList = exitedAPIContainers fakeDocker.ExitedContainerList = exitedAPIContainers
fakeDocker.ContainerMap = containerMap fakeDocker.ContainerMap = containerMap
fakeDocker.ClearCalls() fakeDocker.ClearCalls()
pods := []api.Pod{ pods[0].Spec.RestartPolicy = tt.policy
{
ObjectMeta: api.ObjectMeta{
UID: "12345678",
Name: "foo",
Namespace: "new",
},
Spec: api.PodSpec{
Containers: containers,
RestartPolicy: tt.policy,
},
},
}
kubelet.podManager.SetPods(pods) kubelet.podManager.SetPods(pods)
waitGroup.Add(1) waitGroup.Add(1)
err := kubelet.SyncPods(pods, emptyPodUIDs, map[string]api.Pod{}, time.Now()) err := kubelet.SyncPods(pods, emptyPodUIDs, map[string]api.Pod{}, time.Now())
@ -3670,13 +3940,6 @@ func TestGetPodStatusWithLastTermination(t *testing.T) {
{Name: "failed"}, {Name: "failed"},
} }
runningAPIContainers := []docker.APIContainers{
{
// pod infra container
Names: []string{"/k8s_POD_foo_new_12345678_0"},
ID: "9876",
},
}
exitedAPIContainers := []docker.APIContainers{ exitedAPIContainers := []docker.APIContainers{
{ {
// format is // k8s_<container-id>_<pod-fullname>_<pod-uid> // format is // k8s_<container-id>_<pod-fullname>_<pod-uid>
@ -3691,10 +3954,22 @@ func TestGetPodStatusWithLastTermination(t *testing.T) {
} }
containerMap := map[string]*docker.Container{ 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": { "1234": {
ID: "1234", ID: "1234",
Name: "succeeded", Name: "succeeded",
Config: &docker.Config{}, Config: &docker.Config{},
HostConfig: &docker.HostConfig{},
State: docker.State{ State: docker.State{
ExitCode: 0, ExitCode: 0,
StartedAt: time.Now(), StartedAt: time.Now(),
@ -3702,9 +3977,10 @@ func TestGetPodStatusWithLastTermination(t *testing.T) {
}, },
}, },
"5678": { "5678": {
ID: "5678", ID: "5678",
Name: "failed", Name: "failed",
Config: &docker.Config{}, Config: &docker.Config{},
HostConfig: &docker.HostConfig{},
State: docker.State{ State: docker.State{
ExitCode: 42, ExitCode: 42,
StartedAt: time.Now(), StartedAt: time.Now(),
@ -3740,7 +4016,6 @@ func TestGetPodStatusWithLastTermination(t *testing.T) {
} }
for i, tt := range tests { for i, tt := range tests {
fakeDocker.ContainerList = runningAPIContainers
fakeDocker.ExitedContainerList = exitedAPIContainers fakeDocker.ExitedContainerList = exitedAPIContainers
fakeDocker.ContainerMap = containerMap fakeDocker.ContainerMap = containerMap
fakeDocker.ClearCalls() 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) kubelet.podManager.SetPods(pods)
waitGroup.Add(1) waitGroup.Add(1)
err := kubelet.SyncPods(pods, emptyPodUIDs, map[string]api.Pod{}, time.Now()) err := kubelet.SyncPods(pods, emptyPodUIDs, map[string]api.Pod{}, time.Now())
@ -3798,7 +4080,9 @@ func TestGetPodCreationFailureReason(t *testing.T) {
kubelet := testKubelet.kubelet kubelet := testKubelet.kubelet
fakeDocker := testKubelet.fakeDocker fakeDocker := testKubelet.fakeDocker
failureReason := "creation failure" failureReason := "creation failure"
fakeDocker.Errors["create"] = fmt.Errorf("%s", failureReason) fakeDocker.Errors = map[string]error{
"create": fmt.Errorf("%s", failureReason),
}
fakeDocker.ContainerList = []docker.APIContainers{} fakeDocker.ContainerList = []docker.APIContainers{}
pod := api.Pod{ pod := api.Pod{
ObjectMeta: api.ObjectMeta{ ObjectMeta: api.ObjectMeta{