Commit 99936383 authored by Alex Robinson's avatar Alex Robinson

Merge pull request #15079 from gmarek/fix-kubemark

Turn on smarter FakeDockerClient in HollowNode.
parents c18d872f 22b318fc
...@@ -107,6 +107,8 @@ func main() { ...@@ -107,6 +107,8 @@ func main() {
configFilePath := makeTempDirOrDie("config", testRootDir) configFilePath := makeTempDirOrDie("config", testRootDir)
glog.Infof("Using %s as root dir for hollow-kubelet", testRootDir) glog.Infof("Using %s as root dir for hollow-kubelet", testRootDir)
fakeDockerClient.VersionInfo = docker.Env{"ApiVersion=1.18"} fakeDockerClient.VersionInfo = docker.Env{"ApiVersion=1.18"}
fakeDockerClient.ContainerMap = make(map[string]*docker.Container)
fakeDockerClient.EnableSleep = true
kcfg := kubeletapp.SimpleKubelet( kcfg := kubeletapp.SimpleKubelet(
cl, cl,
&fakeDockerClient, &fakeDockerClient,
......
...@@ -19,6 +19,7 @@ package dockertools ...@@ -19,6 +19,7 @@ package dockertools
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"math/rand"
"os" "os"
"reflect" "reflect"
"sort" "sort"
...@@ -52,6 +53,7 @@ type FakeDockerClient struct { ...@@ -52,6 +53,7 @@ type FakeDockerClient struct {
Information docker.Env Information docker.Env
ExecInspect *docker.ExecInspect ExecInspect *docker.ExecInspect
execCmd []string execCmd []string
EnableSleep bool
} }
func (f *FakeDockerClient) ClearCalls() { func (f *FakeDockerClient) ClearCalls() {
...@@ -175,27 +177,41 @@ func (f *FakeDockerClient) InspectImage(name string) (*docker.Image, error) { ...@@ -175,27 +177,41 @@ func (f *FakeDockerClient) InspectImage(name string) (*docker.Image, error) {
return f.Image, err return f.Image, err
} }
// Sleeps random amount of time with the normal distribution with given mean and stddev
// (in milliseconds), we never sleep less than cutOffMillis
func (f *FakeDockerClient) normalSleep(mean, stdDev, cutOffMillis int) {
if !f.EnableSleep {
return
}
cutoff := (time.Duration)(cutOffMillis) * time.Millisecond
delay := (time.Duration)(rand.NormFloat64()*float64(stdDev)+float64(mean)) * time.Millisecond
if delay < cutoff {
delay = cutoff
}
time.Sleep(delay)
}
// CreateContainer is a test-spy implementation of DockerInterface.CreateContainer. // CreateContainer is a test-spy implementation of DockerInterface.CreateContainer.
// It adds an entry "create" to the internal method call record. // It adds an entry "create" to the internal method call record.
func (f *FakeDockerClient) CreateContainer(c docker.CreateContainerOptions) (*docker.Container, error) { func (f *FakeDockerClient) CreateContainer(c docker.CreateContainerOptions) (*docker.Container, error) {
f.Lock() f.Lock()
defer f.Unlock() defer f.Unlock()
f.called = append(f.called, "create") f.called = append(f.called, "create")
err := f.popError("create") if err := f.popError("create"); err != nil {
if err == nil { return nil, err
f.Created = append(f.Created, c.Name) }
// This is not a very good fake. We'll just add this container's name to the list. f.Created = append(f.Created, c.Name)
// Docker likes to add a '/', so copy that behavior. // This is not a very good fake. We'll just add this container's name to the list.
name := "/" + c.Name // Docker likes to add a '/', so copy that behavior.
f.ContainerList = append(f.ContainerList, docker.APIContainers{ID: name, Names: []string{name}, Image: c.Config.Image}) name := "/" + c.Name
container := docker.Container{ID: name, Name: name, Config: c.Config} f.ContainerList = append(f.ContainerList, docker.APIContainers{ID: name, Names: []string{name}, Image: c.Config.Image})
if f.ContainerMap != nil { container := docker.Container{ID: name, Name: name, Config: c.Config}
containerCopy := container if f.ContainerMap != nil {
f.ContainerMap[name] = &containerCopy containerCopy := container
} f.ContainerMap[name] = &containerCopy
return &container, nil
} }
return nil, err f.normalSleep(200, 50, 50)
return &container, nil
} }
// StartContainer is a test-spy implementation of DockerInterface.StartContainer. // StartContainer is a test-spy implementation of DockerInterface.StartContainer.
...@@ -204,37 +220,37 @@ func (f *FakeDockerClient) StartContainer(id string, hostConfig *docker.HostConf ...@@ -204,37 +220,37 @@ func (f *FakeDockerClient) StartContainer(id string, hostConfig *docker.HostConf
f.Lock() f.Lock()
defer f.Unlock() defer f.Unlock()
f.called = append(f.called, "start") f.called = append(f.called, "start")
err := f.popError("start") if err := f.popError("start"); err != nil {
if err == nil { return err
}
f.Container = &docker.Container{ f.Container = &docker.Container{
ID: id, ID: id,
Name: id, // For testing purpose, we set name to id Name: id, // For testing purpose, we set name to id
Config: &docker.Config{Image: "testimage"}, Config: &docker.Config{Image: "testimage"},
HostConfig: hostConfig, HostConfig: hostConfig,
State: docker.State{ State: docker.State{
Running: true, Running: true,
Pid: os.Getpid(), Pid: os.Getpid(),
StartedAt: time.Now(), StartedAt: time.Now(),
}, },
NetworkSettings: &docker.NetworkSettings{IPAddress: "1.2.3.4"}, NetworkSettings: &docker.NetworkSettings{IPAddress: "1.2.3.4"},
}
if f.ContainerMap != nil {
container, ok := f.ContainerMap[id]
if !ok {
container = &docker.Container{ID: id, Name: id}
} }
if f.ContainerMap != nil { container.HostConfig = hostConfig
container, ok := f.ContainerMap[id] container.State = docker.State{
if !ok { Running: true,
container = &docker.Container{ID: id, Name: id} Pid: os.Getpid(),
} StartedAt: time.Now(),
container.HostConfig = hostConfig
container.State = docker.State{
Running: true,
Pid: os.Getpid(),
StartedAt: time.Now(),
}
container.NetworkSettings = &docker.NetworkSettings{IPAddress: "2.3.4.5"}
f.ContainerMap[id] = container
} }
container.NetworkSettings = &docker.NetworkSettings{IPAddress: "2.3.4.5"}
f.ContainerMap[id] = container
} }
return err f.normalSleep(200, 50, 50)
return nil
} }
// StopContainer is a test-spy implementation of DockerInterface.StopContainer. // StopContainer is a test-spy implementation of DockerInterface.StopContainer.
...@@ -243,39 +259,39 @@ func (f *FakeDockerClient) StopContainer(id string, timeout uint) error { ...@@ -243,39 +259,39 @@ func (f *FakeDockerClient) StopContainer(id string, timeout uint) error {
f.Lock() f.Lock()
defer f.Unlock() defer f.Unlock()
f.called = append(f.called, "stop") f.called = append(f.called, "stop")
err := f.popError("stop") if err := f.popError("stop"); err != nil {
if err == nil { return err
f.Stopped = append(f.Stopped, id) }
var newList []docker.APIContainers f.Stopped = append(f.Stopped, id)
for _, container := range f.ContainerList { var newList []docker.APIContainers
if container.ID == id { for _, container := range f.ContainerList {
f.ExitedContainerList = append(f.ExitedContainerList, container) if container.ID == id {
continue f.ExitedContainerList = append(f.ExitedContainerList, container)
} continue
newList = append(newList, container)
} }
f.ContainerList = newList newList = append(newList, container)
if f.ContainerMap != nil { }
container, ok := f.ContainerMap[id] f.ContainerList = newList
if !ok { if f.ContainerMap != nil {
container = &docker.Container{ container, ok := f.ContainerMap[id]
ID: id, if !ok {
Name: id, container = &docker.Container{
State: docker.State{ ID: id,
Running: false, Name: id,
StartedAt: time.Now().Add(-time.Second), State: docker.State{
FinishedAt: time.Now(), Running: false,
}, StartedAt: time.Now().Add(-time.Second),
} FinishedAt: time.Now(),
} else { },
container.State.FinishedAt = time.Now()
container.State.Running = false
} }
f.ContainerMap[id] = container } else {
container.State.FinishedAt = time.Now()
container.State.Running = false
} }
f.ContainerMap[id] = container
} }
return err f.normalSleep(200, 50, 50)
return nil
} }
func (f *FakeDockerClient) RemoveContainer(opts docker.RemoveContainerOptions) error { func (f *FakeDockerClient) RemoveContainer(opts docker.RemoveContainerOptions) error {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment