mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-25 12:43:23 +00:00
Merge pull request #8844 from yujuhong/kubelet_unittest
Kubelet: clean up unit tests
This commit is contained in:
commit
9ca4fb40dc
@ -18,6 +18,7 @@ package container
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"reflect"
|
"reflect"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@ -30,17 +31,39 @@ import (
|
|||||||
type FakeRuntime struct {
|
type FakeRuntime struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
CalledFunctions []string
|
CalledFunctions []string
|
||||||
Podlist []*Pod
|
PodList []*Pod
|
||||||
ContainerList []*Container
|
ContainerList []*Container
|
||||||
|
ImageList []Image
|
||||||
PodStatus api.PodStatus
|
PodStatus api.PodStatus
|
||||||
StartedPods []string
|
StartedPods []string
|
||||||
KilledPods []string
|
KilledPods []string
|
||||||
StartedContainers []string
|
StartedContainers []string
|
||||||
KilledContainers []string
|
KilledContainers []string
|
||||||
VersionInfo map[string]string
|
VersionInfo string
|
||||||
Err error
|
Err error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FakeRuntime should implement Runtime.
|
||||||
|
var _ Runtime = &FakeRuntime{}
|
||||||
|
|
||||||
|
type FakeVersion struct {
|
||||||
|
Version string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fv *FakeVersion) String() string {
|
||||||
|
return fv.Version
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fv *FakeVersion) Compare(other string) (int, error) {
|
||||||
|
result := 0
|
||||||
|
if fv.Version > other {
|
||||||
|
result = 1
|
||||||
|
} else if fv.Version < other {
|
||||||
|
result = -1
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
type FakeRuntimeCache struct {
|
type FakeRuntimeCache struct {
|
||||||
getter podsGetter
|
getter podsGetter
|
||||||
}
|
}
|
||||||
@ -63,14 +86,14 @@ func (f *FakeRuntime) ClearCalls() {
|
|||||||
defer f.Unlock()
|
defer f.Unlock()
|
||||||
|
|
||||||
f.CalledFunctions = []string{}
|
f.CalledFunctions = []string{}
|
||||||
f.Podlist = []*Pod{}
|
f.PodList = []*Pod{}
|
||||||
f.ContainerList = []*Container{}
|
f.ContainerList = []*Container{}
|
||||||
f.PodStatus = api.PodStatus{}
|
f.PodStatus = api.PodStatus{}
|
||||||
f.StartedPods = []string{}
|
f.StartedPods = []string{}
|
||||||
f.KilledPods = []string{}
|
f.KilledPods = []string{}
|
||||||
f.StartedContainers = []string{}
|
f.StartedContainers = []string{}
|
||||||
f.KilledContainers = []string{}
|
f.KilledContainers = []string{}
|
||||||
f.VersionInfo = map[string]string{}
|
f.VersionInfo = ""
|
||||||
f.Err = nil
|
f.Err = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -112,12 +135,12 @@ func (f *FakeRuntime) AssertKilledContainers(containers []string) error {
|
|||||||
return f.assertList(containers, f.KilledContainers)
|
return f.assertList(containers, f.KilledContainers)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FakeRuntime) Version() (map[string]string, error) {
|
func (f *FakeRuntime) Version() (Version, error) {
|
||||||
f.Lock()
|
f.Lock()
|
||||||
defer f.Unlock()
|
defer f.Unlock()
|
||||||
|
|
||||||
f.CalledFunctions = append(f.CalledFunctions, "Version")
|
f.CalledFunctions = append(f.CalledFunctions, "Version")
|
||||||
return f.VersionInfo, f.Err
|
return &FakeVersion{Version: f.VersionInfo}, f.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FakeRuntime) GetPods(all bool) ([]*Pod, error) {
|
func (f *FakeRuntime) GetPods(all bool) ([]*Pod, error) {
|
||||||
@ -125,10 +148,10 @@ func (f *FakeRuntime) GetPods(all bool) ([]*Pod, error) {
|
|||||||
defer f.Unlock()
|
defer f.Unlock()
|
||||||
|
|
||||||
f.CalledFunctions = append(f.CalledFunctions, "GetPods")
|
f.CalledFunctions = append(f.CalledFunctions, "GetPods")
|
||||||
return f.Podlist, f.Err
|
return f.PodList, f.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FakeRuntime) SyncPod(pod *api.Pod, _ Pod, _ api.PodStatus) error {
|
func (f *FakeRuntime) SyncPod(pod *api.Pod, _ Pod, _ api.PodStatus, _ []api.Secret) error {
|
||||||
f.Lock()
|
f.Lock()
|
||||||
defer f.Unlock()
|
defer f.Unlock()
|
||||||
|
|
||||||
@ -140,13 +163,13 @@ func (f *FakeRuntime) SyncPod(pod *api.Pod, _ Pod, _ api.PodStatus) error {
|
|||||||
return f.Err
|
return f.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FakeRuntime) KillPod(pod *api.Pod) error {
|
func (f *FakeRuntime) KillPod(pod Pod) error {
|
||||||
f.Lock()
|
f.Lock()
|
||||||
defer f.Unlock()
|
defer f.Unlock()
|
||||||
|
|
||||||
f.CalledFunctions = append(f.CalledFunctions, "KillPod")
|
f.CalledFunctions = append(f.CalledFunctions, "KillPod")
|
||||||
f.KilledPods = append(f.KilledPods, string(pod.UID))
|
f.KilledPods = append(f.KilledPods, string(pod.ID))
|
||||||
for _, c := range pod.Spec.Containers {
|
for _, c := range pod.Containers {
|
||||||
f.KilledContainers = append(f.KilledContainers, c.Name)
|
f.KilledContainers = append(f.KilledContainers, c.Name)
|
||||||
}
|
}
|
||||||
return f.Err
|
return f.Err
|
||||||
@ -186,12 +209,13 @@ func (f *FakeRuntime) KillContainerInPod(container api.Container, pod *api.Pod)
|
|||||||
return f.Err
|
return f.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FakeRuntime) GetPodStatus(pod *Pod) (api.PodStatus, error) {
|
func (f *FakeRuntime) GetPodStatus(*api.Pod) (*api.PodStatus, error) {
|
||||||
f.Lock()
|
f.Lock()
|
||||||
defer f.Unlock()
|
defer f.Unlock()
|
||||||
|
|
||||||
f.CalledFunctions = append(f.CalledFunctions, "GetPodStatus")
|
f.CalledFunctions = append(f.CalledFunctions, "GetPodStatus")
|
||||||
return f.PodStatus, f.Err
|
status := f.PodStatus
|
||||||
|
return &status, f.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FakeRuntime) GetContainers(all bool) ([]*Container, error) {
|
func (f *FakeRuntime) GetContainers(all bool) ([]*Container, error) {
|
||||||
@ -201,3 +225,81 @@ func (f *FakeRuntime) GetContainers(all bool) ([]*Container, error) {
|
|||||||
f.CalledFunctions = append(f.CalledFunctions, "GetContainers")
|
f.CalledFunctions = append(f.CalledFunctions, "GetContainers")
|
||||||
return f.ContainerList, f.Err
|
return f.ContainerList, f.Err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *FakeRuntime) ExecInContainer(containerID string, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool) error {
|
||||||
|
f.Lock()
|
||||||
|
defer f.Unlock()
|
||||||
|
|
||||||
|
f.CalledFunctions = append(f.CalledFunctions, "ExecInContainer")
|
||||||
|
return f.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FakeRuntime) RunInContainer(containerID string, cmd []string) ([]byte, error) {
|
||||||
|
f.Lock()
|
||||||
|
defer f.Unlock()
|
||||||
|
|
||||||
|
f.CalledFunctions = append(f.CalledFunctions, "RunInContainer")
|
||||||
|
return []byte{}, f.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FakeRuntime) GetContainerLogs(pod *api.Pod, containerID, tail string, follow bool, stdout, stderr io.Writer) (err error) {
|
||||||
|
f.Lock()
|
||||||
|
defer f.Unlock()
|
||||||
|
|
||||||
|
f.CalledFunctions = append(f.CalledFunctions, "GetContainerLogs")
|
||||||
|
return f.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FakeRuntime) PullImage(image ImageSpec, pullSecrets []api.Secret) error {
|
||||||
|
f.Lock()
|
||||||
|
defer f.Unlock()
|
||||||
|
|
||||||
|
f.CalledFunctions = append(f.CalledFunctions, "PullImage")
|
||||||
|
return f.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FakeRuntime) IsImagePresent(image ImageSpec) (bool, error) {
|
||||||
|
f.Lock()
|
||||||
|
defer f.Unlock()
|
||||||
|
|
||||||
|
f.CalledFunctions = append(f.CalledFunctions, "IsImagePresent")
|
||||||
|
for _, i := range f.ImageList {
|
||||||
|
if i.ID == image.Image {
|
||||||
|
return true, f.Err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false, f.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FakeRuntime) ListImages() ([]Image, error) {
|
||||||
|
f.Lock()
|
||||||
|
defer f.Unlock()
|
||||||
|
|
||||||
|
f.CalledFunctions = append(f.CalledFunctions, "ListImages")
|
||||||
|
return f.ImageList, f.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FakeRuntime) RemoveImage(image ImageSpec) error {
|
||||||
|
f.Lock()
|
||||||
|
defer f.Unlock()
|
||||||
|
|
||||||
|
f.CalledFunctions = append(f.CalledFunctions, "RemoveImage")
|
||||||
|
index := 0
|
||||||
|
for i := range f.ImageList {
|
||||||
|
if f.ImageList[i].ID == image.Image {
|
||||||
|
index = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f.ImageList = append(f.ImageList[:index], f.ImageList[index+1:]...)
|
||||||
|
|
||||||
|
return f.Err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FakeRuntime) PortForward(pod *Pod, port uint16, stream io.ReadWriteCloser) error {
|
||||||
|
f.Lock()
|
||||||
|
defer f.Unlock()
|
||||||
|
|
||||||
|
f.CalledFunctions = append(f.CalledFunctions, "PortForward")
|
||||||
|
return f.Err
|
||||||
|
}
|
||||||
|
@ -48,7 +48,7 @@ func newTestRuntimeCache(getter podsGetter) *testRuntimeCache {
|
|||||||
func TestGetPods(t *testing.T) {
|
func TestGetPods(t *testing.T) {
|
||||||
runtime := &FakeRuntime{}
|
runtime := &FakeRuntime{}
|
||||||
expected := []*Pod{{ID: "1111"}, {ID: "2222"}, {ID: "3333"}}
|
expected := []*Pod{{ID: "1111"}, {ID: "2222"}, {ID: "3333"}}
|
||||||
runtime.Podlist = expected
|
runtime.PodList = expected
|
||||||
cache := newTestRuntimeCache(runtime)
|
cache := newTestRuntimeCache(runtime)
|
||||||
actual, err := cache.GetPods()
|
actual, err := cache.GetPods()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -65,12 +65,12 @@ func TestForceUpdateIfOlder(t *testing.T) {
|
|||||||
|
|
||||||
// Cache old pods.
|
// Cache old pods.
|
||||||
oldpods := []*Pod{{ID: "1111"}}
|
oldpods := []*Pod{{ID: "1111"}}
|
||||||
runtime.Podlist = oldpods
|
runtime.PodList = oldpods
|
||||||
cache.updateCacheWithLock()
|
cache.updateCacheWithLock()
|
||||||
|
|
||||||
// Update the runtime to new pods.
|
// Update the runtime to new pods.
|
||||||
newpods := []*Pod{{ID: "1111"}, {ID: "2222"}, {ID: "3333"}}
|
newpods := []*Pod{{ID: "1111"}, {ID: "2222"}, {ID: "3333"}}
|
||||||
runtime.Podlist = newpods
|
runtime.PodList = newpods
|
||||||
|
|
||||||
// An older timestamp should not force an update.
|
// An older timestamp should not force an update.
|
||||||
cache.ForceUpdateIfOlder(time.Now().Add(-20 * time.Minute))
|
cache.ForceUpdateIfOlder(time.Now().Add(-20 * time.Minute))
|
||||||
@ -100,7 +100,7 @@ func TestUpdatePodsOnlyIfNewer(t *testing.T) {
|
|||||||
|
|
||||||
// Instruct runime to return a list of old pods.
|
// Instruct runime to return a list of old pods.
|
||||||
oldpods := []*Pod{{ID: "1111"}}
|
oldpods := []*Pod{{ID: "1111"}}
|
||||||
runtime.Podlist = oldpods
|
runtime.PodList = oldpods
|
||||||
|
|
||||||
// Try to update the cache; the attempt should not succeed because the
|
// Try to update the cache; the attempt should not succeed because the
|
||||||
// cache timestamp is newer than the current time.
|
// cache timestamp is newer than the current time.
|
||||||
|
@ -19,8 +19,12 @@ package dockertools
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -37,12 +41,61 @@ import (
|
|||||||
"github.com/fsouza/go-dockerclient"
|
"github.com/fsouza/go-dockerclient"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type fakeHTTP struct {
|
||||||
|
url string
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *fakeHTTP) Get(url string) (*http.Response, error) {
|
||||||
|
f.url = url
|
||||||
|
return nil, f.err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Find a better way to mock the runtime hooks so that we don't have to
|
||||||
|
// duplicate the code here.
|
||||||
|
type fakeRuntimeHooks struct {
|
||||||
|
recorder record.EventRecorder
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ kubecontainer.RuntimeHooks = &fakeRuntimeHooks{}
|
||||||
|
|
||||||
|
func newFakeRuntimeHooks(recorder record.EventRecorder) kubecontainer.RuntimeHooks {
|
||||||
|
return &fakeRuntimeHooks{
|
||||||
|
recorder: recorder,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fr *fakeRuntimeHooks) ShouldPullImage(pod *api.Pod, container *api.Container, imagePresent bool) bool {
|
||||||
|
if container.ImagePullPolicy == api.PullNever {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if container.ImagePullPolicy == api.PullAlways ||
|
||||||
|
(container.ImagePullPolicy == api.PullIfNotPresent && (!imagePresent)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fr *fakeRuntimeHooks) ReportImagePull(pod *api.Pod, container *api.Container, pullError error) {
|
||||||
|
}
|
||||||
|
|
||||||
|
type fakeOptionGenerator struct{}
|
||||||
|
|
||||||
|
var _ kubecontainer.RunContainerOptionsGenerator = &fakeOptionGenerator{}
|
||||||
|
|
||||||
|
func (*fakeOptionGenerator) GenerateRunContainerOptions(pod *api.Pod, container *api.Container) (*kubecontainer.RunContainerOptions, error) {
|
||||||
|
return &kubecontainer.RunContainerOptions{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func newTestDockerManager() (*DockerManager, *FakeDockerClient) {
|
func newTestDockerManager() (*DockerManager, *FakeDockerClient) {
|
||||||
fakeDocker := &FakeDockerClient{VersionInfo: docker.Env{"Version=1.1.3", "ApiVersion=1.15"}, Errors: make(map[string]error), RemovedImages: util.StringSet{}}
|
fakeDocker := &FakeDockerClient{VersionInfo: docker.Env{"Version=1.1.3", "ApiVersion=1.15"}, Errors: make(map[string]error), RemovedImages: util.StringSet{}}
|
||||||
fakeRecorder := &record.FakeRecorder{}
|
fakeRecorder := &record.FakeRecorder{}
|
||||||
readinessManager := kubecontainer.NewReadinessManager()
|
readinessManager := kubecontainer.NewReadinessManager()
|
||||||
containerRefManager := kubecontainer.NewRefManager()
|
containerRefManager := kubecontainer.NewRefManager()
|
||||||
networkPlugin, _ := network.InitNetworkPlugin([]network.NetworkPlugin{}, "", network.NewFakeHost(nil))
|
networkPlugin, _ := network.InitNetworkPlugin([]network.NetworkPlugin{}, "", network.NewFakeHost(nil))
|
||||||
|
runtimeHooks := newFakeRuntimeHooks(fakeRecorder)
|
||||||
|
optionGenerator := &fakeOptionGenerator{}
|
||||||
dockerManager := NewFakeDockerManager(
|
dockerManager := NewFakeDockerManager(
|
||||||
fakeDocker,
|
fakeDocker,
|
||||||
fakeRecorder,
|
fakeRecorder,
|
||||||
@ -52,13 +105,21 @@ func newTestDockerManager() (*DockerManager, *FakeDockerClient) {
|
|||||||
0, 0, "",
|
0, 0, "",
|
||||||
kubecontainer.FakeOS{},
|
kubecontainer.FakeOS{},
|
||||||
networkPlugin,
|
networkPlugin,
|
||||||
nil,
|
optionGenerator,
|
||||||
nil,
|
&fakeHTTP{},
|
||||||
nil)
|
runtimeHooks)
|
||||||
|
|
||||||
return dockerManager, fakeDocker
|
return dockerManager, fakeDocker
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func matchString(t *testing.T, pattern, str string) bool {
|
||||||
|
match, err := regexp.MatchString(pattern, str)
|
||||||
|
if err != nil {
|
||||||
|
t.Logf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
return match
|
||||||
|
}
|
||||||
|
|
||||||
func TestSetEntrypointAndCommand(t *testing.T) {
|
func TestSetEntrypointAndCommand(t *testing.T) {
|
||||||
cases := []struct {
|
cases := []struct {
|
||||||
name string
|
name string
|
||||||
@ -699,3 +760,440 @@ func TestIsAExitError(t *testing.T) {
|
|||||||
t.Error("couldn't cast dockerExitError to exec.ExitError")
|
t.Error("couldn't cast dockerExitError to exec.ExitError")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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: PodInfraContainerName,
|
||||||
|
Image: PodInfraContainerImage,
|
||||||
|
Ports: ports,
|
||||||
|
}
|
||||||
|
return kubecontainer.HashContainer(container)
|
||||||
|
}
|
||||||
|
|
||||||
|
// runSyncPod is a helper function to retrieve the running pods from the fake
|
||||||
|
// docker client and runs SyncPod for the given pod.
|
||||||
|
func runSyncPod(t *testing.T, dm *DockerManager, fakeDocker *FakeDockerClient, pod *api.Pod) {
|
||||||
|
runningPods, err := dm.GetPods(false)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
runningPod := kubecontainer.Pods(runningPods).FindPodByID(pod.UID)
|
||||||
|
fakeDocker.ClearCalls()
|
||||||
|
err = dm.SyncPod(pod, runningPod, api.PodStatus{}, []api.Secret{})
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSyncPodCreateNetAndContainer(t *testing.T) {
|
||||||
|
dm, fakeDocker := newTestDockerManager()
|
||||||
|
dm.PodInfraContainerImage = "custom_image_name"
|
||||||
|
fakeDocker.ContainerList = []docker.APIContainers{}
|
||||||
|
pod := &api.Pod{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
UID: "12345678",
|
||||||
|
Name: "foo",
|
||||||
|
Namespace: "new",
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
Containers: []api.Container{
|
||||||
|
{Name: "bar"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
runSyncPod(t, dm, fakeDocker, pod)
|
||||||
|
verifyCalls(t, fakeDocker, []string{
|
||||||
|
// Create pod infra container.
|
||||||
|
"create", "start", "inspect_container",
|
||||||
|
// Create container.
|
||||||
|
"create", "start",
|
||||||
|
})
|
||||||
|
|
||||||
|
fakeDocker.Lock()
|
||||||
|
|
||||||
|
found := false
|
||||||
|
for _, c := range fakeDocker.ContainerList {
|
||||||
|
if c.Image == "custom_image_name" && strings.HasPrefix(c.Names[0], "/k8s_POD") {
|
||||||
|
found = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
t.Errorf("Custom pod infra container not found: %v", fakeDocker.ContainerList)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(fakeDocker.Created) != 2 ||
|
||||||
|
!matchString(t, "k8s_POD\\.[a-f0-9]+_foo_new_", fakeDocker.Created[0]) ||
|
||||||
|
!matchString(t, "k8s_bar\\.[a-f0-9]+_foo_new_", fakeDocker.Created[1]) {
|
||||||
|
t.Errorf("Unexpected containers created %v", fakeDocker.Created)
|
||||||
|
}
|
||||||
|
fakeDocker.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSyncPodCreatesNetAndContainerPullsImage(t *testing.T) {
|
||||||
|
dm, fakeDocker := newTestDockerManager()
|
||||||
|
dm.PodInfraContainerImage = "custom_image_name"
|
||||||
|
puller := dm.Puller.(*FakeDockerPuller)
|
||||||
|
puller.HasImages = []string{}
|
||||||
|
dm.PodInfraContainerImage = "custom_image_name"
|
||||||
|
fakeDocker.ContainerList = []docker.APIContainers{}
|
||||||
|
pod := &api.Pod{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
UID: "12345678",
|
||||||
|
Name: "foo",
|
||||||
|
Namespace: "new",
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
Containers: []api.Container{
|
||||||
|
{Name: "bar", Image: "something", ImagePullPolicy: "IfNotPresent"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
runSyncPod(t, dm, fakeDocker, pod)
|
||||||
|
|
||||||
|
verifyCalls(t, fakeDocker, []string{
|
||||||
|
// Create pod infra container.
|
||||||
|
"create", "start", "inspect_container",
|
||||||
|
// Create container.
|
||||||
|
"create", "start",
|
||||||
|
})
|
||||||
|
|
||||||
|
fakeDocker.Lock()
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(puller.ImagesPulled, []string{"custom_image_name", "something"}) {
|
||||||
|
t.Errorf("Unexpected pulled containers: %v", puller.ImagesPulled)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(fakeDocker.Created) != 2 ||
|
||||||
|
!matchString(t, "k8s_POD\\.[a-f0-9]+_foo_new_", fakeDocker.Created[0]) ||
|
||||||
|
!matchString(t, "k8s_bar\\.[a-f0-9]+_foo_new_", fakeDocker.Created[1]) {
|
||||||
|
t.Errorf("Unexpected containers created %v", fakeDocker.Created)
|
||||||
|
}
|
||||||
|
fakeDocker.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSyncPodWithPodInfraCreatesContainer(t *testing.T) {
|
||||||
|
dm, fakeDocker := newTestDockerManager()
|
||||||
|
pod := &api.Pod{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
UID: "12345678",
|
||||||
|
Name: "foo",
|
||||||
|
Namespace: "new",
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
Containers: []api.Container{
|
||||||
|
{Name: "bar"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
fakeDocker.ContainerList = []docker.APIContainers{
|
||||||
|
{
|
||||||
|
// pod infra container
|
||||||
|
Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(pod), 16) + "_foo_new_12345678_0"},
|
||||||
|
ID: "9876",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
fakeDocker.ContainerMap = map[string]*docker.Container{
|
||||||
|
"9876": {
|
||||||
|
ID: "9876",
|
||||||
|
Config: &docker.Config{},
|
||||||
|
HostConfig: &docker.HostConfig{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
runSyncPod(t, dm, fakeDocker, pod)
|
||||||
|
|
||||||
|
verifyCalls(t, fakeDocker, []string{
|
||||||
|
// Inspect pod infra container (but does not create)"
|
||||||
|
"inspect_container",
|
||||||
|
// Create container.
|
||||||
|
"create", "start",
|
||||||
|
})
|
||||||
|
|
||||||
|
fakeDocker.Lock()
|
||||||
|
if len(fakeDocker.Created) != 1 ||
|
||||||
|
!matchString(t, "k8s_bar\\.[a-f0-9]+_foo_new_", fakeDocker.Created[0]) {
|
||||||
|
t.Errorf("Unexpected containers created %v", fakeDocker.Created)
|
||||||
|
}
|
||||||
|
fakeDocker.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSyncPodDeletesWithNoPodInfraContainer(t *testing.T) {
|
||||||
|
dm, fakeDocker := newTestDockerManager()
|
||||||
|
pod := &api.Pod{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
UID: "12345678",
|
||||||
|
Name: "foo1",
|
||||||
|
Namespace: "new",
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
Containers: []api.Container{
|
||||||
|
{Name: "bar1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
fakeDocker.ContainerList = []docker.APIContainers{
|
||||||
|
{
|
||||||
|
// format is // k8s_<container-id>_<pod-fullname>_<pod-uid>
|
||||||
|
Names: []string{"/k8s_bar1_foo1_new_12345678_0"},
|
||||||
|
ID: "1234",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
runSyncPod(t, dm, fakeDocker, pod)
|
||||||
|
|
||||||
|
verifyCalls(t, fakeDocker, []string{
|
||||||
|
// Kill the container since pod infra container is not running.
|
||||||
|
"inspect_container", "stop",
|
||||||
|
// Create pod infra container.
|
||||||
|
"create", "start", "inspect_container",
|
||||||
|
// Create container.
|
||||||
|
"create", "start",
|
||||||
|
})
|
||||||
|
|
||||||
|
// A map iteration is used to delete containers, so must not depend on
|
||||||
|
// order here.
|
||||||
|
expectedToStop := map[string]bool{
|
||||||
|
"1234": true,
|
||||||
|
}
|
||||||
|
fakeDocker.Lock()
|
||||||
|
if len(fakeDocker.Stopped) != 1 || !expectedToStop[fakeDocker.Stopped[0]] {
|
||||||
|
t.Errorf("Wrong containers were stopped: %v", fakeDocker.Stopped)
|
||||||
|
}
|
||||||
|
fakeDocker.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSyncPodDeletesDuplicate(t *testing.T) {
|
||||||
|
dm, fakeDocker := newTestDockerManager()
|
||||||
|
pod := &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",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// pod infra container
|
||||||
|
Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(pod), 16) + "_bar_new_12345678_2222"},
|
||||||
|
ID: "9876",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Duplicate for the same container.
|
||||||
|
Names: []string{"/k8s_foo_bar_new_12345678_3333"},
|
||||||
|
ID: "4567",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
fakeDocker.ContainerMap = map[string]*docker.Container{
|
||||||
|
"1234": {
|
||||||
|
ID: "1234",
|
||||||
|
Config: &docker.Config{},
|
||||||
|
HostConfig: &docker.HostConfig{},
|
||||||
|
},
|
||||||
|
"9876": {
|
||||||
|
ID: "9876",
|
||||||
|
Config: &docker.Config{},
|
||||||
|
HostConfig: &docker.HostConfig{},
|
||||||
|
},
|
||||||
|
"4567": {
|
||||||
|
ID: "4567",
|
||||||
|
Config: &docker.Config{},
|
||||||
|
HostConfig: &docker.HostConfig{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
runSyncPod(t, dm, fakeDocker, pod)
|
||||||
|
|
||||||
|
verifyCalls(t, fakeDocker, []string{
|
||||||
|
// Check the pod infra container.
|
||||||
|
"inspect_container",
|
||||||
|
// Kill the duplicated container.
|
||||||
|
"inspect_container", "stop",
|
||||||
|
})
|
||||||
|
// 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) {
|
||||||
|
dm, fakeDocker := newTestDockerManager()
|
||||||
|
pod := &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",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// pod infra container
|
||||||
|
Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(pod), 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{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
runSyncPod(t, dm, fakeDocker, pod)
|
||||||
|
|
||||||
|
verifyCalls(t, fakeDocker, []string{
|
||||||
|
// Check the pod infra container.
|
||||||
|
"inspect_container",
|
||||||
|
// Kill and restart the bad hash container.
|
||||||
|
"inspect_container", "stop", "create", "start",
|
||||||
|
})
|
||||||
|
|
||||||
|
if err := fakeDocker.AssertStopped([]string{"1234"}); err != nil {
|
||||||
|
t.Errorf("%v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSyncPodsUnhealthy(t *testing.T) {
|
||||||
|
dm, fakeDocker := newTestDockerManager()
|
||||||
|
pod := &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
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
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(pod), 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{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
runSyncPod(t, dm, fakeDocker, pod)
|
||||||
|
|
||||||
|
verifyCalls(t, fakeDocker, []string{
|
||||||
|
// Check the pod infra container.
|
||||||
|
"inspect_container",
|
||||||
|
// Kill the unhealthy container.
|
||||||
|
"inspect_container", "stop",
|
||||||
|
// Restart the unhealthy container.
|
||||||
|
"create", "start",
|
||||||
|
})
|
||||||
|
|
||||||
|
if err := fakeDocker.AssertStopped([]string{"1234"}); err != nil {
|
||||||
|
t.Errorf("%v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSyncPodsDoesNothing(t *testing.T) {
|
||||||
|
dm, fakeDocker := newTestDockerManager()
|
||||||
|
container := api.Container{Name: "bar"}
|
||||||
|
pod := &api.Pod{
|
||||||
|
ObjectMeta: api.ObjectMeta{
|
||||||
|
UID: "12345678",
|
||||||
|
Name: "foo",
|
||||||
|
Namespace: "new",
|
||||||
|
},
|
||||||
|
Spec: api.PodSpec{
|
||||||
|
Containers: []api.Container{
|
||||||
|
container,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
fakeDocker.ContainerList = []docker.APIContainers{
|
||||||
|
{
|
||||||
|
// format is // k8s_<container-id>_<pod-fullname>_<pod-uid>_<random>
|
||||||
|
Names: []string{"/k8s_bar." + strconv.FormatUint(kubecontainer.HashContainer(&container), 16) + "_foo_new_12345678_0"},
|
||||||
|
ID: "1234",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// pod infra container
|
||||||
|
Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(pod), 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{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
runSyncPod(t, dm, fakeDocker, pod)
|
||||||
|
|
||||||
|
verifyCalls(t, fakeDocker, []string{
|
||||||
|
// Check the pod infra contianer.
|
||||||
|
"inspect_container",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -61,6 +61,8 @@ func init() {
|
|||||||
util.ReallyCrash = true
|
util.ReallyCrash = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Depcreate this in favor of TestKubeletWithFakeRuntime after all
|
||||||
|
// Docker-specific tests have been moved to dockertools.
|
||||||
type TestKubelet struct {
|
type TestKubelet struct {
|
||||||
kubelet *Kubelet
|
kubelet *Kubelet
|
||||||
fakeDocker *dockertools.FakeDockerClient
|
fakeDocker *dockertools.FakeDockerClient
|
||||||
@ -173,6 +175,67 @@ func verifyBoolean(t *testing.T, expected, value bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Rename this to TestKubelet after TestKubelet is removed.
|
||||||
|
type TestKubeletWithFakeRuntime struct {
|
||||||
|
kubelet *Kubelet
|
||||||
|
fakeRuntime *kubecontainer.FakeRuntime
|
||||||
|
fakeCadvisor *cadvisor.Mock
|
||||||
|
fakeKubeClient *testclient.Fake
|
||||||
|
fakeMirrorClient *fakeMirrorClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTestKubeletWithFakeRuntime(t *testing.T) *TestKubeletWithFakeRuntime {
|
||||||
|
fakeRuntime := &kubecontainer.FakeRuntime{}
|
||||||
|
fakeRuntime.VersionInfo = "1.15"
|
||||||
|
fakeRecorder := &record.FakeRecorder{}
|
||||||
|
fakeKubeClient := &testclient.Fake{}
|
||||||
|
kubelet := &Kubelet{}
|
||||||
|
kubelet.kubeClient = fakeKubeClient
|
||||||
|
kubelet.os = kubecontainer.FakeOS{}
|
||||||
|
|
||||||
|
kubelet.hostname = testKubeletHostname
|
||||||
|
kubelet.runtimeUpThreshold = maxWaitForContainerRuntime
|
||||||
|
kubelet.networkPlugin, _ = network.InitNetworkPlugin([]network.NetworkPlugin{}, "", network.NewFakeHost(nil))
|
||||||
|
if tempDir, err := ioutil.TempDir("/tmp", "kubelet_test."); err != nil {
|
||||||
|
t.Fatalf("can't make a temp rootdir: %v", err)
|
||||||
|
} else {
|
||||||
|
kubelet.rootDirectory = tempDir
|
||||||
|
}
|
||||||
|
if err := os.MkdirAll(kubelet.rootDirectory, 0750); err != nil {
|
||||||
|
t.Fatalf("can't mkdir(%q): %v", kubelet.rootDirectory, err)
|
||||||
|
}
|
||||||
|
kubelet.sourcesReady = func() bool { return true }
|
||||||
|
kubelet.masterServiceNamespace = api.NamespaceDefault
|
||||||
|
kubelet.serviceLister = testServiceLister{}
|
||||||
|
kubelet.nodeLister = testNodeLister{}
|
||||||
|
kubelet.readinessManager = kubecontainer.NewReadinessManager()
|
||||||
|
kubelet.recorder = fakeRecorder
|
||||||
|
kubelet.statusManager = newStatusManager(fakeKubeClient)
|
||||||
|
if err := kubelet.setupDataDirs(); err != nil {
|
||||||
|
t.Fatalf("can't initialize kubelet data dirs: %v", err)
|
||||||
|
}
|
||||||
|
mockCadvisor := &cadvisor.Mock{}
|
||||||
|
kubelet.cadvisor = mockCadvisor
|
||||||
|
podManager, fakeMirrorClient := newFakePodManager()
|
||||||
|
kubelet.podManager = podManager
|
||||||
|
kubelet.containerRefManager = kubecontainer.NewRefManager()
|
||||||
|
diskSpaceManager, err := newDiskSpaceManager(mockCadvisor, DiskSpacePolicy{})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("can't initialize disk space manager: %v", err)
|
||||||
|
}
|
||||||
|
kubelet.diskSpaceManager = diskSpaceManager
|
||||||
|
|
||||||
|
kubelet.containerRuntime = fakeRuntime
|
||||||
|
kubelet.runtimeCache = kubecontainer.NewFakeRuntimeCache(kubelet.containerRuntime)
|
||||||
|
kubelet.podWorkers = &fakePodWorkers{
|
||||||
|
syncPodFn: kubelet.syncPod,
|
||||||
|
runtimeCache: kubelet.runtimeCache,
|
||||||
|
t: t,
|
||||||
|
}
|
||||||
|
kubelet.volumeManager = newVolumeManager()
|
||||||
|
return &TestKubeletWithFakeRuntime{kubelet, fakeRuntime, mockCadvisor, fakeKubeClient, fakeMirrorClient}
|
||||||
|
}
|
||||||
|
|
||||||
func newTestPods(count int) []*api.Pod {
|
func newTestPods(count int) []*api.Pod {
|
||||||
pods := make([]*api.Pod, count)
|
pods := make([]*api.Pod, count)
|
||||||
for i := 0; i < count; i++ {
|
for i := 0; i < count; i++ {
|
||||||
@ -354,6 +417,8 @@ func apiContainerToContainer(c docker.APIContainers) container.Container {
|
|||||||
|
|
||||||
var emptyPodUIDs map[types.UID]metrics.SyncPodType
|
var emptyPodUIDs map[types.UID]metrics.SyncPodType
|
||||||
|
|
||||||
|
// TODO: Remove this function after all docker-specifc tests have been migrated
|
||||||
|
// to dockertools.
|
||||||
func generatePodInfraContainerHash(pod *api.Pod) uint64 {
|
func generatePodInfraContainerHash(pod *api.Pod) uint64 {
|
||||||
var ports []api.ContainerPort
|
var ports []api.ContainerPort
|
||||||
if !pod.Spec.HostNetwork {
|
if !pod.Spec.HostNetwork {
|
||||||
@ -370,73 +435,6 @@ func generatePodInfraContainerHash(pod *api.Pod) uint64 {
|
|||||||
return kubecontainer.HashContainer(container)
|
return kubecontainer.HashContainer(container)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSyncPodsDoesNothing(t *testing.T) {
|
|
||||||
testKubelet := newTestKubelet(t)
|
|
||||||
testKubelet.fakeCadvisor.On("MachineInfo").Return(&cadvisorApi.MachineInfo{}, nil)
|
|
||||||
testKubelet.fakeCadvisor.On("DockerImagesFsInfo").Return(cadvisorApiv2.FsInfo{}, nil)
|
|
||||||
testKubelet.fakeCadvisor.On("RootFsInfo").Return(cadvisorApiv2.FsInfo{}, nil)
|
|
||||||
kubelet := testKubelet.kubelet
|
|
||||||
fakeDocker := testKubelet.fakeDocker
|
|
||||||
|
|
||||||
container := api.Container{Name: "bar"}
|
|
||||||
pods := []*api.Pod{
|
|
||||||
{
|
|
||||||
ObjectMeta: api.ObjectMeta{
|
|
||||||
UID: "12345678",
|
|
||||||
Name: "foo",
|
|
||||||
Namespace: "new",
|
|
||||||
},
|
|
||||||
Spec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
container,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
fakeDocker.ContainerList = []docker.APIContainers{
|
|
||||||
{
|
|
||||||
// format is // k8s_<container-id>_<pod-fullname>_<pod-uid>_<random>
|
|
||||||
Names: []string{"/k8s_bar." + strconv.FormatUint(kubecontainer.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)
|
|
||||||
err := kubelet.SyncPods(pods, emptyPodUIDs, map[string]*api.Pod{}, time.Now())
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
verifyCalls(t, fakeDocker, []string{
|
|
||||||
"list", "list",
|
|
||||||
// Get pod status.
|
|
||||||
"list", "inspect_container", "inspect_container",
|
|
||||||
// Check the pod infra contianer.
|
|
||||||
"inspect_container",
|
|
||||||
// Get pod status.
|
|
||||||
"list", "inspect_container", "inspect_container",
|
|
||||||
// Get pods for deleting orphaned volumes.
|
|
||||||
"list",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSyncPodsWithTerminationLog(t *testing.T) {
|
func TestSyncPodsWithTerminationLog(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)
|
||||||
@ -501,18 +499,13 @@ func matchString(t *testing.T, pattern, str string) bool {
|
|||||||
return match
|
return match
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSyncPodsCreatesNetAndContainer(t *testing.T) {
|
func TestSyncPodsStartPod(t *testing.T) {
|
||||||
testKubelet := newTestKubelet(t)
|
testKubelet := newTestKubeletWithFakeRuntime(t)
|
||||||
testKubelet.fakeCadvisor.On("MachineInfo").Return(&cadvisorApi.MachineInfo{}, nil)
|
testKubelet.fakeCadvisor.On("MachineInfo").Return(&cadvisorApi.MachineInfo{}, nil)
|
||||||
testKubelet.fakeCadvisor.On("DockerImagesFsInfo").Return(cadvisorApiv2.FsInfo{}, nil)
|
testKubelet.fakeCadvisor.On("DockerImagesFsInfo").Return(cadvisorApiv2.FsInfo{}, nil)
|
||||||
testKubelet.fakeCadvisor.On("RootFsInfo").Return(cadvisorApiv2.FsInfo{}, nil)
|
testKubelet.fakeCadvisor.On("RootFsInfo").Return(cadvisorApiv2.FsInfo{}, nil)
|
||||||
kubelet := testKubelet.kubelet
|
kubelet := testKubelet.kubelet
|
||||||
fakeDocker := testKubelet.fakeDocker
|
fakeRuntime := testKubelet.fakeRuntime
|
||||||
// TODO: Move this test to dockertools so that we don't have to do the hacky
|
|
||||||
// type assertion here.
|
|
||||||
dm := kubelet.containerRuntime.(*dockertools.DockerManager)
|
|
||||||
dm.PodInfraContainerImage = "custom_image_name"
|
|
||||||
fakeDocker.ContainerList = []docker.APIContainers{}
|
|
||||||
pods := []*api.Pod{
|
pods := []*api.Pod{
|
||||||
{
|
{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
@ -532,164 +525,7 @@ func TestSyncPodsCreatesNetAndContainer(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
fakeRuntime.AssertStartedPods([]string{string(pods[0].UID)})
|
||||||
verifyCalls(t, fakeDocker, []string{
|
|
||||||
"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",
|
|
||||||
// Get pods for deleting orphaned volumes.
|
|
||||||
"list",
|
|
||||||
})
|
|
||||||
|
|
||||||
fakeDocker.Lock()
|
|
||||||
|
|
||||||
found := false
|
|
||||||
for _, c := range fakeDocker.ContainerList {
|
|
||||||
if c.Image == "custom_image_name" && strings.HasPrefix(c.Names[0], "/k8s_POD") {
|
|
||||||
found = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !found {
|
|
||||||
t.Errorf("Custom pod infra container not found: %v", fakeDocker.ContainerList)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(fakeDocker.Created) != 2 ||
|
|
||||||
!matchString(t, "k8s_POD\\.[a-f0-9]+_foo_new_", fakeDocker.Created[0]) ||
|
|
||||||
!matchString(t, "k8s_bar\\.[a-f0-9]+_foo_new_", fakeDocker.Created[1]) {
|
|
||||||
t.Errorf("Unexpected containers created %v", fakeDocker.Created)
|
|
||||||
}
|
|
||||||
fakeDocker.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSyncPodsCreatesNetAndContainerPullsImage(t *testing.T) {
|
|
||||||
testKubelet := newTestKubelet(t)
|
|
||||||
testKubelet.fakeCadvisor.On("MachineInfo").Return(&cadvisorApi.MachineInfo{}, nil)
|
|
||||||
testKubelet.fakeCadvisor.On("DockerImagesFsInfo").Return(cadvisorApiv2.FsInfo{}, nil)
|
|
||||||
testKubelet.fakeCadvisor.On("RootFsInfo").Return(cadvisorApiv2.FsInfo{}, nil)
|
|
||||||
kubelet := testKubelet.kubelet
|
|
||||||
fakeDocker := testKubelet.fakeDocker
|
|
||||||
// TODO: Move this test to dockertools so that we don't have to do the hacky
|
|
||||||
// type assertion here.
|
|
||||||
dm := kubelet.containerRuntime.(*dockertools.DockerManager)
|
|
||||||
puller := dm.Puller.(*dockertools.FakeDockerPuller)
|
|
||||||
puller.HasImages = []string{}
|
|
||||||
dm.PodInfraContainerImage = "custom_image_name"
|
|
||||||
fakeDocker.ContainerList = []docker.APIContainers{}
|
|
||||||
pods := []*api.Pod{
|
|
||||||
{
|
|
||||||
ObjectMeta: api.ObjectMeta{
|
|
||||||
UID: "12345678",
|
|
||||||
Name: "foo",
|
|
||||||
Namespace: "new",
|
|
||||||
},
|
|
||||||
Spec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{Name: "bar", Image: "something", ImagePullPolicy: "IfNotPresent"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
kubelet.podManager.SetPods(pods)
|
|
||||||
err := kubelet.SyncPods(pods, emptyPodUIDs, map[string]*api.Pod{}, time.Now())
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
verifyCalls(t, fakeDocker, []string{
|
|
||||||
"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",
|
|
||||||
// Get pods for deleting orphaned volumes.
|
|
||||||
"list",
|
|
||||||
})
|
|
||||||
|
|
||||||
fakeDocker.Lock()
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(puller.ImagesPulled, []string{"custom_image_name", "something"}) {
|
|
||||||
t.Errorf("Unexpected pulled containers: %v", puller.ImagesPulled)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(fakeDocker.Created) != 2 ||
|
|
||||||
!matchString(t, "k8s_POD\\.[a-f0-9]+_foo_new_", fakeDocker.Created[0]) ||
|
|
||||||
!matchString(t, "k8s_bar\\.[a-f0-9]+_foo_new_", fakeDocker.Created[1]) {
|
|
||||||
t.Errorf("Unexpected containers created %v", fakeDocker.Created)
|
|
||||||
}
|
|
||||||
fakeDocker.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSyncPodsWithPodInfraCreatesContainer(t *testing.T) {
|
|
||||||
testKubelet := newTestKubelet(t)
|
|
||||||
testKubelet.fakeCadvisor.On("MachineInfo").Return(&cadvisorApi.MachineInfo{}, nil)
|
|
||||||
testKubelet.fakeCadvisor.On("DockerImagesFsInfo").Return(cadvisorApiv2.FsInfo{}, nil)
|
|
||||||
testKubelet.fakeCadvisor.On("RootFsInfo").Return(cadvisorApiv2.FsInfo{}, nil)
|
|
||||||
kubelet := testKubelet.kubelet
|
|
||||||
fakeDocker := testKubelet.fakeDocker
|
|
||||||
pods := []*api.Pod{
|
|
||||||
{
|
|
||||||
ObjectMeta: api.ObjectMeta{
|
|
||||||
UID: "12345678",
|
|
||||||
Name: "foo",
|
|
||||||
Namespace: "new",
|
|
||||||
},
|
|
||||||
Spec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{Name: "bar"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
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{},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
kubelet.podManager.SetPods(pods)
|
|
||||||
err := kubelet.SyncPods(pods, emptyPodUIDs, map[string]*api.Pod{}, time.Now())
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
verifyCalls(t, fakeDocker, []string{
|
|
||||||
"list", "list",
|
|
||||||
// Get pod status.
|
|
||||||
"list", "inspect_container", "inspect_image",
|
|
||||||
// Check the pod infra container.
|
|
||||||
"inspect_container",
|
|
||||||
// Create container.
|
|
||||||
"create", "start",
|
|
||||||
// Get pod status.
|
|
||||||
"list", "inspect_container", "inspect_container",
|
|
||||||
// Get pods for deleting orphaned volumes.
|
|
||||||
"list",
|
|
||||||
})
|
|
||||||
|
|
||||||
fakeDocker.Lock()
|
|
||||||
if len(fakeDocker.Created) != 1 ||
|
|
||||||
!matchString(t, "k8s_bar\\.[a-f0-9]+_foo_new_", fakeDocker.Created[0]) {
|
|
||||||
t.Errorf("Unexpected containers created %v", fakeDocker.Created)
|
|
||||||
}
|
|
||||||
fakeDocker.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type fakeHTTP struct {
|
type fakeHTTP struct {
|
||||||
@ -786,168 +622,33 @@ func TestSyncPodsWithPodInfraCreatesContainerCallsHandler(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSyncPodsDeletesWithNoPodInfraContainer(t *testing.T) {
|
|
||||||
testKubelet := newTestKubelet(t)
|
|
||||||
testKubelet.fakeCadvisor.On("MachineInfo").Return(&cadvisorApi.MachineInfo{}, nil)
|
|
||||||
testKubelet.fakeCadvisor.On("DockerImagesFsInfo").Return(cadvisorApiv2.FsInfo{}, nil)
|
|
||||||
testKubelet.fakeCadvisor.On("RootFsInfo").Return(cadvisorApiv2.FsInfo{}, nil)
|
|
||||||
kubelet := testKubelet.kubelet
|
|
||||||
fakeDocker := testKubelet.fakeDocker
|
|
||||||
|
|
||||||
pods := []*api.Pod{
|
|
||||||
{
|
|
||||||
ObjectMeta: api.ObjectMeta{
|
|
||||||
UID: "12345678",
|
|
||||||
Name: "foo1",
|
|
||||||
Namespace: "new",
|
|
||||||
},
|
|
||||||
Spec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{Name: "bar1"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
ObjectMeta: api.ObjectMeta{
|
|
||||||
UID: "87654321",
|
|
||||||
Name: "foo2",
|
|
||||||
Namespace: "new",
|
|
||||||
},
|
|
||||||
Spec: api.PodSpec{
|
|
||||||
Containers: []api.Container{
|
|
||||||
{Name: "bar2"},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
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{},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
kubelet.podManager.SetPods(pods)
|
|
||||||
err := kubelet.SyncPods(pods, emptyPodUIDs, map[string]*api.Pod{}, time.Now())
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
verifyCalls(t, fakeDocker, []string{
|
|
||||||
"list",
|
|
||||||
|
|
||||||
// foo1
|
|
||||||
"list",
|
|
||||||
// Get pod status.
|
|
||||||
"list", "inspect_container",
|
|
||||||
// Kill the container since pod infra container is not running.
|
|
||||||
"inspect_container", "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",
|
|
||||||
// Get pod status.
|
|
||||||
"list", "inspect_container", "inspect_container",
|
|
||||||
// Check the pod infra container.
|
|
||||||
"inspect_container",
|
|
||||||
// Get pod status.
|
|
||||||
"list", "inspect_container", "inspect_container",
|
|
||||||
|
|
||||||
// Get pods for deleting orphaned volumes.
|
|
||||||
"list",
|
|
||||||
})
|
|
||||||
|
|
||||||
// A map iteration is used to delete containers, so must not depend on
|
|
||||||
// order here.
|
|
||||||
expectedToStop := map[string]bool{
|
|
||||||
"1234": true,
|
|
||||||
}
|
|
||||||
fakeDocker.Lock()
|
|
||||||
if len(fakeDocker.Stopped) != 1 || !expectedToStop[fakeDocker.Stopped[0]] {
|
|
||||||
t.Errorf("Wrong containers were stopped: %v", fakeDocker.Stopped)
|
|
||||||
}
|
|
||||||
fakeDocker.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSyncPodsDeletesWhenSourcesAreReady(t *testing.T) {
|
func TestSyncPodsDeletesWhenSourcesAreReady(t *testing.T) {
|
||||||
ready := false
|
ready := false
|
||||||
testKubelet := newTestKubelet(t)
|
|
||||||
|
testKubelet := newTestKubeletWithFakeRuntime(t)
|
||||||
|
fakeRuntime := testKubelet.fakeRuntime
|
||||||
testKubelet.fakeCadvisor.On("MachineInfo").Return(&cadvisorApi.MachineInfo{}, nil)
|
testKubelet.fakeCadvisor.On("MachineInfo").Return(&cadvisorApi.MachineInfo{}, nil)
|
||||||
testKubelet.fakeCadvisor.On("DockerImagesFsInfo").Return(cadvisorApiv2.FsInfo{}, nil)
|
testKubelet.fakeCadvisor.On("DockerImagesFsInfo").Return(cadvisorApiv2.FsInfo{}, nil)
|
||||||
testKubelet.fakeCadvisor.On("RootFsInfo").Return(cadvisorApiv2.FsInfo{}, nil)
|
testKubelet.fakeCadvisor.On("RootFsInfo").Return(cadvisorApiv2.FsInfo{}, nil)
|
||||||
kubelet := testKubelet.kubelet
|
kubelet := testKubelet.kubelet
|
||||||
fakeDocker := testKubelet.fakeDocker
|
|
||||||
kubelet.sourcesReady = func() bool { return ready }
|
kubelet.sourcesReady = func() bool { return ready }
|
||||||
|
|
||||||
fakeDocker.ContainerList = []docker.APIContainers{
|
fakeRuntime.PodList = []*kubecontainer.Pod{
|
||||||
{
|
{ID: "12345678", Name: "foo", Namespace: "new", Containers: []*kubecontainer.Container{{Name: "bar"}}},
|
||||||
// the k8s prefix is required for the kubelet to manage the container
|
|
||||||
Names: []string{"/k8s_foo_bar_new_12345678_42"},
|
|
||||||
ID: "1234",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// pod infra container
|
|
||||||
Names: []string{"/k8s_POD_foo_new_12345678_42"},
|
|
||||||
ID: "9876",
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
if err := kubelet.SyncPods([]*api.Pod{}, emptyPodUIDs, map[string]*api.Pod{}, time.Now()); err != nil {
|
if err := kubelet.SyncPods([]*api.Pod{}, emptyPodUIDs, map[string]*api.Pod{}, time.Now()); err != nil {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
// Validate nothing happened.
|
// Sources are not ready yet. Don't remove any pods.
|
||||||
verifyCalls(t, fakeDocker, []string{"list"})
|
fakeRuntime.AssertKilledPods([]string{})
|
||||||
fakeDocker.ClearCalls()
|
|
||||||
|
|
||||||
ready = true
|
ready = true
|
||||||
if err := kubelet.SyncPods([]*api.Pod{}, emptyPodUIDs, map[string]*api.Pod{}, time.Now()); err != nil {
|
if err := kubelet.SyncPods([]*api.Pod{}, emptyPodUIDs, map[string]*api.Pod{}, time.Now()); err != nil {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
verifyCalls(t, fakeDocker, []string{"list", "inspect_container", "stop", "inspect_container", "stop", "list"})
|
|
||||||
|
|
||||||
// A map iteration is used to delete containers, so must not depend on
|
// Sources are ready. Remove unwanted pods.
|
||||||
// order here.
|
fakeRuntime.AssertKilledPods([]string{"12345678"})
|
||||||
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 TestSyncPodsDeletes(t *testing.T) {
|
func TestSyncPodsDeletes(t *testing.T) {
|
||||||
@ -993,240 +694,6 @@ func TestSyncPodsDeletes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSyncPodsDeletesDuplicate(t *testing.T) {
|
|
||||||
testKubelet := newTestKubelet(t)
|
|
||||||
testKubelet.fakeCadvisor.On("MachineInfo").Return(&cadvisorApi.MachineInfo{}, nil)
|
|
||||||
testKubelet.fakeCadvisor.On("DockerImagesFsInfo").Return(cadvisorApiv2.FsInfo{}, nil)
|
|
||||||
testKubelet.fakeCadvisor.On("RootFsInfo").Return(cadvisorApiv2.FsInfo{}, nil)
|
|
||||||
kubelet := testKubelet.kubelet
|
|
||||||
fakeDocker := testKubelet.fakeDocker
|
|
||||||
|
|
||||||
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",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// pod infra container
|
|
||||||
Names: []string{"/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(pods[0]), 16) + "_bar_new_12345678_2222"},
|
|
||||||
ID: "9876",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// Duplicate for the same container.
|
|
||||||
Names: []string{"/k8s_foo_bar_new_12345678_3333"},
|
|
||||||
ID: "4567",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
fakeDocker.ContainerMap = map[string]*docker.Container{
|
|
||||||
"1234": {
|
|
||||||
ID: "1234",
|
|
||||||
Config: &docker.Config{},
|
|
||||||
HostConfig: &docker.HostConfig{},
|
|
||||||
},
|
|
||||||
"9876": {
|
|
||||||
ID: "9876",
|
|
||||||
Config: &docker.Config{},
|
|
||||||
HostConfig: &docker.HostConfig{},
|
|
||||||
},
|
|
||||||
"4567": {
|
|
||||||
ID: "4567",
|
|
||||||
Config: &docker.Config{},
|
|
||||||
HostConfig: &docker.HostConfig{},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
kubelet.podManager.SetPods(pods)
|
|
||||||
err := kubelet.SyncPods(pods, emptyPodUIDs, map[string]*api.Pod{}, time.Now())
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
verifyCalls(t, fakeDocker, []string{
|
|
||||||
"list", "list",
|
|
||||||
// Get pod status.
|
|
||||||
"list", "inspect_container", "inspect_container", "inspect_container",
|
|
||||||
// Check the pod infra container.
|
|
||||||
"inspect_container",
|
|
||||||
// Kill the duplicated container.
|
|
||||||
"inspect_container", "stop",
|
|
||||||
// Get pod status.
|
|
||||||
"list", "inspect_container", "inspect_container", "inspect_container",
|
|
||||||
// Get pods for deleting orphaned volumes.
|
|
||||||
"list",
|
|
||||||
})
|
|
||||||
// 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 TestSyncPodsBadHash(t *testing.T) {
|
|
||||||
testKubelet := newTestKubelet(t)
|
|
||||||
testKubelet.fakeCadvisor.On("MachineInfo").Return(&cadvisorApi.MachineInfo{}, nil)
|
|
||||||
testKubelet.fakeCadvisor.On("DockerImagesFsInfo").Return(cadvisorApiv2.FsInfo{}, nil)
|
|
||||||
testKubelet.fakeCadvisor.On("RootFsInfo").Return(cadvisorApiv2.FsInfo{}, nil)
|
|
||||||
kubelet := testKubelet.kubelet
|
|
||||||
fakeDocker := testKubelet.fakeDocker
|
|
||||||
|
|
||||||
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",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// 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.SyncPods(pods, emptyPodUIDs, map[string]*api.Pod{}, time.Now())
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
verifyCalls(t, fakeDocker, []string{
|
|
||||||
"list", "list",
|
|
||||||
// Get pod status.
|
|
||||||
"list", "inspect_container", "inspect_container",
|
|
||||||
// Check the pod infra container.
|
|
||||||
"inspect_container",
|
|
||||||
// Kill and restart the bad hash container.
|
|
||||||
"inspect_container", "stop", "create", "start",
|
|
||||||
// Get pod status.
|
|
||||||
"list", "inspect_container", "inspect_container", "inspect_container",
|
|
||||||
// Get pods for deleting orphaned volumes.
|
|
||||||
"list",
|
|
||||||
})
|
|
||||||
|
|
||||||
if err := fakeDocker.AssertStopped([]string{"1234"}); err != nil {
|
|
||||||
t.Errorf("%v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestSyncPodsUnhealthy(t *testing.T) {
|
|
||||||
testKubelet := newTestKubelet(t)
|
|
||||||
testKubelet.fakeCadvisor.On("MachineInfo").Return(&cadvisorApi.MachineInfo{}, nil)
|
|
||||||
testKubelet.fakeCadvisor.On("DockerImagesFsInfo").Return(cadvisorApiv2.FsInfo{}, nil)
|
|
||||||
testKubelet.fakeCadvisor.On("RootFsInfo").Return(cadvisorApiv2.FsInfo{}, nil)
|
|
||||||
kubelet := testKubelet.kubelet
|
|
||||||
fakeDocker := testKubelet.fakeDocker
|
|
||||||
|
|
||||||
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
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
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.SyncPods(pods, emptyPodUIDs, map[string]*api.Pod{}, time.Now())
|
|
||||||
if err != nil {
|
|
||||||
t.Errorf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
verifyCalls(t, fakeDocker, []string{
|
|
||||||
"list", "list",
|
|
||||||
// Get pod status.
|
|
||||||
"list", "inspect_container", "inspect_container",
|
|
||||||
// Check the pod infra container.
|
|
||||||
"inspect_container",
|
|
||||||
// Kill the unhealthy container.
|
|
||||||
"inspect_container", "stop",
|
|
||||||
// Restart the unhealthy container.
|
|
||||||
"create", "start",
|
|
||||||
// Get pod status.
|
|
||||||
"list", "inspect_container", "inspect_container", "inspect_container",
|
|
||||||
// Get pods for deleting orphaned volumes.
|
|
||||||
"list",
|
|
||||||
})
|
|
||||||
|
|
||||||
if err := fakeDocker.AssertStopped([]string{"1234"}); err != nil {
|
|
||||||
t.Errorf("%v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMountExternalVolumes(t *testing.T) {
|
func TestMountExternalVolumes(t *testing.T) {
|
||||||
testKubelet := newTestKubelet(t)
|
testKubelet := newTestKubelet(t)
|
||||||
kubelet := testKubelet.kubelet
|
kubelet := testKubelet.kubelet
|
||||||
|
Loading…
Reference in New Issue
Block a user