diff --git a/pkg/server/container_create_test.go b/pkg/server/container_create_test.go index 019a8dbb9..aa7172852 100644 --- a/pkg/server/container_create_test.go +++ b/pkg/server/container_create_test.go @@ -17,26 +17,14 @@ limitations under the License. package server import ( - "encoding/json" - "errors" - "os" "testing" - "github.com/containerd/containerd/api/services/containers" - snapshotapi "github.com/containerd/containerd/api/services/snapshot" imagespec "github.com/opencontainers/image-spec/specs-go/v1" runtimespec "github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-tools/generate" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "golang.org/x/net/context" "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" - - ostesting "github.com/kubernetes-incubator/cri-containerd/pkg/os/testing" - servertesting "github.com/kubernetes-incubator/cri-containerd/pkg/server/testing" - containerstore "github.com/kubernetes-incubator/cri-containerd/pkg/store/container" - imagestore "github.com/kubernetes-incubator/cri-containerd/pkg/store/image" - sandboxstore "github.com/kubernetes-incubator/cri-containerd/pkg/store/sandbox" ) func checkMount(t *testing.T, mounts []runtimespec.Mount, src, dest, typ string, @@ -440,159 +428,3 @@ func TestPrivilegedBindMount(t *testing.T) { } } } - -func TestCreateContainer(t *testing.T) { - testSandboxID := "test-sandbox-id" - testSandboxPid := uint32(4321) - config, sandboxConfig, imageConfig, specCheck := getCreateContainerTestData() - testSandbox := &sandboxstore.Sandbox{ - Metadata: sandboxstore.Metadata{ - ID: testSandboxID, - Name: "test-sandbox-name", - Config: sandboxConfig, - Pid: testSandboxPid, - }, - } - testContainerName := makeContainerName(config.Metadata, sandboxConfig.Metadata) - // Use an image id to avoid image name resolution. - // TODO(random-liu): Change this to image name after we have complete image - // management unit test framework. - testImageRef := config.GetImage().GetImage() - testChainID := "test-chain-id" - testImage := imagestore.Image{ - ID: testImageRef, - ChainID: testChainID, - Config: imageConfig, - } - - for desc, test := range map[string]struct { - sandbox *sandboxstore.Sandbox - reserveNameErr bool - imageStoreErr bool - prepareSnapshotErr error - createRootDirErr error - expectErr bool - expectedMeta containerstore.Metadata - }{ - "should return error if sandbox does not exist": { - sandbox: nil, - expectErr: true, - }, - "should return error if name is reserved": { - sandbox: testSandbox, - reserveNameErr: true, - expectErr: true, - }, - "should return error if fail to create root directory": { - sandbox: testSandbox, - createRootDirErr: errors.New("random error"), - expectErr: true, - }, - "should return error if image is not pulled": { - sandbox: testSandbox, - imageStoreErr: true, - expectErr: true, - }, - "should return error if prepare snapshot fails": { - sandbox: testSandbox, - prepareSnapshotErr: errors.New("random error"), - expectErr: true, - }, - "should be able to create container successfully": { - sandbox: testSandbox, - expectErr: false, - expectedMeta: containerstore.Metadata{ - Name: testContainerName, - SandboxID: testSandboxID, - ImageRef: testImageRef, - Config: config, - }, - }, - } { - t.Logf("TestCase %q", desc) - c := newTestCRIContainerdService() - fake := c.containerService.(*servertesting.FakeContainersClient) - fakeSnapshotClient := WithFakeSnapshotClient(c) - fakeOS := c.os.(*ostesting.FakeOS) - if test.sandbox != nil { - assert.NoError(t, c.sandboxStore.Add(*test.sandbox)) - } - if test.reserveNameErr { - assert.NoError(t, c.containerNameIndex.Reserve(testContainerName, "random id")) - } - if !test.imageStoreErr { - c.imageStore.Add(testImage) - } - if test.prepareSnapshotErr != nil { - fakeSnapshotClient.InjectError("prepare", test.prepareSnapshotErr) - } - rootExists := false - rootPath := "" - fakeOS.MkdirAllFn = func(path string, perm os.FileMode) error { - assert.Equal(t, os.FileMode(0755), perm) - rootPath = path - if test.createRootDirErr == nil { - rootExists = true - } - return test.createRootDirErr - } - fakeOS.RemoveAllFn = func(path string) error { - assert.Equal(t, rootPath, path) - rootExists = false - return nil - } - resp, err := c.CreateContainer(context.Background(), &runtime.CreateContainerRequest{ - PodSandboxId: testSandboxID, - Config: config, - SandboxConfig: sandboxConfig, - }) - if test.expectErr { - assert.Error(t, err) - assert.Nil(t, resp) - assert.False(t, rootExists, "root directory should be cleaned up") - if !test.reserveNameErr { - assert.NoError(t, c.containerNameIndex.Reserve(testContainerName, "random id"), - "container name should be released") - } - assert.Empty(t, fakeSnapshotClient.ListMounts(), "snapshot should be cleaned up") - listResp, err := fake.List(context.Background(), &containers.ListContainersRequest{}) - assert.NoError(t, err) - assert.Empty(t, listResp.Containers, "containerd container should be cleaned up") - assert.Empty(t, c.containerStore.List(), "container metadata should not be created") - continue - } - assert.NoError(t, err) - assert.NotNil(t, resp) - id := resp.GetContainerId() - assert.True(t, rootExists) - assert.Equal(t, getContainerRootDir(c.rootDir, id), rootPath, "root directory should be created") - - // Check runtime spec - containersCalls := fake.GetCalledDetails() - require.Len(t, containersCalls, 1) - createOpts, ok := containersCalls[0].Argument.(*containers.CreateContainerRequest) - assert.True(t, ok, "should create containerd container") - assert.Equal(t, id, createOpts.Container.ID, "container id should be correct") - assert.Equal(t, testImageRef, createOpts.Container.Image, "test image should be correct") - assert.Equal(t, id, createOpts.Container.RootFS, "rootfs should be correct") - spec := &runtimespec.Spec{} - assert.NoError(t, json.Unmarshal(createOpts.Container.Spec.Value, spec)) - specCheck(t, id, testSandboxPid, spec) - - assert.Equal(t, []string{"prepare"}, fakeSnapshotClient.GetCalledNames(), "prepare should be called") - snapshotCalls := fakeSnapshotClient.GetCalledDetails() - require.Len(t, snapshotCalls, 1) - prepareOpts := snapshotCalls[0].Argument.(*snapshotapi.PrepareRequest) - assert.Equal(t, &snapshotapi.PrepareRequest{ - Key: id, - Parent: testChainID, - }, prepareOpts, "prepare request should be correct") - - container, err := c.containerStore.Get(id) - assert.NoError(t, err) - test.expectedMeta.ID = id - assert.Equal(t, test.expectedMeta, container.Metadata, "container metadata should be created") - assert.Equal(t, runtime.ContainerState_CONTAINER_CREATED, container.Status.Get().State(), - "container should be in created state") - } -} diff --git a/pkg/server/container_remove_test.go b/pkg/server/container_remove_test.go index 2f6caec33..255f6b0b1 100644 --- a/pkg/server/container_remove_test.go +++ b/pkg/server/container_remove_test.go @@ -17,20 +17,11 @@ limitations under the License. package server import ( - "errors" "testing" "time" - "github.com/containerd/containerd/api/services/containers" - snapshotapi "github.com/containerd/containerd/api/services/snapshot" - "github.com/containerd/containerd/api/types/mount" "github.com/stretchr/testify/assert" - "golang.org/x/net/context" - "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" - ostesting "github.com/kubernetes-incubator/cri-containerd/pkg/os/testing" - servertesting "github.com/kubernetes-incubator/cri-containerd/pkg/server/testing" - "github.com/kubernetes-incubator/cri-containerd/pkg/store" containerstore "github.com/kubernetes-incubator/cri-containerd/pkg/store/container" ) @@ -83,146 +74,3 @@ func TestSetContainerRemoving(t *testing.T) { } } } - -func TestRemoveContainer(t *testing.T) { - testID := "test-id" - testName := "test-name" - testContainerStatus := &containerstore.Status{ - CreatedAt: time.Now().UnixNano(), - StartedAt: time.Now().UnixNano(), - FinishedAt: time.Now().UnixNano(), - } - - for desc, test := range map[string]struct { - status *containerstore.Status - removeSnapshotErr error - deleteContainerErr error - removeDirErr error - expectErr bool - expectUnsetRemoving bool - }{ - "should return error when container is still running": { - status: &containerstore.Status{ - CreatedAt: time.Now().UnixNano(), - StartedAt: time.Now().UnixNano(), - }, - expectErr: true, - }, - "should return error when there is ongoing removing": { - status: &containerstore.Status{ - CreatedAt: time.Now().UnixNano(), - StartedAt: time.Now().UnixNano(), - FinishedAt: time.Now().UnixNano(), - Removing: true, - }, - expectErr: true, - }, - "should not return error if container does not exist": { - status: nil, - removeSnapshotErr: servertesting.SnapshotNotExistError, - deleteContainerErr: servertesting.ContainerNotExistError, - expectErr: false, - }, - "should not return error if snapshot does not exist": { - status: testContainerStatus, - removeSnapshotErr: servertesting.SnapshotNotExistError, - expectErr: false, - }, - "should return error if remove snapshot fails": { - status: testContainerStatus, - removeSnapshotErr: errors.New("random error"), - expectErr: true, - }, - "should not return error if containerd container does not exist": { - status: testContainerStatus, - deleteContainerErr: servertesting.ContainerNotExistError, - expectErr: false, - }, - "should return error if delete containerd container fails": { - status: testContainerStatus, - deleteContainerErr: errors.New("random error"), - expectErr: true, - }, - "should return error if remove container root fails": { - status: testContainerStatus, - removeDirErr: errors.New("random error"), - expectErr: true, - expectUnsetRemoving: true, - }, - "should be able to remove container successfully": { - status: testContainerStatus, - expectErr: false, - }, - } { - t.Logf("TestCase %q", desc) - c := newTestCRIContainerdService() - fake := c.containerService.(*servertesting.FakeContainersClient) - fakeSnapshotClient := WithFakeSnapshotClient(c) - fakeOS := c.os.(*ostesting.FakeOS) - if test.status != nil { - assert.NoError(t, c.containerNameIndex.Reserve(testName, testID)) - container, err := containerstore.NewContainer( - containerstore.Metadata{ID: testID}, - *test.status, - ) - assert.NoError(t, err) - assert.NoError(t, c.containerStore.Add(container)) - } - fakeOS.RemoveAllFn = func(path string) error { - assert.Equal(t, getContainerRootDir(c.rootDir, testID), path) - return test.removeDirErr - } - if test.removeSnapshotErr == nil { - fakeSnapshotClient.SetFakeMounts(testID, []*mount.Mount{ - { - Type: "bind", - Source: "/test/source", - Target: "/test/target", - }, - }) - } else { - fakeSnapshotClient.InjectError("remove", test.removeSnapshotErr) - } - if test.deleteContainerErr == nil { - _, err := fake.Create(context.Background(), &containers.CreateContainerRequest{ - Container: containers.Container{ID: testID}, - }) - assert.NoError(t, err) - } else { - fake.InjectError("delete", test.deleteContainerErr) - } - resp, err := c.RemoveContainer(context.Background(), &runtime.RemoveContainerRequest{ - ContainerId: testID, - }) - if test.expectErr { - assert.Error(t, err) - assert.Nil(t, resp) - if !test.expectUnsetRemoving { - continue - } - container, err := c.containerStore.Get(testID) - assert.NoError(t, err) - // Also covers resetContainerRemoving. - assert.False(t, container.Status.Get().Removing, "removing state should be unset") - continue - } - assert.NoError(t, err) - assert.NotNil(t, resp) - _, err = c.containerStore.Get(testID) - assert.Equal(t, store.ErrNotExist, err) - assert.NoError(t, c.containerNameIndex.Reserve(testName, testID), - "container name should be released") - mountsResp, err := fakeSnapshotClient.Mounts(context.Background(), &snapshotapi.MountsRequest{Key: testID}) - assert.Equal(t, servertesting.SnapshotNotExistError, err, "snapshot should be removed") - assert.Nil(t, mountsResp) - getResp, err := fake.Get(context.Background(), &containers.GetContainerRequest{ID: testID}) - assert.Equal(t, servertesting.ContainerNotExistError, err, "containerd container should be removed") - assert.Nil(t, getResp) - - resp, err = c.RemoveContainer(context.Background(), &runtime.RemoveContainerRequest{ - ContainerId: testID, - }) - assert.NoError(t, err) - assert.NotNil(t, resp, "remove should be idempotent") - } -} diff --git a/pkg/server/container_start_test.go b/pkg/server/container_start_test.go deleted file mode 100644 index 920f31b90..000000000 --- a/pkg/server/container_start_test.go +++ /dev/null @@ -1,255 +0,0 @@ -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package server - -import ( - "errors" - "io" - "os" - "testing" - "time" - - "github.com/containerd/containerd/api/services/execution" - "github.com/containerd/containerd/api/types/mount" - "github.com/containerd/containerd/api/types/task" - "github.com/stretchr/testify/assert" - "golang.org/x/net/context" - "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" - - ostesting "github.com/kubernetes-incubator/cri-containerd/pkg/os/testing" - servertesting "github.com/kubernetes-incubator/cri-containerd/pkg/server/testing" - containerstore "github.com/kubernetes-incubator/cri-containerd/pkg/store/container" - sandboxstore "github.com/kubernetes-incubator/cri-containerd/pkg/store/sandbox" -) - -func TestStartContainer(t *testing.T) { - testID := "test-id" - testSandboxID := "test-sandbox-id" - testMetadata := containerstore.Metadata{ - ID: testID, - Name: "test-name", - SandboxID: testSandboxID, - } - testStatus := &containerstore.Status{CreatedAt: time.Now().UnixNano()} - testSandbox := &sandboxstore.Sandbox{ - Metadata: sandboxstore.Metadata{ - ID: testSandboxID, - Name: "test-sandbox-name", - }, - } - testSandboxContainer := &task.Task{ - ID: testSandboxID, - Pid: uint32(4321), - Status: task.StatusRunning, - } - testMounts := []*mount.Mount{{Type: "bind", Source: "test-source"}} - for desc, test := range map[string]struct { - status *containerstore.Status - sandbox *sandboxstore.Sandbox - sandboxContainerdContainer *task.Task - snapshotMountsErr bool - prepareFIFOErr error - createContainerErr error - startContainerErr error - expectStateChange bool - expectCalls []string - expectErr bool - }{ - "should return error when container does not exist": { - status: nil, - sandbox: testSandbox, - sandboxContainerdContainer: testSandboxContainer, - expectCalls: []string{}, - expectErr: true, - }, - "should return error when container is not in created state": { - status: &containerstore.Status{ - CreatedAt: time.Now().UnixNano(), - StartedAt: time.Now().UnixNano(), - }, - sandbox: testSandbox, - sandboxContainerdContainer: testSandboxContainer, - expectCalls: []string{}, - expectErr: true, - }, - "should return error when container is in removing state": { - status: &containerstore.Status{ - CreatedAt: time.Now().UnixNano(), - Removing: true, - }, - sandbox: testSandbox, - sandboxContainerdContainer: testSandboxContainer, - expectCalls: []string{}, - expectErr: true, - }, - "should return error when sandbox does not exist": { - status: testStatus, - sandbox: nil, - sandboxContainerdContainer: testSandboxContainer, - expectStateChange: true, - expectCalls: []string{}, - expectErr: true, - }, - "should return error when sandbox is not running": { - status: testStatus, - sandbox: testSandbox, - sandboxContainerdContainer: &task.Task{ - ID: testSandboxID, - Pid: uint32(4321), - Status: task.StatusStopped, - }, - expectStateChange: true, - expectCalls: []string{"info"}, - expectErr: true, - }, - "should return error when snapshot mounts fails": { - status: testStatus, - sandbox: testSandbox, - sandboxContainerdContainer: testSandboxContainer, - snapshotMountsErr: true, - expectStateChange: true, - expectCalls: []string{"info"}, - expectErr: true, - }, - "should return error when fail to open streaming pipes": { - status: testStatus, - sandbox: testSandbox, - sandboxContainerdContainer: testSandboxContainer, - prepareFIFOErr: errors.New("open error"), - expectStateChange: true, - expectCalls: []string{"info"}, - expectErr: true, - }, - "should return error when fail to create container": { - status: testStatus, - sandbox: testSandbox, - sandboxContainerdContainer: testSandboxContainer, - createContainerErr: errors.New("create error"), - expectStateChange: true, - expectCalls: []string{"info", "create"}, - expectErr: true, - }, - "should return error when fail to start container": { - status: testStatus, - sandbox: testSandbox, - sandboxContainerdContainer: testSandboxContainer, - startContainerErr: errors.New("start error"), - expectStateChange: true, - // cleanup the containerd task. - expectCalls: []string{"info", "create", "start", "delete"}, - expectErr: true, - }, - "should be able to start container successfully": { - status: testStatus, - sandbox: testSandbox, - sandboxContainerdContainer: testSandboxContainer, - expectStateChange: true, - expectCalls: []string{"info", "create", "start"}, - expectErr: false, - }, - } { - t.Logf("TestCase %q", desc) - c := newTestCRIContainerdService() - fake := c.taskService.(*servertesting.FakeExecutionClient) - fakeOS := c.os.(*ostesting.FakeOS) - fakeSnapshotClient := WithFakeSnapshotClient(c) - if test.status != nil { - cntr, err := containerstore.NewContainer( - testMetadata, - *test.status, - ) - assert.NoError(t, err) - assert.NoError(t, c.containerStore.Add(cntr)) - } - if test.sandbox != nil { - assert.NoError(t, c.sandboxStore.Add(*test.sandbox)) - } - if test.sandboxContainerdContainer != nil { - fake.SetFakeTasks([]task.Task{*test.sandboxContainerdContainer}) - } - if !test.snapshotMountsErr { - fakeSnapshotClient.SetFakeMounts(testID, testMounts) - } - // TODO(random-liu): Test behavior with different streaming config. - fakeOS.OpenFifoFn = func(context.Context, string, int, os.FileMode) (io.ReadWriteCloser, error) { - return nopReadWriteCloser{}, test.prepareFIFOErr - } - if test.createContainerErr != nil { - fake.InjectError("create", test.createContainerErr) - } - if test.startContainerErr != nil { - fake.InjectError("start", test.startContainerErr) - } - resp, err := c.StartContainer(context.Background(), &runtime.StartContainerRequest{ - ContainerId: testID, - }) - // Check containerd functions called. - assert.Equal(t, test.expectCalls, fake.GetCalledNames()) - // Check results returned. - if test.expectErr { - assert.Error(t, err) - assert.Nil(t, resp) - } else { - assert.NoError(t, err) - assert.NotNil(t, resp) - } - // Skip following validation if no container is injected initially. - if test.status == nil { - continue - } - // Check container state. - cntr, err := c.containerStore.Get(testID) - assert.NoError(t, err) - status := cntr.Status.Get() - if !test.expectStateChange { - assert.Equal(t, testMetadata, cntr.Metadata) - assert.Equal(t, *test.status, status) - continue - } - if test.expectErr { - t.Logf("container state should be in exited state when fail to start") - assert.Equal(t, runtime.ContainerState_CONTAINER_EXITED, status.State()) - assert.Zero(t, status.Pid) - assert.EqualValues(t, errorStartExitCode, status.ExitCode) - assert.Equal(t, errorStartReason, status.Reason) - assert.NotEmpty(t, status.Message) - _, err := fake.Info(context.Background(), &execution.InfoRequest{ContainerID: testID}) - assert.True(t, isContainerdGRPCNotFoundError(err), - "containerd task should be cleaned up when fail to start") - continue - } - t.Logf("container state should be running when start successfully") - assert.Equal(t, runtime.ContainerState_CONTAINER_RUNNING, status.State()) - info, err := fake.Info(context.Background(), &execution.InfoRequest{ContainerID: testID}) - assert.NoError(t, err) - pid := info.Task.Pid - assert.Equal(t, pid, status.Pid) - assert.Equal(t, task.StatusRunning, info.Task.Status) - // Check runtime spec - calls := fake.GetCalledDetails() - createOpts, ok := calls[1].Argument.(*execution.CreateRequest) - assert.True(t, ok, "2nd call should be create") - _, stdout, stderr := getStreamingPipes(getContainerRootDir(c.rootDir, testID)) - assert.Equal(t, &execution.CreateRequest{ - ContainerID: testID, - Rootfs: testMounts, - // TODO(random-liu): Test streaming configurations. - Stdout: stdout, - Stderr: stderr, - }, createOpts, "create options should be correct") - } -} diff --git a/pkg/server/container_stop_test.go b/pkg/server/container_stop_test.go index 80ee1e549..7ebc1ba8a 100644 --- a/pkg/server/container_stop_test.go +++ b/pkg/server/container_stop_test.go @@ -17,21 +17,13 @@ limitations under the License. package server import ( - "errors" "testing" "time" - "github.com/containerd/containerd/api/services/execution" - "github.com/containerd/containerd/api/types/task" - imagespec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/stretchr/testify/assert" "golang.org/x/net/context" - "golang.org/x/sys/unix" - "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" - servertesting "github.com/kubernetes-incubator/cri-containerd/pkg/server/testing" containerstore "github.com/kubernetes-incubator/cri-containerd/pkg/store/container" - imagestore "github.com/kubernetes-incubator/cri-containerd/pkg/store/image" ) func TestWaitContainerStop(t *testing.T) { @@ -93,240 +85,3 @@ func TestWaitContainerStop(t *testing.T) { assert.Equal(t, test.expectErr, err != nil, desc) } } - -func TestStopContainer(t *testing.T) { - testID := "test-id" - testPid := uint32(1234) - testImageID := "test-image-id" - testStatus := containerstore.Status{ - Pid: testPid, - CreatedAt: time.Now().UnixNano(), - StartedAt: time.Now().UnixNano(), - } - testImage := imagestore.Image{ - ID: testImageID, - Config: &imagespec.ImageConfig{}, - } - testContainer := task.Task{ - ID: testID, - Pid: testPid, - Status: task.StatusRunning, - } - for desc, test := range map[string]struct { - status *containerstore.Status - containerdContainer *task.Task - stopSignal string - stopErr error - noTimeout bool - expectErr bool - expectCalls []servertesting.CalledDetail - }{ - "should return error when container does not exist": { - status: nil, - expectErr: true, - expectCalls: []servertesting.CalledDetail{}, - }, - "should not return error when container is not running": { - status: &containerstore.Status{CreatedAt: time.Now().UnixNano()}, - expectErr: false, - expectCalls: []servertesting.CalledDetail{}, - }, - "should not return error if containerd task does not exist": { - status: &testStatus, - containerdContainer: &testContainer, - // Since it's hard to inject event during `StopContainer` is running, - // we only test the case that first stop returns error, but container - // status is not updated yet. - // We also leverage this behavior to test that when graceful - // stop doesn't take effect, container should be SIGKILL-ed. - stopErr: servertesting.TaskNotExistError, - expectErr: false, - expectCalls: []servertesting.CalledDetail{ - { - Name: "kill", - Argument: &execution.KillRequest{ - ContainerID: testID, - Signal: uint32(unix.SIGTERM), - PidOrAll: &execution.KillRequest_All{All: true}, - }, - }, - { - Name: "kill", - Argument: &execution.KillRequest{ - ContainerID: testID, - Signal: uint32(unix.SIGKILL), - PidOrAll: &execution.KillRequest_All{All: true}, - }, - }, - { - Name: "delete", - Argument: &execution.DeleteRequest{ContainerID: testID}, - }, - }, - }, - "should not return error if containerd task process already finished": { - status: &testStatus, - containerdContainer: &testContainer, - stopErr: errors.New("os: process already finished"), - expectErr: false, - expectCalls: []servertesting.CalledDetail{ - { - Name: "kill", - Argument: &execution.KillRequest{ - ContainerID: testID, - Signal: uint32(unix.SIGTERM), - PidOrAll: &execution.KillRequest_All{All: true}, - }, - }, - { - Name: "kill", - Argument: &execution.KillRequest{ - ContainerID: testID, - Signal: uint32(unix.SIGKILL), - PidOrAll: &execution.KillRequest_All{All: true}, - }, - }, - { - Name: "delete", - Argument: &execution.DeleteRequest{ContainerID: testID}, - }, - }, - }, - "should return error if graceful stop returns random error": { - status: &testStatus, - containerdContainer: &testContainer, - stopErr: errors.New("random stop error"), - expectErr: true, - expectCalls: []servertesting.CalledDetail{ - { - Name: "kill", - Argument: &execution.KillRequest{ - ContainerID: testID, - Signal: uint32(unix.SIGTERM), - PidOrAll: &execution.KillRequest_All{All: true}, - }, - }, - }, - }, - "should not return error if containerd task is gracefully stopped": { - status: &testStatus, - containerdContainer: &testContainer, - expectErr: false, - // deleted by the event monitor. - expectCalls: []servertesting.CalledDetail{ - { - Name: "kill", - Argument: &execution.KillRequest{ - ContainerID: testID, - Signal: uint32(unix.SIGTERM), - PidOrAll: &execution.KillRequest_All{All: true}, - }, - }, - { - Name: "delete", - Argument: &execution.DeleteRequest{ContainerID: testID}, - }, - }, - }, - "should use stop signal specified in image config if not empty": { - status: &testStatus, - containerdContainer: &testContainer, - stopSignal: "SIGHUP", - expectErr: false, - // deleted by the event monitor. - expectCalls: []servertesting.CalledDetail{ - { - Name: "kill", - Argument: &execution.KillRequest{ - ContainerID: testID, - Signal: uint32(unix.SIGHUP), - PidOrAll: &execution.KillRequest_All{All: true}, - }, - }, - { - Name: "delete", - Argument: &execution.DeleteRequest{ContainerID: testID}, - }, - }, - }, - "should directly kill container if timeout is 0": { - status: &testStatus, - containerdContainer: &testContainer, - noTimeout: true, - expectErr: false, - expectCalls: []servertesting.CalledDetail{ - { - Name: "kill", - Argument: &execution.KillRequest{ - ContainerID: testID, - Signal: uint32(unix.SIGKILL), - PidOrAll: &execution.KillRequest_All{All: true}, - }, - }, - { - Name: "delete", - Argument: &execution.DeleteRequest{ContainerID: testID}, - }, - }, - }, - // TODO(random-liu): Test "should return error if both failed" after we have - // fake clock for test. - } { - t.Logf("TestCase %q", desc) - c := newTestCRIContainerdService() - fake := servertesting.NewFakeExecutionClient().WithEvents() - defer fake.Stop() - c.taskService = fake - - // Inject the container. - if test.status != nil { - cntr, err := containerstore.NewContainer( - containerstore.Metadata{ - ID: testID, - ImageRef: testImageID, - }, - *test.status, - ) - assert.NoError(t, err) - assert.NoError(t, c.containerStore.Add(cntr)) - } - // Inject containerd task. - if test.containerdContainer != nil { - fake.SetFakeTasks([]task.Task{*test.containerdContainer}) - } - testImage.Config.StopSignal = test.stopSignal - c.imageStore.Add(testImage) - if test.stopErr != nil { - fake.InjectError("kill", test.stopErr) - } - eventClient, err := fake.Events(context.Background(), &execution.EventsRequest{}) - assert.NoError(t, err) - // Start a simple test event monitor. - go func(e execution.Tasks_EventsClient) { - for { - if err := c.handleEventStream(e); err != nil { // nolint: vetshadow - return - } - } - }(eventClient) - fake.ClearCalls() - timeout := int64(1) - if test.noTimeout { - timeout = 0 - } - // 1 second timeout should be enough for the unit test. - // TODO(random-liu): Use fake clock for this test. - resp, err := c.StopContainer(context.Background(), &runtime.StopContainerRequest{ - ContainerId: testID, - Timeout: timeout, - }) - if test.expectErr { - assert.Error(t, err) - assert.Nil(t, resp) - } else { - assert.NoError(t, err) - assert.NotNil(t, resp) - } - assert.Equal(t, test.expectCalls, fake.GetCalledDetails()) - } -} diff --git a/pkg/server/events_test.go b/pkg/server/events_test.go deleted file mode 100644 index 336d60fc7..000000000 --- a/pkg/server/events_test.go +++ /dev/null @@ -1,172 +0,0 @@ -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package server - -import ( - "fmt" - "testing" - "time" - - "github.com/containerd/containerd/api/services/execution" - "github.com/containerd/containerd/api/types/task" - "github.com/stretchr/testify/assert" - "golang.org/x/net/context" - "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" - - servertesting "github.com/kubernetes-incubator/cri-containerd/pkg/server/testing" - containerstore "github.com/kubernetes-incubator/cri-containerd/pkg/store/container" -) - -func TestHandleEvent(t *testing.T) { - testID := "test-id" - testPid := uint32(1234) - testCreatedAt := time.Now().UnixNano() - testStartedAt := time.Now().UnixNano() - testMetadata := containerstore.Metadata{ - ID: testID, - Name: "test-name", - SandboxID: "test-sandbox-id", - } - // Container status in running state. - testStatus := containerstore.Status{ - Pid: testPid, - CreatedAt: testCreatedAt, - StartedAt: testStartedAt, - } - testExitedAt := time.Now() - testExitEvent := task.Event{ - ID: testID, - Type: task.Event_EXIT, - Pid: testPid, - ExitStatus: 1, - ExitedAt: testExitedAt, - } - testFinishedStatus := containerstore.Status{ - Pid: 0, - CreatedAt: testCreatedAt, - StartedAt: testStartedAt, - FinishedAt: testExitedAt.UnixNano(), - ExitCode: 1, - } - assert.Equal(t, runtime.ContainerState_CONTAINER_RUNNING, testStatus.State()) - testContainerdContainer := task.Task{ - ID: testID, - Pid: testPid, - Status: task.StatusRunning, - } - - for desc, test := range map[string]struct { - event *task.Event - status *containerstore.Status - containerdContainer *task.Task - containerdErr error - expected *containerstore.Status - }{ - "should not update state when no corresponding container for event": { - event: &testExitEvent, - expected: nil, - }, - "should not update state when exited process is not init process": { - event: &task.Event{ - ID: testID, - Type: task.Event_EXIT, - Pid: 9999, - ExitStatus: 1, - ExitedAt: testExitedAt, - }, - status: &testStatus, - containerdContainer: &testContainerdContainer, - expected: &testStatus, - }, - "should not update state when fail to delete containerd task": { - event: &testExitEvent, - status: &testStatus, - containerdContainer: &testContainerdContainer, - containerdErr: fmt.Errorf("random error"), - expected: &testStatus, - }, - "should not update state for irrelevant events": { - event: &task.Event{ - ID: testID, - Type: task.Event_PAUSED, - Pid: testPid, - }, - status: &testStatus, - containerdContainer: &testContainerdContainer, - expected: &testStatus, - }, - "should update state when containerd task is already deleted": { - event: &testExitEvent, - status: &testStatus, - expected: &testFinishedStatus, - }, - "should update state when delete containerd task successfully": { - event: &testExitEvent, - status: &testStatus, - containerdContainer: &testContainerdContainer, - expected: &testFinishedStatus, - }, - "should update exit reason when container is oom killed": { - event: &task.Event{ - ID: testID, - Type: task.Event_OOM, - }, - status: &testStatus, - expected: &containerstore.Status{ - Pid: testPid, - CreatedAt: testCreatedAt, - StartedAt: testStartedAt, - Reason: oomExitReason, - }, - }, - } { - t.Logf("TestCase %q", desc) - c := newTestCRIContainerdService() - fake := c.taskService.(*servertesting.FakeExecutionClient) - e, err := fake.Events(context.Background(), &execution.EventsRequest{}) - assert.NoError(t, err) - fakeEvents := e.(*servertesting.EventClient) - // Inject event. - if test.event != nil { - fakeEvents.Events <- test.event - } - // Inject internal container object. - if test.status != nil { - cntr, err := containerstore.NewContainer( // nolint: vetshadow - testMetadata, - *test.status, - ) - assert.NoError(t, err) - assert.NoError(t, c.containerStore.Add(cntr)) - } - // Inject containerd task. - if test.containerdContainer != nil { - fake.SetFakeTasks([]task.Task{*test.containerdContainer}) - } - // Inject containerd delete error. - if test.containerdErr != nil { - fake.InjectError("delete", test.containerdErr) - } - assert.NoError(t, c.handleEventStream(e)) - if test.expected == nil { - continue - } - got, err := c.containerStore.Get(testID) - assert.NoError(t, err) - assert.Equal(t, *test.expected, got.Status.Get()) - } -} diff --git a/pkg/server/sandbox_list_test.go b/pkg/server/sandbox_list_test.go index 56684f63b..3168153b8 100644 --- a/pkg/server/sandbox_list_test.go +++ b/pkg/server/sandbox_list_test.go @@ -21,13 +21,8 @@ import ( "time" "github.com/stretchr/testify/assert" - "golang.org/x/net/context" - - "github.com/containerd/containerd/api/types/task" - "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" - servertesting "github.com/kubernetes-incubator/cri-containerd/pkg/server/testing" sandboxstore "github.com/kubernetes-incubator/cri-containerd/pkg/store/sandbox" ) @@ -131,86 +126,3 @@ func TestFilterSandboxes(t *testing.T) { assert.Equal(t, test.expect, filtered, desc) } } - -func TestListPodSandbox(t *testing.T) { - c := newTestCRIContainerdService() - - fake := c.taskService.(*servertesting.FakeExecutionClient) - - sandboxesInStore := []sandboxstore.Sandbox{ - { - Metadata: sandboxstore.Metadata{ - ID: "1", - Name: "name-1", - Config: &runtime.PodSandboxConfig{Metadata: &runtime.PodSandboxMetadata{Name: "name-1"}}, - }, - }, - { - Metadata: sandboxstore.Metadata{ - ID: "2", - Name: "name-2", - Config: &runtime.PodSandboxConfig{Metadata: &runtime.PodSandboxMetadata{Name: "name-2"}}, - }, - }, - { - Metadata: sandboxstore.Metadata{ - ID: "3", - Name: "name-3", - Config: &runtime.PodSandboxConfig{Metadata: &runtime.PodSandboxMetadata{Name: "name-3"}}, - }, - }, - } - sandboxesInContainerd := []task.Task{ - // Running container with corresponding metadata - { - ID: "1", - Pid: 1, - Status: task.StatusRunning, - }, - // Stopped container with corresponding metadata - { - ID: "2", - Pid: 2, - Status: task.StatusStopped, - }, - // Container without corresponding metadata - { - ID: "4", - Pid: 4, - Status: task.StatusStopped, - }, - } - expect := []*runtime.PodSandbox{ - { - Id: "1", - Metadata: &runtime.PodSandboxMetadata{Name: "name-1"}, - State: runtime.PodSandboxState_SANDBOX_READY, - }, - { - Id: "2", - Metadata: &runtime.PodSandboxMetadata{Name: "name-2"}, - State: runtime.PodSandboxState_SANDBOX_NOTREADY, - }, - { - Id: "3", - Metadata: &runtime.PodSandboxMetadata{Name: "name-3"}, - State: runtime.PodSandboxState_SANDBOX_NOTREADY, - }, - } - - // Inject test metadata - for _, s := range sandboxesInStore { - assert.NoError(t, c.sandboxStore.Add(s)) - } - - // Inject fake containerd tasks - fake.SetFakeTasks(sandboxesInContainerd) - - resp, err := c.ListPodSandbox(context.Background(), &runtime.ListPodSandboxRequest{}) - assert.NoError(t, err) - sandboxes := resp.GetItems() - assert.Len(t, sandboxes, len(expect)) - for _, s := range expect { - assert.Contains(t, sandboxes, s) - } -} diff --git a/pkg/server/sandbox_remove_test.go b/pkg/server/sandbox_remove_test.go deleted file mode 100644 index 17baef318..000000000 --- a/pkg/server/sandbox_remove_test.go +++ /dev/null @@ -1,241 +0,0 @@ -/* Copyright 2017 The Kubernetes Authors. -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package server - -import ( - "fmt" - "testing" - "time" - - "github.com/containerd/containerd/api/services/containers" - snapshotapi "github.com/containerd/containerd/api/services/snapshot" - "github.com/containerd/containerd/api/types/mount" - "github.com/containerd/containerd/api/types/task" - "github.com/stretchr/testify/assert" - "golang.org/x/net/context" - "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" - - ostesting "github.com/kubernetes-incubator/cri-containerd/pkg/os/testing" - servertesting "github.com/kubernetes-incubator/cri-containerd/pkg/server/testing" - "github.com/kubernetes-incubator/cri-containerd/pkg/store" - containerstore "github.com/kubernetes-incubator/cri-containerd/pkg/store/container" - sandboxstore "github.com/kubernetes-incubator/cri-containerd/pkg/store/sandbox" -) - -func TestRemovePodSandbox(t *testing.T) { - testID := "test-id" - testName := "test-name" - testSandbox := sandboxstore.Sandbox{ - Metadata: sandboxstore.Metadata{ - ID: testID, - Name: testName, - }, - } - for desc, test := range map[string]struct { - sandboxTasks []task.Task - injectSandbox bool - removeSnapshotErr error - deleteContainerErr error - taskInfoErr error - injectFSErr error - expectErr bool - expectRemoved string - expectCalls []string - }{ - "should not return error if sandbox does not exist": { - injectSandbox: false, - removeSnapshotErr: servertesting.SnapshotNotExistError, - deleteContainerErr: servertesting.ContainerNotExistError, - expectErr: false, - expectCalls: []string{}, - }, - "should not return error if snapshot does not exist": { - injectSandbox: true, - removeSnapshotErr: servertesting.SnapshotNotExistError, - expectRemoved: getSandboxRootDir(testRootDir, testID), - expectCalls: []string{"info"}, - }, - "should return error if remove snapshot fails": { - injectSandbox: true, - removeSnapshotErr: fmt.Errorf("arbitrary error"), - expectErr: true, - expectCalls: []string{"info"}, - }, - "should return error when sandbox container task is not deleted": { - injectSandbox: true, - sandboxTasks: []task.Task{{ID: testID}}, - expectErr: true, - expectCalls: []string{"info"}, - }, - "should return error when arbitrary containerd error is injected": { - injectSandbox: true, - taskInfoErr: fmt.Errorf("arbitrary error"), - expectErr: true, - expectCalls: []string{"info"}, - }, - "should return error when error fs error is injected": { - injectSandbox: true, - injectFSErr: fmt.Errorf("fs error"), - expectRemoved: getSandboxRootDir(testRootDir, testID), - expectErr: true, - expectCalls: []string{"info"}, - }, - "should not return error if sandbox container does not exist": { - injectSandbox: true, - deleteContainerErr: servertesting.ContainerNotExistError, - expectRemoved: getSandboxRootDir(testRootDir, testID), - expectCalls: []string{"info"}, - }, - "should return error if delete sandbox container fails": { - injectSandbox: true, - deleteContainerErr: fmt.Errorf("arbitrary error"), - expectRemoved: getSandboxRootDir(testRootDir, testID), - expectErr: true, - expectCalls: []string{"info"}, - }, - "should be able to successfully delete": { - injectSandbox: true, - expectRemoved: getSandboxRootDir(testRootDir, testID), - expectCalls: []string{"info"}, - }, - } { - t.Logf("TestCase %q", desc) - c := newTestCRIContainerdService() - fake := c.containerService.(*servertesting.FakeContainersClient) - fakeOS := c.os.(*ostesting.FakeOS) - fakeExecutionClient := c.taskService.(*servertesting.FakeExecutionClient) - fakeSnapshotClient := WithFakeSnapshotClient(c) - fakeExecutionClient.SetFakeTasks(test.sandboxTasks) - if test.injectSandbox { - c.sandboxNameIndex.Reserve(testName, testID) - assert.NoError(t, c.sandboxStore.Add(testSandbox)) - } - if test.removeSnapshotErr == nil { - fakeSnapshotClient.SetFakeMounts(testID, []*mount.Mount{ - { - Type: "bind", - Source: "/test/source", - Target: "/test/target", - }, - }) - } else { - fakeSnapshotClient.InjectError("remove", test.removeSnapshotErr) - } - if test.deleteContainerErr == nil { - _, err := fake.Create(context.Background(), &containers.CreateContainerRequest{ - Container: containers.Container{ID: testID}, - }) - assert.NoError(t, err) - } else { - fake.InjectError("delete", test.deleteContainerErr) - } - if test.taskInfoErr != nil { - fakeExecutionClient.InjectError("info", test.taskInfoErr) - } - fakeOS.RemoveAllFn = func(path string) error { - assert.Equal(t, test.expectRemoved, path) - return test.injectFSErr - } - res, err := c.RemovePodSandbox(context.Background(), &runtime.RemovePodSandboxRequest{ - PodSandboxId: testID, - }) - assert.Equal(t, test.expectCalls, fakeExecutionClient.GetCalledNames()) - if test.expectErr { - assert.Error(t, err) - assert.Nil(t, res) - continue - } - assert.NoError(t, err) - assert.NotNil(t, res) - assert.NoError(t, c.sandboxNameIndex.Reserve(testName, testID), - "sandbox name should be released") - _, err = c.sandboxStore.Get(testID) - assert.Equal(t, store.ErrNotExist, err, "sandbox should be removed") - mountsResp, err := fakeSnapshotClient.Mounts(context.Background(), &snapshotapi.MountsRequest{Key: testID}) - assert.Equal(t, servertesting.SnapshotNotExistError, err, "snapshot should be removed") - assert.Nil(t, mountsResp) - getResp, err := fake.Get(context.Background(), &containers.GetContainerRequest{ID: testID}) - assert.Equal(t, servertesting.ContainerNotExistError, err, "containerd container should be removed") - assert.Nil(t, getResp) - res, err = c.RemovePodSandbox(context.Background(), &runtime.RemovePodSandboxRequest{ - PodSandboxId: testID, - }) - assert.NoError(t, err) - assert.NotNil(t, res, "remove should be idempotent") - } -} - -func TestRemoveContainersInSandbox(t *testing.T) { - testID := "test-id" - testName := "test-name" - testSandbox := sandboxstore.Sandbox{ - Metadata: sandboxstore.Metadata{ - ID: testID, - Name: testName, - }, - } - testContainers := []containerForTest{ - { - metadata: containerstore.Metadata{ - ID: "test-cid-1", - Name: "test-cname-1", - SandboxID: testID, - }, - status: containerstore.Status{FinishedAt: time.Now().UnixNano()}, - }, - { - metadata: containerstore.Metadata{ - - ID: "test-cid-2", - Name: "test-cname-2", - SandboxID: testID, - }, - status: containerstore.Status{FinishedAt: time.Now().UnixNano()}, - }, - { - metadata: containerstore.Metadata{ - ID: "test-cid-3", - Name: "test-cname-3", - SandboxID: "other-sandbox-id", - }, - status: containerstore.Status{FinishedAt: time.Now().UnixNano()}, - }, - } - - c := newTestCRIContainerdService() - WithFakeSnapshotClient(c) - assert.NoError(t, c.sandboxNameIndex.Reserve(testName, testID)) - assert.NoError(t, c.sandboxStore.Add(testSandbox)) - for _, tc := range testContainers { - assert.NoError(t, c.containerNameIndex.Reserve(tc.metadata.Name, tc.metadata.ID)) - cntr, err := tc.toContainer() - assert.NoError(t, err) - assert.NoError(t, c.containerStore.Add(cntr)) - } - - res, err := c.RemovePodSandbox(context.Background(), &runtime.RemovePodSandboxRequest{ - PodSandboxId: testID, - }) - assert.NoError(t, err) - assert.NotNil(t, res) - - _, err = c.sandboxStore.Get(testID) - assert.Equal(t, store.ErrNotExist, err, "sandbox metadata should be removed") - - cntrs := c.containerStore.List() - assert.Len(t, cntrs, 1) - assert.Equal(t, testContainers[2].metadata, cntrs[0].Metadata, "container should be removed") - assert.Equal(t, testContainers[2].status, cntrs[0].Status.Get(), "container should be removed") -} diff --git a/pkg/server/sandbox_run_test.go b/pkg/server/sandbox_run_test.go index 675a9d8f0..6fe05cb31 100644 --- a/pkg/server/sandbox_run_test.go +++ b/pkg/server/sandbox_run_test.go @@ -17,25 +17,16 @@ limitations under the License. package server import ( - "encoding/json" - "io" "os" - "syscall" "testing" - "github.com/containerd/containerd/api/services/containers" - "github.com/containerd/containerd/api/services/execution" - snapshotapi "github.com/containerd/containerd/api/services/snapshot" imagespec "github.com/opencontainers/image-spec/specs-go/v1" runtimespec "github.com/opencontainers/runtime-spec/specs-go" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "golang.org/x/net/context" "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" ostesting "github.com/kubernetes-incubator/cri-containerd/pkg/os/testing" - servertesting "github.com/kubernetes-incubator/cri-containerd/pkg/server/testing" - imagestore "github.com/kubernetes-incubator/cri-containerd/pkg/store/image" ) func getRunPodSandboxTestData() (*runtime.PodSandboxConfig, *imagespec.ImageConfig, func(*testing.T, string, *runtimespec.Spec)) { @@ -269,112 +260,6 @@ options timeout:1 } } -func TestRunPodSandbox(t *testing.T) { - config, imageConfig, specCheck := getRunPodSandboxTestData() - c := newTestCRIContainerdService() - fake := c.containerService.(*servertesting.FakeContainersClient) - fakeSnapshotClient := WithFakeSnapshotClient(c) - fakeExecutionClient := c.taskService.(*servertesting.FakeExecutionClient) - fakeCNIPlugin := c.netPlugin.(*servertesting.FakeCNIPlugin) - fakeOS := c.os.(*ostesting.FakeOS) - var dirs []string - var pipes []string - fakeOS.MkdirAllFn = func(path string, perm os.FileMode) error { - dirs = append(dirs, path) - return nil - } - fakeOS.OpenFifoFn = func(ctx context.Context, fn string, flag int, perm os.FileMode) (io.ReadWriteCloser, error) { - pipes = append(pipes, fn) - assert.Equal(t, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, flag) - assert.Equal(t, os.FileMode(0700), perm) - return nopReadWriteCloser{}, nil - } - testChainID := "test-sandbox-chain-id" - image := imagestore.Image{ - ID: testSandboxImage, - ChainID: testChainID, - Config: imageConfig, - } - // Insert sandbox image. - c.imageStore.Add(image) - expectContainersClientCalls := []string{"create"} - expectSnapshotClientCalls := []string{"view"} - expectExecutionClientCalls := []string{"create", "start"} - - res, err := c.RunPodSandbox(context.Background(), &runtime.RunPodSandboxRequest{Config: config}) - assert.NoError(t, err) - require.NotNil(t, res) - id := res.GetPodSandboxId() - - sandboxRootDir := getSandboxRootDir(c.rootDir, id) - assert.Contains(t, dirs[0], sandboxRootDir, "sandbox root directory should be created") - - assert.Len(t, pipes, 2) - _, stdout, stderr := getStreamingPipes(sandboxRootDir) - assert.Contains(t, pipes, stdout, "sandbox stdout pipe should be created") - assert.Contains(t, pipes, stderr, "sandbox stderr pipe should be created") - - assert.Equal(t, expectSnapshotClientCalls, fakeSnapshotClient.GetCalledNames(), "expect snapshot functions should be called") - calls := fakeSnapshotClient.GetCalledDetails() - prepareOpts := calls[0].Argument.(*snapshotapi.PrepareRequest) - assert.Equal(t, &snapshotapi.PrepareRequest{ - Key: id, - Parent: testChainID, - }, prepareOpts, "prepare request should be correct") - - assert.Equal(t, expectContainersClientCalls, fake.GetCalledNames(), "expect containers functions should be called") - calls = fake.GetCalledDetails() - createOpts, ok := calls[0].Argument.(*containers.CreateContainerRequest) - assert.True(t, ok, "should create sandbox container") - assert.Equal(t, id, createOpts.Container.ID, "container id should be correct") - assert.Equal(t, testSandboxImage, createOpts.Container.Image, "test image should be correct") - assert.Equal(t, id, createOpts.Container.RootFS, "rootfs should be correct") - spec := &runtimespec.Spec{} - assert.NoError(t, json.Unmarshal(createOpts.Container.Spec.Value, spec)) - t.Logf("oci spec check") - specCheck(t, id, spec) - - assert.Equal(t, expectExecutionClientCalls, fakeExecutionClient.GetCalledNames(), "expect execution functions should be called") - calls = fakeExecutionClient.GetCalledDetails() - createTaskOpts := calls[0].Argument.(*execution.CreateRequest) - mountsResp, err := fakeSnapshotClient.Mounts(context.Background(), &snapshotapi.MountsRequest{Key: id}) - assert.NoError(t, err) - assert.Equal(t, &execution.CreateRequest{ - ContainerID: id, - Rootfs: mountsResp.Mounts, - Stdout: stdout, - Stderr: stderr, - }, createTaskOpts, "create options should be correct") - - startID := calls[1].Argument.(*execution.StartRequest).ContainerID - assert.Equal(t, id, startID, "start id should be correct") - - sandbox, err := c.sandboxStore.Get(id) - assert.NoError(t, err) - assert.Equal(t, id, sandbox.ID, "sandbox id should be correct") - err = c.sandboxNameIndex.Reserve(sandbox.Name, "random-id") - assert.Error(t, err, "sandbox name should be reserved") - assert.Equal(t, config, sandbox.Config, "sandbox config should be correct") - // TODO(random-liu): [P2] Add clock interface and use fake clock. - assert.NotZero(t, sandbox.CreatedAt, "sandbox CreatedAt should be set") - info, err := fakeExecutionClient.Info(context.Background(), &execution.InfoRequest{ContainerID: id}) - assert.NoError(t, err) - pid := info.Task.Pid - assert.Equal(t, sandbox.NetNS, getNetworkNamespace(pid), "sandbox network namespace should be correct") - - expectedCNICalls := []string{"SetUpPod"} - assert.Equal(t, expectedCNICalls, fakeCNIPlugin.GetCalledNames(), "expect SetUpPod should be called") - calls = fakeCNIPlugin.GetCalledDetails() - pluginArgument := calls[0].Argument.(servertesting.CNIPluginArgument) - expectedPluginArgument := servertesting.CNIPluginArgument{ - NetnsPath: sandbox.NetNS, - Namespace: config.GetMetadata().GetNamespace(), - Name: config.GetMetadata().GetName(), - ContainerID: id, - } - assert.Equal(t, expectedPluginArgument, pluginArgument, "SetUpPod should be called with correct arguments") -} - func TestParseDNSOption(t *testing.T) { for desc, test := range map[string]struct { servers []string diff --git a/pkg/server/sandbox_status_test.go b/pkg/server/sandbox_status_test.go deleted file mode 100644 index de79d89e8..000000000 --- a/pkg/server/sandbox_status_test.go +++ /dev/null @@ -1,218 +0,0 @@ -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package server - -import ( - "errors" - "testing" - "time" - - "github.com/containerd/containerd/api/types/task" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "golang.org/x/net/context" - "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" - - servertesting "github.com/kubernetes-incubator/cri-containerd/pkg/server/testing" - sandboxstore "github.com/kubernetes-incubator/cri-containerd/pkg/store/sandbox" -) - -// Variables used in the following test. - -const ( - sandboxStatusTestID = "test-id" - sandboxStatusTestIP = "10.10.10.10" - sandboxStatusTestNetNS = "test-netns" -) - -func getSandboxStatusTestData() (*sandboxstore.Sandbox, *runtime.PodSandboxStatus) { - config := &runtime.PodSandboxConfig{ - Metadata: &runtime.PodSandboxMetadata{ - Name: "test-name", - Uid: "test-uid", - Namespace: "test-ns", - Attempt: 1, - }, - Linux: &runtime.LinuxPodSandboxConfig{ - SecurityContext: &runtime.LinuxSandboxSecurityContext{ - NamespaceOptions: &runtime.NamespaceOption{ - HostNetwork: true, - HostPid: false, - HostIpc: true, - }, - }, - }, - Labels: map[string]string{"a": "b"}, - Annotations: map[string]string{"c": "d"}, - } - - createdAt := time.Now().UnixNano() - - sandbox := &sandboxstore.Sandbox{ - Metadata: sandboxstore.Metadata{ - ID: sandboxStatusTestID, - Name: "test-name", - Config: config, - CreatedAt: createdAt, - NetNS: sandboxStatusTestNetNS, - }, - } - - expectedStatus := &runtime.PodSandboxStatus{ - Id: sandboxStatusTestID, - Metadata: config.GetMetadata(), - CreatedAt: createdAt, - Network: &runtime.PodSandboxNetworkStatus{Ip: ""}, - Linux: &runtime.LinuxPodSandboxStatus{ - Namespaces: &runtime.Namespace{ - Options: &runtime.NamespaceOption{ - HostNetwork: true, - HostPid: false, - HostIpc: true, - }, - }, - }, - Labels: config.GetLabels(), - Annotations: config.GetAnnotations(), - } - - return sandbox, expectedStatus -} - -func TestPodSandboxStatus(t *testing.T) { - for desc, test := range map[string]struct { - sandboxTasks []task.Task - injectSandbox bool - injectErr error - injectIP bool - injectCNIErr error - expectState runtime.PodSandboxState - expectErr bool - expectCalls []string - expectedCNICalls []string - }{ - "sandbox status without metadata": { - injectSandbox: false, - expectErr: true, - expectCalls: []string{}, - expectedCNICalls: []string{}, - }, - "sandbox status with running sandbox container": { - sandboxTasks: []task.Task{{ - ID: sandboxStatusTestID, - Pid: 1, - Status: task.StatusRunning, - }}, - injectSandbox: true, - expectState: runtime.PodSandboxState_SANDBOX_READY, - expectCalls: []string{"info"}, - expectedCNICalls: []string{"GetContainerNetworkStatus"}, - }, - "sandbox status with stopped sandbox container": { - sandboxTasks: []task.Task{{ - ID: sandboxStatusTestID, - Pid: 1, - Status: task.StatusStopped, - }}, - injectSandbox: true, - expectState: runtime.PodSandboxState_SANDBOX_NOTREADY, - expectCalls: []string{"info"}, - expectedCNICalls: []string{"GetContainerNetworkStatus"}, - }, - "sandbox status with non-existing sandbox container": { - sandboxTasks: []task.Task{}, - injectSandbox: true, - expectState: runtime.PodSandboxState_SANDBOX_NOTREADY, - expectCalls: []string{"info"}, - expectedCNICalls: []string{"GetContainerNetworkStatus"}, - }, - "sandbox status with arbitrary error": { - sandboxTasks: []task.Task{{ - ID: sandboxStatusTestID, - Pid: 1, - Status: task.StatusRunning, - }}, - injectSandbox: true, - expectState: runtime.PodSandboxState_SANDBOX_READY, - injectErr: errors.New("arbitrary error"), - expectErr: true, - expectCalls: []string{"info"}, - expectedCNICalls: []string{}, - }, - "sandbox status with IP address": { - sandboxTasks: []task.Task{{ - ID: sandboxStatusTestID, - Pid: 1, - Status: task.StatusRunning, - }}, - injectSandbox: true, - expectState: runtime.PodSandboxState_SANDBOX_READY, - expectCalls: []string{"info"}, - injectIP: true, - expectedCNICalls: []string{"GetContainerNetworkStatus"}, - }, - "sandbox status with GetContainerNetworkStatus returns error": { - sandboxTasks: []task.Task{{ - ID: sandboxStatusTestID, - Pid: 1, - Status: task.StatusRunning, - }}, - injectSandbox: true, - expectState: runtime.PodSandboxState_SANDBOX_READY, - expectCalls: []string{"info"}, - expectedCNICalls: []string{"GetContainerNetworkStatus"}, - injectCNIErr: errors.New("get container network status error"), - }, - } { - t.Logf("TestCase %q", desc) - sandbox, expect := getSandboxStatusTestData() - expect.Network.Ip = "" - c := newTestCRIContainerdService() - fake := c.taskService.(*servertesting.FakeExecutionClient) - fakeCNIPlugin := c.netPlugin.(*servertesting.FakeCNIPlugin) - fake.SetFakeTasks(test.sandboxTasks) - if test.injectSandbox { - assert.NoError(t, c.sandboxStore.Add(*sandbox)) - } - if test.injectErr != nil { - fake.InjectError("info", test.injectErr) - } - if test.injectCNIErr != nil { - fakeCNIPlugin.InjectError("GetContainerNetworkStatus", test.injectCNIErr) - } - if test.injectIP { - fakeCNIPlugin.SetFakePodNetwork(sandbox.NetNS, sandbox.Config.GetMetadata().GetNamespace(), - sandbox.Config.GetMetadata().GetName(), sandboxStatusTestID, sandboxStatusTestIP) - expect.Network.Ip = sandboxStatusTestIP - } - res, err := c.PodSandboxStatus(context.Background(), &runtime.PodSandboxStatusRequest{ - PodSandboxId: sandboxStatusTestID, - }) - assert.Equal(t, test.expectCalls, fake.GetCalledNames()) - assert.Equal(t, test.expectedCNICalls, fakeCNIPlugin.GetCalledNames()) - if test.expectErr { - assert.Error(t, err) - assert.Nil(t, res) - continue - } - - assert.NoError(t, err) - require.NotNil(t, res) - expect.State = test.expectState - assert.Equal(t, expect, res.GetStatus()) - } -} diff --git a/pkg/server/sandbox_stop_test.go b/pkg/server/sandbox_stop_test.go deleted file mode 100644 index ac314ee1c..000000000 --- a/pkg/server/sandbox_stop_test.go +++ /dev/null @@ -1,292 +0,0 @@ -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package server - -import ( - "errors" - "os" - "testing" - "time" - - "github.com/containerd/containerd/api/services/execution" - "github.com/containerd/containerd/api/types/task" - "github.com/stretchr/testify/assert" - "golang.org/x/net/context" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" - "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" - - ostesting "github.com/kubernetes-incubator/cri-containerd/pkg/os/testing" - servertesting "github.com/kubernetes-incubator/cri-containerd/pkg/server/testing" - containerstore "github.com/kubernetes-incubator/cri-containerd/pkg/store/container" - sandboxstore "github.com/kubernetes-incubator/cri-containerd/pkg/store/sandbox" -) - -func TestStopPodSandbox(t *testing.T) { - testID := "test-id" - testSandbox := sandboxstore.Sandbox{ - Metadata: sandboxstore.Metadata{ - ID: testID, - Name: "test-name", - Config: &runtime.PodSandboxConfig{ - Metadata: &runtime.PodSandboxMetadata{ - Name: "test-name", - Uid: "test-uid", - Namespace: "test-ns", - }}, - NetNS: "test-netns", - }, - } - testContainer := task.Task{ - ID: testID, - Pid: 1, - Status: task.StatusRunning, - } - - for desc, test := range map[string]struct { - sandboxTasks []task.Task - injectSandbox bool - injectErr error - injectStatErr error - injectCNIErr error - injectUnmountErr error - expectErr bool - expectCalls []string - expectedCNICalls []string - }{ - "stop non-existing sandbox": { - injectSandbox: false, - expectErr: true, - expectCalls: []string{}, - expectedCNICalls: []string{}, - }, - "stop sandbox with sandbox container": { - sandboxTasks: []task.Task{testContainer}, - injectSandbox: true, - expectErr: false, - expectCalls: []string{"delete"}, - expectedCNICalls: []string{"TearDownPod"}, - }, - "stop sandbox with sandbox container not exist error": { - sandboxTasks: []task.Task{}, - injectSandbox: true, - // Inject error to make sure fake execution client returns error. - injectErr: servertesting.TaskNotExistError, - expectErr: false, - expectCalls: []string{"delete"}, - expectedCNICalls: []string{"TearDownPod"}, - }, - "stop sandbox with with arbitrary error": { - injectSandbox: true, - injectErr: grpc.Errorf(codes.Unknown, "arbitrary error"), - expectErr: true, - expectCalls: []string{"delete"}, - expectedCNICalls: []string{"TearDownPod"}, - }, - "stop sandbox with Stat returns arbitrary error": { - sandboxTasks: []task.Task{testContainer}, - injectSandbox: true, - expectErr: true, - injectStatErr: errors.New("arbitrary error"), - expectCalls: []string{}, - expectedCNICalls: []string{}, - }, - "stop sandbox with Stat returns not exist error": { - sandboxTasks: []task.Task{testContainer}, - injectSandbox: true, - expectErr: false, - expectCalls: []string{"delete"}, - injectStatErr: os.ErrNotExist, - expectedCNICalls: []string{}, - }, - "stop sandbox with TearDownPod fails": { - sandboxTasks: []task.Task{testContainer}, - injectSandbox: true, - expectErr: true, - expectedCNICalls: []string{"TearDownPod"}, - injectCNIErr: errors.New("arbitrary error"), - expectCalls: []string{}, - }, - "stop sandbox with unmount error": { - sandboxTasks: []task.Task{testContainer}, - injectSandbox: true, - expectErr: true, - expectedCNICalls: []string{"TearDownPod"}, - injectCNIErr: errors.New("arbitrary error"), - injectUnmountErr: errors.New("arbitrary error"), - expectCalls: []string{}, - }, - } { - t.Logf("TestCase %q", desc) - c := newTestCRIContainerdService() - fake := c.taskService.(*servertesting.FakeExecutionClient) - fakeCNIPlugin := c.netPlugin.(*servertesting.FakeCNIPlugin) - fakeOS := c.os.(*ostesting.FakeOS) - fake.SetFakeTasks(test.sandboxTasks) - - if test.injectSandbox { - assert.NoError(t, c.sandboxStore.Add(testSandbox)) - } - if test.injectErr != nil { - fake.InjectError("delete", test.injectErr) - } - if test.injectCNIErr != nil { - fakeCNIPlugin.InjectError("TearDownPod", test.injectCNIErr) - } - if test.injectStatErr != nil { - fakeOS.InjectError("Stat", test.injectStatErr) - } - if test.injectUnmountErr != nil { - fakeOS.InjectError("Unmount", test.injectUnmountErr) - } - fakeCNIPlugin.SetFakePodNetwork(testSandbox.NetNS, testSandbox.Config.GetMetadata().GetNamespace(), - testSandbox.Config.GetMetadata().GetName(), testID, sandboxStatusTestIP) - - res, err := c.StopPodSandbox(context.Background(), &runtime.StopPodSandboxRequest{ - PodSandboxId: testID, - }) - if test.expectErr { - assert.Error(t, err) - assert.Nil(t, res) - } else { - assert.NoError(t, err) - assert.NotNil(t, res) - } - assert.Equal(t, test.expectCalls, fake.GetCalledNames()) - assert.Equal(t, test.expectedCNICalls, fakeCNIPlugin.GetCalledNames()) - } -} - -func TestStopContainersInSandbox(t *testing.T) { - testID := "test-id" - testSandbox := sandboxstore.Sandbox{ - Metadata: sandboxstore.Metadata{ - ID: testID, - Name: "test-name", - Config: &runtime.PodSandboxConfig{ - Metadata: &runtime.PodSandboxMetadata{ - Name: "test-name", - Uid: "test-uid", - Namespace: "test-ns", - }}, - NetNS: "test-netns", - }, - } - testContainers := []containerForTest{ - { - metadata: containerstore.Metadata{ - ID: "test-cid-1", - Name: "test-cname-1", - SandboxID: testID, - }, - status: containerstore.Status{ - Pid: 2, - StartedAt: time.Now().UnixNano(), - }, - }, - { - - metadata: containerstore.Metadata{ - ID: "test-cid-2", - Name: "test-cname-2", - SandboxID: testID, - }, - status: containerstore.Status{ - Pid: 3, - StartedAt: time.Now().UnixNano(), - }, - }, - { - metadata: containerstore.Metadata{ - ID: "test-cid-3", - Name: "test-cname-3", - SandboxID: "other-sandbox-id", - }, - status: containerstore.Status{ - Pid: 4, - StartedAt: time.Now().UnixNano(), - }, - }, - } - testContainerdContainers := []task.Task{ - { - ID: testID, - Pid: 1, - Status: task.StatusRunning, - }, - { - ID: "test-cid-1", - Pid: 2, - Status: task.StatusRunning, - }, - { - ID: "test-cid-2", - Pid: 3, - Status: task.StatusRunning, - }, - { - ID: "test-cid-3", - Pid: 4, - Status: task.StatusRunning, - }, - } - - c := newTestCRIContainerdService() - fake := servertesting.NewFakeExecutionClient().WithEvents() - defer fake.Stop() - c.taskService = fake - fake.SetFakeTasks(testContainerdContainers) - c.sandboxStore.Add(testSandbox) - for _, tc := range testContainers { - cntr, err := tc.toContainer() - assert.NoError(t, err) - assert.NoError(t, c.containerStore.Add(cntr)) - } - - fakeCNIPlugin := c.netPlugin.(*servertesting.FakeCNIPlugin) - fakeCNIPlugin.SetFakePodNetwork(testSandbox.NetNS, testSandbox.Config.GetMetadata().GetNamespace(), - testSandbox.Config.GetMetadata().GetName(), testID, sandboxStatusTestIP) - - eventClient, err := fake.Events(context.Background(), &execution.EventsRequest{}) - assert.NoError(t, err) - // Start a simple test event monitor. - go func(e execution.Tasks_EventsClient) { - for { - if err := c.handleEventStream(e); err != nil { // nolint: vetshadow - return - } - } - }(eventClient) - res, err := c.StopPodSandbox(context.Background(), &runtime.StopPodSandboxRequest{ - PodSandboxId: testID, - }) - assert.NoError(t, err) - assert.NotNil(t, res) - - cntrs := c.containerStore.List() - assert.Len(t, cntrs, 3) - expectedStates := map[string]runtime.ContainerState{ - "test-cid-1": runtime.ContainerState_CONTAINER_EXITED, - "test-cid-2": runtime.ContainerState_CONTAINER_EXITED, - "test-cid-3": runtime.ContainerState_CONTAINER_RUNNING, - } - for id, expected := range expectedStates { - cntr, err := c.containerStore.Get(id) - assert.NoError(t, err) - assert.Equal(t, expected, cntr.Status.Get().State()) - } -} diff --git a/pkg/server/service_test.go b/pkg/server/service_test.go index 3a5734aec..7d92dc3fc 100644 --- a/pkg/server/service_test.go +++ b/pkg/server/service_test.go @@ -18,16 +18,6 @@ package server import ( "io" - "os" - "testing" - - "github.com/containerd/containerd/api/services/execution" - snapshotservice "github.com/containerd/containerd/services/snapshot" - imagespec "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "golang.org/x/net/context" - "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime" ostesting "github.com/kubernetes-incubator/cri-containerd/pkg/os/testing" "github.com/kubernetes-incubator/cri-containerd/pkg/registrar" @@ -64,132 +54,7 @@ func newTestCRIContainerdService() *criContainerdService { sandboxNameIndex: registrar.NewRegistrar(), containerStore: containerstore.NewStore(), containerNameIndex: registrar.NewRegistrar(), - taskService: servertesting.NewFakeExecutionClient(), - containerService: servertesting.NewFakeContainersClient(), netPlugin: servertesting.NewFakeCNIPlugin(), agentFactory: agentstesting.NewFakeAgentFactory(), } } - -// WithFakeSnapshotClient add and return fake snapshot client. -func WithFakeSnapshotClient(c *criContainerdService) *servertesting.FakeSnapshotClient { - fake := servertesting.NewFakeSnapshotClient() - c.snapshotService = snapshotservice.NewSnapshotterFromClient(fake) - return fake -} - -// Test all sandbox operations. -func TestSandboxOperations(t *testing.T) { - c := newTestCRIContainerdService() - fake := c.taskService.(*servertesting.FakeExecutionClient) - fakeOS := c.os.(*ostesting.FakeOS) - fakeCNIPlugin := c.netPlugin.(*servertesting.FakeCNIPlugin) - WithFakeSnapshotClient(c) - fakeOS.OpenFifoFn = func(ctx context.Context, fn string, flag int, perm os.FileMode) (io.ReadWriteCloser, error) { - return nopReadWriteCloser{}, nil - } - // Insert sandbox image metadata. - c.imageStore.Add(imagestore.Image{ - ID: testSandboxImage, - ChainID: "test-chain-id", - Config: &imagespec.ImageConfig{Entrypoint: []string{"/pause"}}, - }) - - config := &runtime.PodSandboxConfig{ - Metadata: &runtime.PodSandboxMetadata{ - Name: "test-name", - Uid: "test-uid", - Namespace: "test-ns", - Attempt: 1, - }, - Hostname: "test-hostname", - LogDirectory: "test-log-directory", - Labels: map[string]string{"a": "b"}, - Annotations: map[string]string{"c": "d"}, - } - - t.Logf("should be able to run a pod sandbox") - runRes, err := c.RunPodSandbox(context.Background(), &runtime.RunPodSandboxRequest{Config: config}) - assert.NoError(t, err) - require.NotNil(t, runRes) - id := runRes.GetPodSandboxId() - - t.Logf("should be able to get pod sandbox status") - info, err := fake.Info(context.Background(), &execution.InfoRequest{ContainerID: id}) - netns := getNetworkNamespace(info.Task.Pid) - assert.NoError(t, err) - expectSandboxStatus := &runtime.PodSandboxStatus{ - Id: id, - Metadata: config.GetMetadata(), - // TODO(random-liu): [P2] Use fake clock for CreatedAt. - Network: &runtime.PodSandboxNetworkStatus{}, - Linux: &runtime.LinuxPodSandboxStatus{ - Namespaces: &runtime.Namespace{ - Options: &runtime.NamespaceOption{ - HostNetwork: false, - HostPid: false, - HostIpc: false, - }, - }, - }, - Labels: config.GetLabels(), - Annotations: config.GetAnnotations(), - } - statusRes, err := c.PodSandboxStatus(context.Background(), &runtime.PodSandboxStatusRequest{PodSandboxId: id}) - assert.NoError(t, err) - require.NotNil(t, statusRes) - status := statusRes.GetStatus() - expectSandboxStatus.CreatedAt = status.GetCreatedAt() - ip, err := fakeCNIPlugin.GetContainerNetworkStatus(netns, config.GetMetadata().GetNamespace(), config.GetMetadata().GetName(), id) - assert.NoError(t, err) - expectSandboxStatus.Network.Ip = ip - assert.Equal(t, expectSandboxStatus, status) - - t.Logf("should be able to list pod sandboxes") - expectSandbox := &runtime.PodSandbox{ - Id: id, - Metadata: config.GetMetadata(), - State: runtime.PodSandboxState_SANDBOX_NOTREADY, // TODO(mikebrow) converting to client... should this be ready? - Labels: config.GetLabels(), - Annotations: config.GetAnnotations(), - } - listRes, err := c.ListPodSandbox(context.Background(), &runtime.ListPodSandboxRequest{}) - assert.NoError(t, err) - require.NotNil(t, listRes) - sandboxes := listRes.GetItems() - assert.Len(t, sandboxes, 1) - expectSandbox.CreatedAt = sandboxes[0].CreatedAt - assert.Equal(t, expectSandbox, sandboxes[0]) - - t.Logf("should be able to stop a pod sandbox") - stopRes, err := c.StopPodSandbox(context.Background(), &runtime.StopPodSandboxRequest{PodSandboxId: id}) - assert.NoError(t, err) - require.NotNil(t, stopRes) - statusRes, err = c.PodSandboxStatus(context.Background(), &runtime.PodSandboxStatusRequest{PodSandboxId: id}) - assert.NoError(t, err) - require.NotNil(t, statusRes) - assert.Equal(t, runtime.PodSandboxState_SANDBOX_NOTREADY, statusRes.GetStatus().GetState(), - "sandbox status should be NOTREADY after stopped") - listRes, err = c.ListPodSandbox(context.Background(), &runtime.ListPodSandboxRequest{}) - assert.NoError(t, err) - require.NotNil(t, listRes) - assert.Len(t, listRes.GetItems(), 1) - assert.Equal(t, runtime.PodSandboxState_SANDBOX_NOTREADY, listRes.GetItems()[0].State, - "sandbox in list should be NOTREADY after stopped") - - t.Logf("should be able to remove a pod sandbox") - removeRes, err := c.RemovePodSandbox(context.Background(), &runtime.RemovePodSandboxRequest{PodSandboxId: id}) - assert.NoError(t, err) - require.NotNil(t, removeRes) - _, err = c.PodSandboxStatus(context.Background(), &runtime.PodSandboxStatusRequest{PodSandboxId: id}) - assert.Error(t, err, "should not be able to get sandbox status after removed") - listRes, err = c.ListPodSandbox(context.Background(), &runtime.ListPodSandboxRequest{}) - assert.NoError(t, err) - require.NotNil(t, listRes) - assert.Empty(t, listRes.GetItems(), "should not be able to list the sandbox after removed") - - t.Logf("should be able to create the sandbox again") - runRes, err = c.RunPodSandbox(context.Background(), &runtime.RunPodSandboxRequest{Config: config}) - assert.NoError(t, err) - require.NotNil(t, runRes) -} diff --git a/pkg/server/testing/fake_cni_plugin.go b/pkg/server/testing/fake_cni_plugin.go index 09fc829d3..e9bad3917 100644 --- a/pkg/server/testing/fake_cni_plugin.go +++ b/pkg/server/testing/fake_cni_plugin.go @@ -26,6 +26,14 @@ import ( "github.com/kubernetes-incubator/cri-o/pkg/ocicni" ) +// CalledDetail is the struct contains called function name and arguments. +type CalledDetail struct { + // Name of the function called. + Name string + // Argument of the function called. + Argument interface{} +} + // CNIPluginArgument is arguments used to call CNI related functions. type CNIPluginArgument struct { NetnsPath string diff --git a/pkg/server/testing/fake_containers_client.go b/pkg/server/testing/fake_containers_client.go deleted file mode 100644 index 03676cb0c..000000000 --- a/pkg/server/testing/fake_containers_client.go +++ /dev/null @@ -1,181 +0,0 @@ -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package testing - -import ( - "fmt" - "sync" - - "github.com/containerd/containerd/api/services/containers" - googleprotobuf "github.com/golang/protobuf/ptypes/empty" - "golang.org/x/net/context" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" -) - -// ContainerNotExistError is the fake error returned when container does not exist. -var ContainerNotExistError = grpc.Errorf(codes.NotFound, "container does not exist") - -// FakeContainersClient is a simple fake containers client, so that cri-containerd -// can be run for testing without requiring a real containerd setup. -type FakeContainersClient struct { - sync.Mutex - called []CalledDetail - errors map[string]error - ContainerList map[string]containers.Container -} - -var _ containers.ContainersClient = &FakeContainersClient{} - -// NewFakeContainersClient creates a FakeContainersClient -func NewFakeContainersClient() *FakeContainersClient { - return &FakeContainersClient{ - errors: make(map[string]error), - ContainerList: make(map[string]containers.Container), - } -} - -func (f *FakeContainersClient) getError(op string) error { - err, ok := f.errors[op] - if ok { - delete(f.errors, op) - return err - } - return nil -} - -// InjectError inject error for call -func (f *FakeContainersClient) InjectError(fn string, err error) { - f.Lock() - defer f.Unlock() - f.errors[fn] = err -} - -// InjectErrors inject errors for calls -func (f *FakeContainersClient) InjectErrors(errs map[string]error) { - f.Lock() - defer f.Unlock() - for fn, err := range errs { - f.errors[fn] = err - } -} - -// ClearErrors clear errors for call -func (f *FakeContainersClient) ClearErrors() { - f.Lock() - defer f.Unlock() - f.errors = make(map[string]error) -} - -func (f *FakeContainersClient) appendCalled(name string, argument interface{}) { - call := CalledDetail{Name: name, Argument: argument} - f.called = append(f.called, call) -} - -// GetCalledNames get names of call -func (f *FakeContainersClient) GetCalledNames() []string { - f.Lock() - defer f.Unlock() - names := []string{} - for _, detail := range f.called { - names = append(names, detail.Name) - } - return names -} - -// ClearCalls clear all call detail. -func (f *FakeContainersClient) ClearCalls() { - f.Lock() - defer f.Unlock() - f.called = []CalledDetail{} -} - -// GetCalledDetails get detail of each call. -func (f *FakeContainersClient) GetCalledDetails() []CalledDetail { - f.Lock() - defer f.Unlock() - // Copy the list and return. - return append([]CalledDetail{}, f.called...) -} - -// Create is a test implementation of containers.Create. -func (f *FakeContainersClient) Create(ctx context.Context, createOpts *containers.CreateContainerRequest, opts ...grpc.CallOption) (*containers.CreateContainerResponse, error) { - f.Lock() - defer f.Unlock() - f.appendCalled("create", createOpts) - if err := f.getError("create"); err != nil { - return nil, err - } - _, ok := f.ContainerList[createOpts.Container.ID] - if ok { - return nil, fmt.Errorf("container already exists") - } - f.ContainerList[createOpts.Container.ID] = createOpts.Container - return &containers.CreateContainerResponse{Container: createOpts.Container}, nil -} - -// Delete is a test implementation of containers.Delete -func (f *FakeContainersClient) Delete(ctx context.Context, deleteOpts *containers.DeleteContainerRequest, opts ...grpc.CallOption) (*googleprotobuf.Empty, error) { - f.Lock() - defer f.Unlock() - f.appendCalled("delete", deleteOpts) - if err := f.getError("delete"); err != nil { - return nil, err - } - _, ok := f.ContainerList[deleteOpts.ID] - if !ok { - return nil, ContainerNotExistError - } - delete(f.ContainerList, deleteOpts.ID) - return &googleprotobuf.Empty{}, nil -} - -// Get is a test implementation of containers.Get -func (f *FakeContainersClient) Get(ctx context.Context, getOpts *containers.GetContainerRequest, opts ...grpc.CallOption) (*containers.GetContainerResponse, error) { - f.Lock() - defer f.Unlock() - f.appendCalled("get", getOpts) - if err := f.getError("get"); err != nil { - return nil, err - } - c, ok := f.ContainerList[getOpts.ID] - if !ok { - return nil, ContainerNotExistError - } - return &containers.GetContainerResponse{Container: c}, nil -} - -// List is a test implementation of containers.List -func (f *FakeContainersClient) List(ctx context.Context, listOpts *containers.ListContainersRequest, opts ...grpc.CallOption) (*containers.ListContainersResponse, error) { - f.Lock() - defer f.Unlock() - f.appendCalled("list", listOpts) - if err := f.getError("list"); err != nil { - return nil, err - } - var cs []containers.Container - for _, c := range f.ContainerList { - cs = append(cs, c) - } - return &containers.ListContainersResponse{Containers: cs}, nil -} - -// Update is a test implementation of containers.Update -func (f *FakeContainersClient) Update(ctx context.Context, updateOpts *containers.UpdateContainerRequest, opts ...grpc.CallOption) (*containers.UpdateContainerResponse, error) { - // TODO: implement Update() - return nil, nil -} diff --git a/pkg/server/testing/fake_execution_client.go b/pkg/server/testing/fake_execution_client.go deleted file mode 100644 index 76821372b..000000000 --- a/pkg/server/testing/fake_execution_client.go +++ /dev/null @@ -1,392 +0,0 @@ -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package testing - -import ( - "fmt" - "math/rand" - "sync" - "time" - - "github.com/containerd/containerd/api/services/execution" - "github.com/containerd/containerd/api/types/task" - googleprotobuf "github.com/golang/protobuf/ptypes/empty" - "golang.org/x/net/context" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" -) - -// TaskNotExistError is the fake error returned when task does not exist. -var TaskNotExistError = grpc.Errorf(codes.NotFound, "task does not exist") - -// CalledDetail is the struct contains called function name and arguments. -type CalledDetail struct { - // Name of the function called. - Name string - // Argument of the function called. - Argument interface{} -} - -var _ execution.Tasks_EventsClient = &EventClient{} - -// EventClient is a test implementation of execution.Tasks_EventsClient -type EventClient struct { - Events chan *task.Event - grpc.ClientStream -} - -// Recv is a test implementation of Recv -func (cli *EventClient) Recv() (*task.Event, error) { - event, ok := <-cli.Events - if !ok { - return nil, fmt.Errorf("event channel closed") - } - return event, nil -} - -// FakeExecutionClient is a simple fake execution client, so that cri-containerd -// can be run for testing without requiring a real containerd setup. -type FakeExecutionClient struct { - sync.Mutex - called []CalledDetail - errors map[string]error - TaskList map[string]task.Task - eventsQueue chan *task.Event - eventClients []*EventClient -} - -var _ execution.TasksClient = &FakeExecutionClient{} - -// NewFakeExecutionClient creates a FakeExecutionClient -func NewFakeExecutionClient() *FakeExecutionClient { - return &FakeExecutionClient{ - errors: make(map[string]error), - TaskList: make(map[string]task.Task), - } -} - -// Stop the fake execution service. Needed when event is enabled. -func (f *FakeExecutionClient) Stop() { - if f.eventsQueue != nil { - close(f.eventsQueue) - } - f.Lock() - defer f.Unlock() - for _, client := range f.eventClients { - close(client.Events) - } - f.eventClients = nil -} - -// WithEvents setup events publisher for FakeExecutionClient -func (f *FakeExecutionClient) WithEvents() *FakeExecutionClient { - f.eventsQueue = make(chan *task.Event, 1024) - go func() { - for e := range f.eventsQueue { - f.Lock() - for _, client := range f.eventClients { - client.Events <- e - } - f.Unlock() - } - }() - return f -} - -func (f *FakeExecutionClient) getError(op string) error { - err, ok := f.errors[op] - if ok { - delete(f.errors, op) - return err - } - return nil -} - -// InjectError inject error for call -func (f *FakeExecutionClient) InjectError(fn string, err error) { - f.Lock() - defer f.Unlock() - f.errors[fn] = err -} - -// InjectErrors inject errors for calls -func (f *FakeExecutionClient) InjectErrors(errs map[string]error) { - f.Lock() - defer f.Unlock() - for fn, err := range errs { - f.errors[fn] = err - } -} - -// ClearErrors clear errors for call -func (f *FakeExecutionClient) ClearErrors() { - f.Lock() - defer f.Unlock() - f.errors = make(map[string]error) -} - -func generatePid() uint32 { - rand.Seed(time.Now().Unix()) - randPid := uint32(rand.Intn(1000)) - return randPid -} - -func (f *FakeExecutionClient) sendEvent(event *task.Event) { - if f.eventsQueue != nil { - f.eventsQueue <- event - } -} - -func (f *FakeExecutionClient) appendCalled(name string, argument interface{}) { - call := CalledDetail{Name: name, Argument: argument} - f.called = append(f.called, call) -} - -// GetCalledNames get names of call -func (f *FakeExecutionClient) GetCalledNames() []string { - f.Lock() - defer f.Unlock() - names := []string{} - for _, detail := range f.called { - names = append(names, detail.Name) - } - return names -} - -// ClearCalls clear all call detail. -func (f *FakeExecutionClient) ClearCalls() { - f.Lock() - defer f.Unlock() - f.called = []CalledDetail{} -} - -// GetCalledDetails get detail of each call. -func (f *FakeExecutionClient) GetCalledDetails() []CalledDetail { - f.Lock() - defer f.Unlock() - // Copy the list and return. - return append([]CalledDetail{}, f.called...) -} - -// SetFakeTasks injects fake tasks. -func (f *FakeExecutionClient) SetFakeTasks(tasks []task.Task) { - f.Lock() - defer f.Unlock() - for _, t := range tasks { - f.TaskList[t.ID] = t - } -} - -// Create is a test implementation of execution.Create. -func (f *FakeExecutionClient) Create(ctx context.Context, createOpts *execution.CreateRequest, opts ...grpc.CallOption) (*execution.CreateResponse, error) { - f.Lock() - defer f.Unlock() - f.appendCalled("create", createOpts) - if err := f.getError("create"); err != nil { - return nil, err - } - _, ok := f.TaskList[createOpts.ContainerID] - if ok { - return nil, fmt.Errorf("task already exists") - } - pid := generatePid() - f.TaskList[createOpts.ContainerID] = task.Task{ - ContainerID: createOpts.ContainerID, - Pid: pid, - Status: task.StatusCreated, - } - f.sendEvent(&task.Event{ - ID: createOpts.ContainerID, - Type: task.Event_CREATE, - Pid: pid, - }) - return &execution.CreateResponse{ - ContainerID: createOpts.ContainerID, - Pid: pid, - }, nil -} - -// Start is a test implementation of execution.Start -func (f *FakeExecutionClient) Start(ctx context.Context, startOpts *execution.StartRequest, opts ...grpc.CallOption) (*googleprotobuf.Empty, error) { - f.Lock() - defer f.Unlock() - f.appendCalled("start", startOpts) - if err := f.getError("start"); err != nil { - return nil, err - } - c, ok := f.TaskList[startOpts.ContainerID] - if !ok { - return nil, TaskNotExistError - } - f.sendEvent(&task.Event{ - ID: c.ID, - Type: task.Event_START, - Pid: c.Pid, - }) - switch c.Status { - case task.StatusCreated: - c.Status = task.StatusRunning - f.TaskList[startOpts.ContainerID] = c - return &googleprotobuf.Empty{}, nil - case task.StatusStopped: - return &googleprotobuf.Empty{}, fmt.Errorf("cannot start a container that has stopped") - case task.StatusRunning: - return &googleprotobuf.Empty{}, fmt.Errorf("cannot start an already running container") - default: - return &googleprotobuf.Empty{}, fmt.Errorf("cannot start a container in the %s state", c.Status) - } -} - -// Delete is a test implementation of execution.Delete -func (f *FakeExecutionClient) Delete(ctx context.Context, deleteOpts *execution.DeleteRequest, opts ...grpc.CallOption) (*execution.DeleteResponse, error) { - f.Lock() - defer f.Unlock() - f.appendCalled("delete", deleteOpts) - if err := f.getError("delete"); err != nil { - return nil, err - } - c, ok := f.TaskList[deleteOpts.ContainerID] - if !ok { - return nil, TaskNotExistError - } - delete(f.TaskList, deleteOpts.ContainerID) - f.sendEvent(&task.Event{ - ID: c.ID, - Type: task.Event_EXIT, - Pid: c.Pid, - }) - return nil, nil -} - -// Info is a test implementation of execution.Info -func (f *FakeExecutionClient) Info(ctx context.Context, infoOpts *execution.InfoRequest, opts ...grpc.CallOption) (*execution.InfoResponse, error) { - f.Lock() - defer f.Unlock() - f.appendCalled("info", infoOpts) - if err := f.getError("info"); err != nil { - return nil, err - } - c, ok := f.TaskList[infoOpts.ContainerID] - if !ok { - return nil, TaskNotExistError - } - return &execution.InfoResponse{Task: &c}, nil -} - -// List is a test implementation of execution.List -func (f *FakeExecutionClient) List(ctx context.Context, listOpts *execution.ListRequest, opts ...grpc.CallOption) (*execution.ListResponse, error) { - f.Lock() - defer f.Unlock() - f.appendCalled("list", listOpts) - if err := f.getError("list"); err != nil { - return nil, err - } - resp := &execution.ListResponse{} - for _, c := range f.TaskList { - resp.Tasks = append(resp.Tasks, &task.Task{ - ID: c.ID, - Pid: c.Pid, - Status: c.Status, - }) - } - return resp, nil -} - -// Kill is a test implementation of execution.Kill -func (f *FakeExecutionClient) Kill(ctx context.Context, killOpts *execution.KillRequest, opts ...grpc.CallOption) (*googleprotobuf.Empty, error) { - f.Lock() - defer f.Unlock() - f.appendCalled("kill", killOpts) - if err := f.getError("kill"); err != nil { - return nil, err - } - c, ok := f.TaskList[killOpts.ContainerID] - if !ok { - return nil, TaskNotExistError - } - c.Status = task.StatusStopped - f.TaskList[killOpts.ContainerID] = c - f.sendEvent(&task.Event{ - ID: c.ID, - Type: task.Event_EXIT, - Pid: c.Pid, - }) - return &googleprotobuf.Empty{}, nil -} - -// Events is a test implementation of execution.Events -func (f *FakeExecutionClient) Events(ctx context.Context, eventsOpts *execution.EventsRequest, opts ...grpc.CallOption) (execution.Tasks_EventsClient, error) { - f.Lock() - defer f.Unlock() - f.appendCalled("events", eventsOpts) - if err := f.getError("events"); err != nil { - return nil, err - } - var client = &EventClient{ - Events: make(chan *task.Event, 100), - } - f.eventClients = append(f.eventClients, client) - return client, nil -} - -// Exec is a test implementation of execution.Exec -func (f *FakeExecutionClient) Exec(ctx context.Context, execOpts *execution.ExecRequest, opts ...grpc.CallOption) (*execution.ExecResponse, error) { - // TODO: implement Exec() - return nil, nil -} - -// Pty is a test implementation of execution.Pty -func (f *FakeExecutionClient) Pty(ctx context.Context, ptyOpts *execution.PtyRequest, opts ...grpc.CallOption) (*googleprotobuf.Empty, error) { - // TODO: implement Pty() - return nil, nil -} - -// CloseStdin is a test implementation of execution.CloseStdin -func (f *FakeExecutionClient) CloseStdin(ctx context.Context, closeStdinOpts *execution.CloseStdinRequest, opts ...grpc.CallOption) (*googleprotobuf.Empty, error) { - // TODO: implement CloseStdin() - return nil, nil -} - -// Pause is a test implementation of execution.Pause -func (f *FakeExecutionClient) Pause(ctx context.Context, in *execution.PauseRequest, opts ...grpc.CallOption) (*googleprotobuf.Empty, error) { - // TODO: implement Pause() - return nil, nil -} - -// Resume is a test implementation of execution.Resume -func (f *FakeExecutionClient) Resume(ctx context.Context, in *execution.ResumeRequest, opts ...grpc.CallOption) (*googleprotobuf.Empty, error) { - // TODO: implement Resume() - return nil, nil -} - -// Checkpoint is a test implementation of execution.Checkpoint -func (f *FakeExecutionClient) Checkpoint(ctx context.Context, in *execution.CheckpointRequest, opts ...grpc.CallOption) (*execution.CheckpointResponse, error) { - // TODO: implement Checkpoint() - return nil, nil -} - -// Processes is a test implementation of execution.Processes -func (f *FakeExecutionClient) Processes(ctx context.Context, in *execution.ProcessesRequest, opts ...grpc.CallOption) (*execution.ProcessesResponse, error) { - // TODO: implement Processes() - return nil, nil -} - -// DeleteProcess is a test implementation of execution.DeleteProcess -func (f *FakeExecutionClient) DeleteProcess(ctx context.Context, in *execution.DeleteProcessRequest, opts ...grpc.CallOption) (*execution.DeleteResponse, error) { - // TODO: implement DeleteProcess() - return nil, nil -} diff --git a/pkg/server/testing/fake_images_client.go b/pkg/server/testing/fake_images_client.go deleted file mode 100644 index c2e39916c..000000000 --- a/pkg/server/testing/fake_images_client.go +++ /dev/null @@ -1,164 +0,0 @@ -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package testing - -import ( - "fmt" - "sync" - - "github.com/containerd/containerd/api/services/images" - googleprotobuf "github.com/golang/protobuf/ptypes/empty" - "golang.org/x/net/context" - "google.golang.org/grpc" -) - -// FakeImagesClient is a simple fake images client, so that cri-containerd -// can be run for testing without requiring a real containerd setup. -type FakeImagesClient struct { - sync.Mutex - called []CalledDetail - errors map[string]error - ImageList map[string]images.Image -} - -var _ images.ImagesClient = &FakeImagesClient{} - -// NewFakeImagesClient creates a FakeImagesClient -func NewFakeImagesClient() *FakeImagesClient { - return &FakeImagesClient{ - errors: make(map[string]error), - ImageList: make(map[string]images.Image), - } -} - -// getError get error for call -func (f *FakeImagesClient) getError(op string) error { - err, ok := f.errors[op] - if ok { - delete(f.errors, op) - return err - } - return nil -} - -// InjectError inject error for call -func (f *FakeImagesClient) InjectError(fn string, err error) { - f.Lock() - defer f.Unlock() - f.errors[fn] = err -} - -// InjectErrors inject errors for calls -func (f *FakeImagesClient) InjectErrors(errs map[string]error) { - f.Lock() - defer f.Unlock() - for fn, err := range errs { - f.errors[fn] = err - } -} - -// ClearErrors clear errors for call -func (f *FakeImagesClient) ClearErrors() { - f.Lock() - defer f.Unlock() - f.errors = make(map[string]error) -} - -func (f *FakeImagesClient) appendCalled(name string, argument interface{}) { - call := CalledDetail{Name: name, Argument: argument} - f.called = append(f.called, call) -} - -// GetCalledNames get names of call -func (f *FakeImagesClient) GetCalledNames() []string { - f.Lock() - defer f.Unlock() - names := []string{} - for _, detail := range f.called { - names = append(names, detail.Name) - } - return names -} - -// SetFakeImages injects fake images. -func (f *FakeImagesClient) SetFakeImages(images []images.Image) { - f.Lock() - defer f.Unlock() - for _, image := range images { - f.ImageList[image.Name] = image - } -} - -// Get is a test implementation of images.Get -func (f *FakeImagesClient) Get(ctx context.Context, getOpts *images.GetRequest, opts ...grpc.CallOption) (*images.GetResponse, error) { - f.Lock() - defer f.Unlock() - f.appendCalled("get", getOpts) - if err := f.getError("get"); err != nil { - return nil, err - } - image, ok := f.ImageList[getOpts.Name] - if !ok { - return nil, fmt.Errorf("image does not exist") - } - return &images.GetResponse{ - Image: &image, - }, nil -} - -// Put is a test implementation of images.Put -func (f *FakeImagesClient) Put(ctx context.Context, putOpts *images.PutRequest, opts ...grpc.CallOption) (*googleprotobuf.Empty, error) { - f.Lock() - defer f.Unlock() - f.appendCalled("put", putOpts) - if err := f.getError("put"); err != nil { - return nil, err - } - f.ImageList[putOpts.Image.Name] = putOpts.Image - return &googleprotobuf.Empty{}, nil -} - -// List is a test implementation of images.List -func (f *FakeImagesClient) List(ctx context.Context, listOpts *images.ListRequest, opts ...grpc.CallOption) (*images.ListResponse, error) { - f.Lock() - defer f.Unlock() - f.appendCalled("list", listOpts) - if err := f.getError("list"); err != nil { - return nil, err - } - resp := &images.ListResponse{} - for _, image := range f.ImageList { - resp.Images = append(resp.Images, image) - } - return resp, nil -} - -// Delete is a test implementation of images.Delete -func (f *FakeImagesClient) Delete(ctx context.Context, deleteOpts *images.DeleteRequest, opts ...grpc.CallOption) (*googleprotobuf.Empty, error) { - f.Lock() - defer f.Unlock() - f.appendCalled("delete", deleteOpts) - if err := f.getError("delete"); err != nil { - return nil, err - } - _, ok := f.ImageList[deleteOpts.Name] - if !ok { - return nil, fmt.Errorf("image does not exist") - } - delete(f.ImageList, deleteOpts.Name) - return &googleprotobuf.Empty{}, nil -} diff --git a/pkg/server/testing/fake_snapshot_client.go b/pkg/server/testing/fake_snapshot_client.go deleted file mode 100644 index 7de9cde8c..000000000 --- a/pkg/server/testing/fake_snapshot_client.go +++ /dev/null @@ -1,221 +0,0 @@ -/* -Copyright 2017 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package testing - -import ( - "fmt" - "sync" - - "github.com/containerd/containerd/api/services/snapshot" - "github.com/containerd/containerd/api/types/mount" - google_protobuf1 "github.com/golang/protobuf/ptypes/empty" - "golang.org/x/net/context" - "google.golang.org/grpc" - "google.golang.org/grpc/codes" -) - -// SnapshotNotExistError is the fake error returned when snapshot does not exist. -var SnapshotNotExistError = grpc.Errorf(codes.NotFound, "snapshot does not exist") - -// FakeSnapshotClient is a simple fake snapshot client, so that cri-containerd -// can be run for testing without requiring a real containerd setup. -type FakeSnapshotClient struct { - sync.Mutex - called []CalledDetail - errors map[string]error - MountList map[string][]*mount.Mount -} - -var _ snapshot.SnapshotClient = &FakeSnapshotClient{} - -// NewFakeSnapshotClient creates a FakeSnapshotClient -func NewFakeSnapshotClient() *FakeSnapshotClient { - return &FakeSnapshotClient{ - errors: make(map[string]error), - MountList: make(map[string][]*mount.Mount), - } -} - -func (f *FakeSnapshotClient) getError(op string) error { - err, ok := f.errors[op] - if ok { - delete(f.errors, op) - return err - } - return nil -} - -// InjectError inject error for call -func (f *FakeSnapshotClient) InjectError(fn string, err error) { - f.Lock() - defer f.Unlock() - f.errors[fn] = err -} - -// InjectErrors inject errors for calls -func (f *FakeSnapshotClient) InjectErrors(errs map[string]error) { - f.Lock() - defer f.Unlock() - for fn, err := range errs { - f.errors[fn] = err - } -} - -// ClearErrors clear errors for call -func (f *FakeSnapshotClient) ClearErrors() { - f.Lock() - defer f.Unlock() - f.errors = make(map[string]error) -} - -func (f *FakeSnapshotClient) appendCalled(name string, argument interface{}) { - call := CalledDetail{Name: name, Argument: argument} - f.called = append(f.called, call) -} - -// GetCalledNames get names of call -func (f *FakeSnapshotClient) GetCalledNames() []string { - f.Lock() - defer f.Unlock() - names := []string{} - for _, detail := range f.called { - names = append(names, detail.Name) - } - return names -} - -// GetCalledDetails get detail of each call. -func (f *FakeSnapshotClient) GetCalledDetails() []CalledDetail { - f.Lock() - defer f.Unlock() - // Copy the list and return. - return append([]CalledDetail{}, f.called...) -} - -// SetFakeMounts injects fake mounts. -func (f *FakeSnapshotClient) SetFakeMounts(name string, mounts []*mount.Mount) { - f.Lock() - defer f.Unlock() - f.MountList[name] = mounts -} - -// ListMounts lists all the fake mounts. -func (f *FakeSnapshotClient) ListMounts() [][]*mount.Mount { - f.Lock() - defer f.Unlock() - var ms [][]*mount.Mount - for _, m := range f.MountList { - ms = append(ms, m) - } - return ms -} - -// Prepare is a test implementation of snapshot.Prepare -func (f *FakeSnapshotClient) Prepare(ctx context.Context, prepareOpts *snapshot.PrepareRequest, opts ...grpc.CallOption) (*snapshot.MountsResponse, error) { - f.Lock() - defer f.Unlock() - f.appendCalled("prepare", prepareOpts) - if err := f.getError("prepare"); err != nil { - return nil, err - } - _, ok := f.MountList[prepareOpts.Key] - if ok { - return nil, fmt.Errorf("mounts already exist") - } - f.MountList[prepareOpts.Key] = []*mount.Mount{{ - Type: "bind", - Source: prepareOpts.Key, - // TODO(random-liu): Fake options based on Readonly option. - }} - return &snapshot.MountsResponse{ - Mounts: f.MountList[prepareOpts.Key], - }, nil -} - -// Mounts is a test implementation of snapshot.Mounts -func (f *FakeSnapshotClient) Mounts(ctx context.Context, mountsOpts *snapshot.MountsRequest, opts ...grpc.CallOption) (*snapshot.MountsResponse, error) { - f.Lock() - defer f.Unlock() - f.appendCalled("mounts", mountsOpts) - if err := f.getError("mounts"); err != nil { - return nil, err - } - mounts, ok := f.MountList[mountsOpts.Key] - if !ok { - return nil, SnapshotNotExistError - } - return &snapshot.MountsResponse{ - Mounts: mounts, - }, nil -} - -// Commit is a test implementation of snapshot.Commit -func (f *FakeSnapshotClient) Commit(ctx context.Context, in *snapshot.CommitRequest, opts ...grpc.CallOption) (*google_protobuf1.Empty, error) { - return nil, nil -} - -// View is a test implementation of snapshot.View -func (f *FakeSnapshotClient) View(ctx context.Context, viewOpts *snapshot.PrepareRequest, opts ...grpc.CallOption) (*snapshot.MountsResponse, error) { - f.Lock() - defer f.Unlock() - f.appendCalled("view", viewOpts) - if err := f.getError("view"); err != nil { - return nil, err - } - _, ok := f.MountList[viewOpts.Key] - if ok { - return nil, fmt.Errorf("mounts already exist") - } - f.MountList[viewOpts.Key] = []*mount.Mount{{ - Type: "bind", - Source: viewOpts.Key, - // TODO(random-liu): Fake options based on Readonly option. - }} - return &snapshot.MountsResponse{ - Mounts: f.MountList[viewOpts.Key], - }, nil -} - -// Remove is a test implementation of snapshot.Remove -func (f *FakeSnapshotClient) Remove(ctx context.Context, removeOpts *snapshot.RemoveRequest, opts ...grpc.CallOption) (*google_protobuf1.Empty, error) { - f.Lock() - defer f.Unlock() - f.appendCalled("remove", removeOpts) - if err := f.getError("remove"); err != nil { - return nil, err - } - if _, ok := f.MountList[removeOpts.Key]; !ok { - return nil, SnapshotNotExistError - } - delete(f.MountList, removeOpts.Key) - return &google_protobuf1.Empty{}, nil -} - -// Stat is a test implementation of snapshot.Stat -func (f *FakeSnapshotClient) Stat(ctx context.Context, in *snapshot.StatRequest, opts ...grpc.CallOption) (*snapshot.StatResponse, error) { - return nil, nil -} - -// List is a test implementation of snapshot.List -func (f *FakeSnapshotClient) List(ctx context.Context, in *snapshot.ListRequest, opts ...grpc.CallOption) (snapshot.Snapshot_ListClient, error) { - return nil, nil -} - -// Usage is a test implementation of snapshot.Usage -func (f *FakeSnapshotClient) Usage(ctx context.Context, in *snapshot.UsageRequest, opts ...grpc.CallOption) (*snapshot.UsageResponse, error) { - return nil, nil -}