mirror of https://github.com/k3s-io/k3s
Various fixes for the fake docker client
* Properly return ImageNotFoundError * Support inject "Images" or "ImageInspects" and keep both in sync. * Remove the FakeDockerPuller and let FakeDockerClient subsumes its functinality. This reduces the overhead to maintain both objects. * Various small fixes and refactoring of the testing utils.pull/6/head
parent
c89e9cdbf1
commit
516848c37d
|
@ -23,6 +23,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
dockertypes "github.com/docker/engine-api/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
|
@ -102,14 +103,15 @@ func TestContainerStatus(t *testing.T) {
|
|||
sConfig := makeSandboxConfig("foo", "bar", "1", 0)
|
||||
labels := map[string]string{"abc.xyz": "foo"}
|
||||
annotations := map[string]string{"foo.bar.baz": "abc"}
|
||||
config := makeContainerConfig(sConfig, "pause", "iamimage", 0, labels, annotations)
|
||||
imageName := "iamimage"
|
||||
config := makeContainerConfig(sConfig, "pause", imageName, 0, labels, annotations)
|
||||
|
||||
var defaultTime time.Time
|
||||
dt := defaultTime.UnixNano()
|
||||
ct, st, ft := dt, dt, dt
|
||||
state := runtimeapi.ContainerState_CONTAINER_CREATED
|
||||
imageRef := DockerImageIDPrefix + imageName
|
||||
// The following variables are not set in FakeDockerClient.
|
||||
imageRef := DockerImageIDPrefix + ""
|
||||
exitCode := int32(0)
|
||||
var reason, message string
|
||||
|
||||
|
@ -129,11 +131,14 @@ func TestContainerStatus(t *testing.T) {
|
|||
Annotations: config.Annotations,
|
||||
}
|
||||
|
||||
fDocker.InjectImages([]dockertypes.Image{{ID: imageName}})
|
||||
|
||||
// Create the container.
|
||||
fClock.SetTime(time.Now().Add(-1 * time.Hour))
|
||||
expected.CreatedAt = fClock.Now().UnixNano()
|
||||
const sandboxId = "sandboxid"
|
||||
id, err := ds.CreateContainer(sandboxId, config, sConfig)
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Check internal labels
|
||||
c, err := fDocker.InspectContainer(id)
|
||||
|
|
|
@ -28,7 +28,7 @@ import (
|
|||
func TestRemoveImage(t *testing.T) {
|
||||
ds, fakeDocker, _ := newTestDockerService()
|
||||
id := "1111"
|
||||
fakeDocker.Image = &dockertypes.ImageInspect{ID: id, RepoTags: []string{"foo"}}
|
||||
fakeDocker.InjectImageInspects([]dockertypes.ImageInspect{{ID: id, RepoTags: []string{"foo"}}})
|
||||
ds.RemoveImage(&runtimeapi.ImageSpec{Image: id})
|
||||
fakeDocker.AssertCallDetails(dockertools.NewCalledDetail("inspect_image", nil),
|
||||
dockertools.NewCalledDetail("remove_image", []interface{}{id, dockertypes.ImageRemoveOptions{PruneChildren: true}}))
|
||||
|
@ -37,7 +37,7 @@ func TestRemoveImage(t *testing.T) {
|
|||
func TestRemoveImageWithMultipleTags(t *testing.T) {
|
||||
ds, fakeDocker, _ := newTestDockerService()
|
||||
id := "1111"
|
||||
fakeDocker.Image = &dockertypes.ImageInspect{ID: id, RepoTags: []string{"foo", "bar"}}
|
||||
fakeDocker.InjectImageInspects([]dockertypes.ImageInspect{{ID: id, RepoTags: []string{"foo", "bar"}}})
|
||||
ds.RemoveImage(&runtimeapi.ImageSpec{Image: id})
|
||||
fakeDocker.AssertCallDetails(dockertools.NewCalledDetail("inspect_image", nil),
|
||||
dockertools.NewCalledDetail("remove_image", []interface{}{"foo", dockertypes.ImageRemoveOptions{PruneChildren: true}}),
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/blang/semver"
|
||||
dockertypes "github.com/docker/engine-api/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
|
@ -265,29 +266,37 @@ func TestGetSecurityOptSeparator(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestEnsureSandboxImageExists(t *testing.T) {
|
||||
sandboxImage := "gcr.io/test/image"
|
||||
for desc, test := range map[string]struct {
|
||||
inject error
|
||||
calls []string
|
||||
err bool
|
||||
injectImage bool
|
||||
injectErr error
|
||||
calls []string
|
||||
err bool
|
||||
}{
|
||||
"should not pull image when it already exists": {
|
||||
inject: nil,
|
||||
calls: []string{"inspect_image"},
|
||||
injectImage: true,
|
||||
injectErr: nil,
|
||||
calls: []string{"inspect_image"},
|
||||
},
|
||||
"should pull image when it doesn't exist": {
|
||||
inject: dockertools.ImageNotFoundError{ID: "image_id"},
|
||||
calls: []string{"inspect_image", "pull"},
|
||||
injectImage: false,
|
||||
injectErr: dockertools.ImageNotFoundError{ID: "image_id"},
|
||||
calls: []string{"inspect_image", "pull"},
|
||||
},
|
||||
"should return error when inspect image fails": {
|
||||
inject: fmt.Errorf("arbitrary error"),
|
||||
calls: []string{"inspect_image"},
|
||||
err: true,
|
||||
injectImage: false,
|
||||
injectErr: fmt.Errorf("arbitrary error"),
|
||||
calls: []string{"inspect_image"},
|
||||
err: true,
|
||||
},
|
||||
} {
|
||||
t.Logf("TestCase: %q", desc)
|
||||
_, fakeDocker, _ := newTestDockerService()
|
||||
fakeDocker.InjectError("inspect_image", test.inject)
|
||||
err := ensureSandboxImageExists(fakeDocker, "gcr.io/test/image")
|
||||
if test.injectImage {
|
||||
fakeDocker.InjectImages([]dockertypes.Image{{ID: sandboxImage}})
|
||||
}
|
||||
fakeDocker.InjectError("inspect_image", test.injectErr)
|
||||
err := ensureSandboxImageExists(fakeDocker, sandboxImage)
|
||||
assert.NoError(t, fakeDocker.AssertCalls(test.calls))
|
||||
assert.Equal(t, test.err, err != nil)
|
||||
}
|
||||
|
|
|
@ -398,7 +398,7 @@ func TestListImages(t *testing.T) {
|
|||
|
||||
func TestDeleteImage(t *testing.T) {
|
||||
manager, fakeDocker := newTestDockerManager()
|
||||
fakeDocker.Image = &dockertypes.ImageInspect{ID: "1111", RepoTags: []string{"foo"}}
|
||||
fakeDocker.InjectImages([]dockertypes.Image{{ID: "1111", RepoTags: []string{"foo"}}})
|
||||
manager.RemoveImage(kubecontainer.ImageSpec{Image: "1111"})
|
||||
fakeDocker.AssertCallDetails(NewCalledDetail("inspect_image", nil), NewCalledDetail("remove_image",
|
||||
[]interface{}{"1111", dockertypes.ImageRemoveOptions{PruneChildren: true}}))
|
||||
|
@ -406,7 +406,7 @@ func TestDeleteImage(t *testing.T) {
|
|||
|
||||
func TestDeleteImageWithMultipleTags(t *testing.T) {
|
||||
manager, fakeDocker := newTestDockerManager()
|
||||
fakeDocker.Image = &dockertypes.ImageInspect{ID: "1111", RepoTags: []string{"foo", "bar"}}
|
||||
fakeDocker.InjectImages([]dockertypes.Image{{ID: "1111", RepoTags: []string{"foo", "bar"}}})
|
||||
manager.RemoveImage(kubecontainer.ImageSpec{Image: "1111"})
|
||||
fakeDocker.AssertCallDetails(NewCalledDetail("inspect_image", nil),
|
||||
NewCalledDetail("remove_image", []interface{}{"foo", dockertypes.ImageRemoveOptions{PruneChildren: true}}),
|
||||
|
@ -609,9 +609,6 @@ func TestSyncPodCreateNetAndContainer(t *testing.T) {
|
|||
func TestSyncPodCreatesNetAndContainerPullsImage(t *testing.T) {
|
||||
dm, fakeDocker := newTestDockerManagerWithRealImageManager()
|
||||
dm.podInfraContainerImage = "foo/infra_image:v1"
|
||||
puller := dm.dockerPuller.(*FakeDockerPuller)
|
||||
puller.HasImages = []string{}
|
||||
dm.podInfraContainerImage = "foo/infra_image:v1"
|
||||
pod := makePod("foo", &v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{Name: "bar", Image: "foo/something:v0", ImagePullPolicy: "IfNotPresent"},
|
||||
|
@ -622,17 +619,12 @@ func TestSyncPodCreatesNetAndContainerPullsImage(t *testing.T) {
|
|||
|
||||
verifyCalls(t, fakeDocker, []string{
|
||||
// Create pod infra container.
|
||||
"inspect_image", "create", "start", "inspect_container", "inspect_container",
|
||||
"inspect_image", "pull", "inspect_image", "create", "start", "inspect_container", "inspect_container",
|
||||
// Create container.
|
||||
"inspect_image", "create", "start", "inspect_container",
|
||||
"inspect_image", "pull", "inspect_image", "create", "start", "inspect_container",
|
||||
})
|
||||
|
||||
fakeDocker.Lock()
|
||||
if !reflect.DeepEqual(puller.ImagesPulled, []string{"foo/infra_image:v1", "foo/something:v0"}) {
|
||||
t.Errorf("unexpected pulled containers: %v", puller.ImagesPulled)
|
||||
}
|
||||
fakeDocker.Unlock()
|
||||
|
||||
assert.NoError(t, fakeDocker.AssertImagesPulled([]string{"foo/infra_image:v1", "foo/something:v0"}))
|
||||
assert.NoError(t, fakeDocker.AssertCreatedByNameWithOrder([]string{"POD", "bar"}))
|
||||
}
|
||||
|
||||
|
@ -1277,22 +1269,25 @@ func TestVerifyNonRoot(t *testing.T) {
|
|||
// success cases
|
||||
"non-root runAsUser": {
|
||||
container: &v1.Container{
|
||||
Image: "foobar",
|
||||
SecurityContext: &v1.SecurityContext{
|
||||
RunAsUser: &nonRootUid,
|
||||
},
|
||||
},
|
||||
},
|
||||
"numeric non-root image user": {
|
||||
container: &v1.Container{},
|
||||
container: &v1.Container{Image: "foobar"},
|
||||
inspectImage: &dockertypes.ImageInspect{
|
||||
ID: "foobar",
|
||||
Config: &dockercontainer.Config{
|
||||
User: "1",
|
||||
},
|
||||
},
|
||||
},
|
||||
"numeric non-root image user with gid": {
|
||||
container: &v1.Container{},
|
||||
container: &v1.Container{Image: "foobar"},
|
||||
inspectImage: &dockertypes.ImageInspect{
|
||||
ID: "foobar",
|
||||
Config: &dockercontainer.Config{
|
||||
User: "1:2",
|
||||
},
|
||||
|
@ -1302,6 +1297,7 @@ func TestVerifyNonRoot(t *testing.T) {
|
|||
// failure cases
|
||||
"root runAsUser": {
|
||||
container: &v1.Container{
|
||||
Image: "foobar",
|
||||
SecurityContext: &v1.SecurityContext{
|
||||
RunAsUser: &rootUid,
|
||||
},
|
||||
|
@ -1309,8 +1305,9 @@ func TestVerifyNonRoot(t *testing.T) {
|
|||
expectedError: "container's runAsUser breaks non-root policy",
|
||||
},
|
||||
"non-numeric image user": {
|
||||
container: &v1.Container{},
|
||||
container: &v1.Container{Image: "foobar"},
|
||||
inspectImage: &dockertypes.ImageInspect{
|
||||
ID: "foobar",
|
||||
Config: &dockercontainer.Config{
|
||||
User: "foo",
|
||||
},
|
||||
|
@ -1318,8 +1315,9 @@ func TestVerifyNonRoot(t *testing.T) {
|
|||
expectedError: "non-numeric user",
|
||||
},
|
||||
"numeric root image user": {
|
||||
container: &v1.Container{},
|
||||
container: &v1.Container{Image: "foobar"},
|
||||
inspectImage: &dockertypes.ImageInspect{
|
||||
ID: "foobar",
|
||||
Config: &dockercontainer.Config{
|
||||
User: "0",
|
||||
},
|
||||
|
@ -1327,8 +1325,9 @@ func TestVerifyNonRoot(t *testing.T) {
|
|||
expectedError: "container has no runAsUser and image will run as root",
|
||||
},
|
||||
"numeric root image user with gid": {
|
||||
container: &v1.Container{},
|
||||
container: &v1.Container{Image: "foobar"},
|
||||
inspectImage: &dockertypes.ImageInspect{
|
||||
ID: "foobar",
|
||||
Config: &dockercontainer.Config{
|
||||
User: "0:1",
|
||||
},
|
||||
|
@ -1336,19 +1335,22 @@ func TestVerifyNonRoot(t *testing.T) {
|
|||
expectedError: "container has no runAsUser and image will run as root",
|
||||
},
|
||||
"nil image in inspect": {
|
||||
container: &v1.Container{},
|
||||
container: &v1.Container{Image: "foobar"},
|
||||
inspectImage: nil,
|
||||
expectedError: "unable to inspect image",
|
||||
expectedError: ImageNotFoundError{"foobar"}.Error(),
|
||||
},
|
||||
"nil config in image inspect": {
|
||||
container: &v1.Container{},
|
||||
inspectImage: &dockertypes.ImageInspect{},
|
||||
container: &v1.Container{Image: "foobar"},
|
||||
inspectImage: &dockertypes.ImageInspect{ID: "foobar"},
|
||||
expectedError: "unable to inspect image",
|
||||
},
|
||||
}
|
||||
|
||||
for k, v := range tests {
|
||||
fakeDocker.Image = v.inspectImage
|
||||
fakeDocker.ResetImages()
|
||||
if v.inspectImage != nil {
|
||||
fakeDocker.InjectImageInspects([]dockertypes.ImageInspect{*v.inspectImage})
|
||||
}
|
||||
err := dm.verifyNonRoot(v.container)
|
||||
if v.expectedError == "" && err != nil {
|
||||
t.Errorf("case[%q]: unexpected error: %v", k, err)
|
||||
|
@ -1435,8 +1437,8 @@ func TestGetIPCMode(t *testing.T) {
|
|||
|
||||
func TestSyncPodWithPullPolicy(t *testing.T) {
|
||||
dm, fakeDocker := newTestDockerManagerWithRealImageManager()
|
||||
puller := dm.dockerPuller.(*FakeDockerPuller)
|
||||
puller.HasImages = []string{"foo/existing_one:v1", "foo/want:latest"}
|
||||
fakeDocker.InjectImages([]dockertypes.Image{{ID: "foo/existing_one:v1"}, {ID: "foo/want:latest"}})
|
||||
|
||||
dm.podInfraContainerImage = "foo/infra_image:v1"
|
||||
|
||||
pod := makePod("foo", &v1.PodSpec{
|
||||
|
@ -1465,13 +1467,11 @@ func TestSyncPodWithPullPolicy(t *testing.T) {
|
|||
result := runSyncPod(t, dm, fakeDocker, pod, nil, true)
|
||||
verifySyncResults(t, expectedResults, result)
|
||||
|
||||
assert.NoError(t, fakeDocker.AssertImagesPulled([]string{"foo/infra_image:v1", "foo/pull_always_image:v1", "foo/pull_if_not_present_image:v1"}))
|
||||
|
||||
fakeDocker.Lock()
|
||||
defer fakeDocker.Unlock()
|
||||
|
||||
pulledImageSorted := puller.ImagesPulled[:]
|
||||
sort.Strings(pulledImageSorted)
|
||||
assert.Equal(t, []string{"foo/infra_image:v1", "foo/pull_always_image:v1", "foo/pull_if_not_present_image:v1"}, pulledImageSorted)
|
||||
|
||||
if len(fakeDocker.Created) != 5 {
|
||||
t.Errorf("unexpected containers created %v", fakeDocker.Created)
|
||||
}
|
||||
|
@ -1485,33 +1485,28 @@ func TestSyncPodWithFailure(t *testing.T) {
|
|||
tests := map[string]struct {
|
||||
container v1.Container
|
||||
dockerError map[string]error
|
||||
pullerError []error
|
||||
expected []*kubecontainer.SyncResult
|
||||
}{
|
||||
"PullImageFailure": {
|
||||
v1.Container{Name: "bar", Image: "foo/real_image:v1", ImagePullPolicy: v1.PullAlways},
|
||||
map[string]error{},
|
||||
[]error{fmt.Errorf("can't pull image")},
|
||||
map[string]error{"pull": fmt.Errorf("can't pull image")},
|
||||
[]*kubecontainer.SyncResult{{kubecontainer.StartContainer, "bar", images.ErrImagePull, "can't pull image"}},
|
||||
},
|
||||
"CreateContainerFailure": {
|
||||
v1.Container{Name: "bar", Image: "foo/already_present:v2"},
|
||||
map[string]error{"create": fmt.Errorf("can't create container")},
|
||||
[]error{},
|
||||
[]*kubecontainer.SyncResult{{kubecontainer.StartContainer, "bar", kubecontainer.ErrRunContainer, "can't create container"}},
|
||||
},
|
||||
"StartContainerFailure": {
|
||||
v1.Container{Name: "bar", Image: "foo/already_present:v2"},
|
||||
map[string]error{"start": fmt.Errorf("can't start container")},
|
||||
[]error{},
|
||||
[]*kubecontainer.SyncResult{{kubecontainer.StartContainer, "bar", kubecontainer.ErrRunContainer, "can't start container"}},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
dm, fakeDocker := newTestDockerManagerWithRealImageManager()
|
||||
puller := dm.dockerPuller.(*FakeDockerPuller)
|
||||
puller.HasImages = []string{test.container.Image}
|
||||
fakeDocker.InjectImages([]dockertypes.Image{{ID: test.container.Image}})
|
||||
// Pretend that the pod infra container has already been created, so that
|
||||
// we can run the user containers.
|
||||
fakeDocker.SetFakeRunningContainers([]*FakeContainer{{
|
||||
|
@ -1519,7 +1514,6 @@ func TestSyncPodWithFailure(t *testing.T) {
|
|||
Name: "/k8s_POD." + strconv.FormatUint(generatePodInfraContainerHash(pod), 16) + "_foo_new_12345678_0",
|
||||
}})
|
||||
fakeDocker.InjectErrors(test.dockerError)
|
||||
puller.ErrorsToInject = test.pullerError
|
||||
pod.Spec.Containers = []v1.Container{test.container}
|
||||
result := runSyncPod(t, dm, fakeDocker, pod, nil, true)
|
||||
verifySyncResults(t, test.expected, result)
|
||||
|
|
|
@ -33,7 +33,6 @@ import (
|
|||
dockercontainer "github.com/docker/engine-api/types/container"
|
||||
|
||||
"k8s.io/client-go/util/clock"
|
||||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
)
|
||||
|
||||
type calledDetail struct {
|
||||
|
@ -53,7 +52,7 @@ type FakeDockerClient struct {
|
|||
RunningContainerList []dockertypes.Container
|
||||
ExitedContainerList []dockertypes.Container
|
||||
ContainerMap map[string]*dockertypes.ContainerJSON
|
||||
Image *dockertypes.ImageInspect
|
||||
ImageInspects map[string]*dockertypes.ImageInspect
|
||||
Images []dockertypes.Image
|
||||
Errors map[string]error
|
||||
called []calledDetail
|
||||
|
@ -61,10 +60,13 @@ type FakeDockerClient struct {
|
|||
EnableTrace bool
|
||||
|
||||
// Created, Started, Stopped and Removed all contain container docker ID
|
||||
Created []string
|
||||
Started []string
|
||||
Stopped []string
|
||||
Removed []string
|
||||
Created []string
|
||||
Started []string
|
||||
Stopped []string
|
||||
Removed []string
|
||||
// Images pulled by ref (name or ID).
|
||||
ImagesPulled []string
|
||||
|
||||
VersionInfo dockertypes.Version
|
||||
Information dockertypes.Info
|
||||
ExecInspect *dockertypes.ContainerExecInspect
|
||||
|
@ -87,10 +89,9 @@ func NewFakeDockerClient() *FakeDockerClient {
|
|||
Errors: make(map[string]error),
|
||||
ContainerMap: make(map[string]*dockertypes.ContainerJSON),
|
||||
Clock: clock.RealClock{},
|
||||
// default this to an empty result, so that we never have a nil non-error response from InspectImage
|
||||
Image: &dockertypes.ImageInspect{},
|
||||
// default this to true, so that we trace calls, image pulls and container lifecycle
|
||||
EnableTrace: true,
|
||||
EnableTrace: true,
|
||||
ImageInspects: make(map[string]*dockertypes.ImageInspect),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -207,8 +208,9 @@ func convertFakeContainer(f *FakeContainer) *dockertypes.ContainerJSON {
|
|||
}
|
||||
return &dockertypes.ContainerJSON{
|
||||
ContainerJSONBase: &dockertypes.ContainerJSONBase{
|
||||
ID: f.ID,
|
||||
Name: f.Name,
|
||||
ID: f.ID,
|
||||
Name: f.Name,
|
||||
Image: f.Config.Image,
|
||||
State: &dockertypes.ContainerState{
|
||||
Running: f.Running,
|
||||
ExitCode: f.ExitCode,
|
||||
|
@ -313,28 +315,17 @@ func (f *FakeDockerClient) AssertCreatedByName(created []string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sort.StringSlice(created).Sort()
|
||||
sort.StringSlice(actualCreated).Sort()
|
||||
if !reflect.DeepEqual(created, actualCreated) {
|
||||
return fmt.Errorf("expected %#v, got %#v", created, actualCreated)
|
||||
}
|
||||
return nil
|
||||
return sortedStringSlicesEqual(created, actualCreated)
|
||||
}
|
||||
|
||||
func (f *FakeDockerClient) AssertStoppedByName(stopped []string) error {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
actualStopped, err := f.idsToNames(f.Stopped)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sort.StringSlice(stopped).Sort()
|
||||
sort.StringSlice(actualStopped).Sort()
|
||||
if !reflect.DeepEqual(stopped, actualStopped) {
|
||||
return fmt.Errorf("expected %#v, got %#v", stopped, actualStopped)
|
||||
}
|
||||
return nil
|
||||
return sortedStringSlicesEqual(stopped, actualStopped)
|
||||
}
|
||||
|
||||
func (f *FakeDockerClient) AssertStopped(stopped []string) error {
|
||||
|
@ -342,10 +333,22 @@ func (f *FakeDockerClient) AssertStopped(stopped []string) error {
|
|||
defer f.Unlock()
|
||||
// Copy stopped to avoid modifying it.
|
||||
actualStopped := append([]string{}, f.Stopped...)
|
||||
sort.StringSlice(stopped).Sort()
|
||||
sort.StringSlice(actualStopped).Sort()
|
||||
if !reflect.DeepEqual(stopped, actualStopped) {
|
||||
return fmt.Errorf("expected %#v, got %#v", stopped, actualStopped)
|
||||
return sortedStringSlicesEqual(stopped, actualStopped)
|
||||
}
|
||||
|
||||
func (f *FakeDockerClient) AssertImagesPulled(pulled []string) error {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
// Copy pulled to avoid modifying it.
|
||||
actualPulled := append([]string{}, f.ImagesPulled...)
|
||||
return sortedStringSlicesEqual(pulled, actualPulled)
|
||||
}
|
||||
|
||||
func sortedStringSlicesEqual(expected, actual []string) error {
|
||||
sort.StringSlice(expected).Sort()
|
||||
sort.StringSlice(actual).Sort()
|
||||
if !reflect.DeepEqual(expected, actual) {
|
||||
return fmt.Errorf("expected %#v, got %#v", expected, actual)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -453,8 +456,13 @@ func (f *FakeDockerClient) InspectImageByRef(name string) (*dockertypes.ImageIns
|
|||
f.Lock()
|
||||
defer f.Unlock()
|
||||
f.appendCalled(calledDetail{name: "inspect_image"})
|
||||
err := f.popError("inspect_image")
|
||||
return f.Image, err
|
||||
if err := f.popError("inspect_image"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if result, ok := f.ImageInspects[name]; ok {
|
||||
return result, nil
|
||||
}
|
||||
return nil, ImageNotFoundError{name}
|
||||
}
|
||||
|
||||
// InspectImageByID is a test-spy implementation of DockerInterface.InspectImageByID.
|
||||
|
@ -463,8 +471,13 @@ func (f *FakeDockerClient) InspectImageByID(name string) (*dockertypes.ImageInsp
|
|||
f.Lock()
|
||||
defer f.Unlock()
|
||||
f.appendCalled(calledDetail{name: "inspect_image"})
|
||||
err := f.popError("inspect_image")
|
||||
return f.Image, err
|
||||
if err := f.popError("inspect_image"); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if result, ok := f.ImageInspects[name]; ok {
|
||||
return result, nil
|
||||
}
|
||||
return nil, ImageNotFoundError{name}
|
||||
}
|
||||
|
||||
// Sleeps random amount of time with the normal distribution with given mean and stddev
|
||||
|
@ -508,7 +521,9 @@ func (f *FakeDockerClient) CreateContainer(c dockertypes.ContainerCreateConfig)
|
|||
}, f.RunningContainerList...)
|
||||
f.ContainerMap[id] = convertFakeContainer(&FakeContainer{
|
||||
ID: id, Name: name, Config: c.Config, HostConfig: c.HostConfig, CreatedAt: f.Clock.Now()})
|
||||
|
||||
f.normalSleep(100, 25, 25)
|
||||
|
||||
return &dockertypes.ContainerCreateResponse{ID: id}, nil
|
||||
}
|
||||
|
||||
|
@ -615,15 +630,11 @@ func (f *FakeDockerClient) PullImage(image string, auth dockertypes.AuthConfig,
|
|||
err := f.popError("pull")
|
||||
if err == nil {
|
||||
authJson, _ := json.Marshal(auth)
|
||||
f.Image = &dockertypes.ImageInspect{
|
||||
ID: image,
|
||||
RepoTags: []string{image},
|
||||
// Image size is required to be non-zero for CRI integration.
|
||||
VirtualSize: fakeImageSize,
|
||||
Size: fakeImageSize,
|
||||
Config: &dockercontainer.Config{},
|
||||
}
|
||||
inspect := createImageInspectFromRef(image)
|
||||
f.ImageInspects[image] = inspect
|
||||
f.appendPulled(fmt.Sprintf("%s using %s", image, string(authJson)))
|
||||
f.Images = append(f.Images, *createImageFromImageInspect(*inspect))
|
||||
f.ImagesPulled = append(f.ImagesPulled, image)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
@ -666,12 +677,16 @@ func (f *FakeDockerClient) InspectExec(id string) (*dockertypes.ContainerExecIns
|
|||
}
|
||||
|
||||
func (f *FakeDockerClient) ListImages(opts dockertypes.ImageListOptions) ([]dockertypes.Image, error) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
f.appendCalled(calledDetail{name: "list_images"})
|
||||
err := f.popError("list_images")
|
||||
return f.Images, err
|
||||
}
|
||||
|
||||
func (f *FakeDockerClient) RemoveImage(image string, opts dockertypes.ImageRemoveOptions) ([]dockertypes.ImageDelete, error) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
f.appendCalled(calledDetail{name: "remove_image", arguments: []interface{}{image, opts}})
|
||||
err := f.popError("remove_image")
|
||||
if err == nil {
|
||||
|
@ -689,6 +704,25 @@ func (f *FakeDockerClient) InjectImages(images []dockertypes.Image) {
|
|||
f.Lock()
|
||||
defer f.Unlock()
|
||||
f.Images = append(f.Images, images...)
|
||||
for _, i := range images {
|
||||
f.ImageInspects[i.ID] = createImageInspectFromImage(i)
|
||||
}
|
||||
}
|
||||
|
||||
func (f *FakeDockerClient) ResetImages() {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
f.Images = []dockertypes.Image{}
|
||||
f.ImageInspects = make(map[string]*dockertypes.ImageInspect)
|
||||
}
|
||||
|
||||
func (f *FakeDockerClient) InjectImageInspects(inspects []dockertypes.ImageInspect) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
for _, i := range inspects {
|
||||
f.Images = append(f.Images, *createImageFromImageInspect(i))
|
||||
f.ImageInspects[i.ID] = &i
|
||||
}
|
||||
}
|
||||
|
||||
func (f *FakeDockerClient) updateContainerStatus(id, status string) {
|
||||
|
@ -713,44 +747,43 @@ func (f *FakeDockerClient) ResizeContainerTTY(id string, height, width int) erro
|
|||
return nil
|
||||
}
|
||||
|
||||
// FakeDockerPuller is a stub implementation of DockerPuller.
|
||||
type FakeDockerPuller struct {
|
||||
sync.Mutex
|
||||
|
||||
HasImages []string
|
||||
ImagesPulled []string
|
||||
|
||||
// Every pull will return the first error here, and then reslice
|
||||
// to remove it. Will give nil errors if this slice is empty.
|
||||
ErrorsToInject []error
|
||||
func createImageInspectFromRef(ref string) *dockertypes.ImageInspect {
|
||||
return &dockertypes.ImageInspect{
|
||||
ID: ref,
|
||||
RepoTags: []string{ref},
|
||||
// Image size is required to be non-zero for CRI integration.
|
||||
VirtualSize: fakeImageSize,
|
||||
Size: fakeImageSize,
|
||||
Config: &dockercontainer.Config{},
|
||||
}
|
||||
}
|
||||
|
||||
// Pull records the image pull attempt, and optionally injects an error.
|
||||
func (f *FakeDockerPuller) Pull(image string, secrets []v1.Secret) (err error) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
f.ImagesPulled = append(f.ImagesPulled, image)
|
||||
|
||||
if len(f.ErrorsToInject) > 0 {
|
||||
err = f.ErrorsToInject[0]
|
||||
f.ErrorsToInject = f.ErrorsToInject[1:]
|
||||
func createImageInspectFromImage(image dockertypes.Image) *dockertypes.ImageInspect {
|
||||
return &dockertypes.ImageInspect{
|
||||
ID: image.ID,
|
||||
RepoTags: image.RepoTags,
|
||||
// Image size is required to be non-zero for CRI integration.
|
||||
VirtualSize: fakeImageSize,
|
||||
Size: fakeImageSize,
|
||||
Config: &dockercontainer.Config{},
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (f *FakeDockerPuller) GetImageRef(name string) (string, error) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
if f.HasImages == nil {
|
||||
return name, nil
|
||||
func createImageFromImageInspect(inspect dockertypes.ImageInspect) *dockertypes.Image {
|
||||
return &dockertypes.Image{
|
||||
ID: inspect.ID,
|
||||
RepoTags: inspect.RepoTags,
|
||||
// Image size is required to be non-zero for CRI integration.
|
||||
VirtualSize: fakeImageSize,
|
||||
Size: fakeImageSize,
|
||||
}
|
||||
for _, s := range f.HasImages {
|
||||
if s == name {
|
||||
return s, nil
|
||||
}
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// dockerTimestampToString converts the timestamp to string
|
||||
func dockerTimestampToString(t time.Time) string {
|
||||
return t.Format(time.RFC3339Nano)
|
||||
}
|
||||
|
||||
func (f *FakeDockerClient) ImageHistory(id string) ([]dockertypes.ImageHistory, error) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
@ -764,8 +797,3 @@ func (f *FakeDockerClient) InjectImageHistory(data map[string][]dockertypes.Imag
|
|||
defer f.Unlock()
|
||||
f.ImageHistoryMap = data
|
||||
}
|
||||
|
||||
// dockerTimestampToString converts the timestamp to string
|
||||
func dockerTimestampToString(t time.Time) string {
|
||||
return t.Format(time.RFC3339Nano)
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ func NewFakeDockerManager(
|
|||
dm := NewDockerManager(client, recorder, livenessManager, containerRefManager, fakePodGetter, machineInfo, podInfraContainerImage, qps,
|
||||
burst, containerLogsDir, osInterface, networkPlugin, runtimeHelper, httpClient, &NativeExecHandler{},
|
||||
fakeOOMAdjuster, fakeProcFs, false, imageBackOff, false, false, true, "/var/lib/kubelet/seccomp")
|
||||
dm.dockerPuller = &FakeDockerPuller{}
|
||||
dm.dockerPuller = newDockerPuller(client)
|
||||
|
||||
// ttl of version cache is set to 0 so we always call version api directly in tests.
|
||||
dm.versionCache = cache.NewObjectCache(
|
||||
|
|
Loading…
Reference in New Issue