Merge pull request #6121 from claudiubelu/integration/enables-windows-tests-part-2

integration: Enable some tests for Windows (part 2)
This commit is contained in:
Phil Estes 2021-10-29 11:25:49 -04:00 committed by GitHub
commit d0bdb0b65e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 440 additions and 402 deletions

View File

@ -238,76 +238,6 @@ func TestShimInCgroup(t *testing.T) {
<-statusC
}
func TestDaemonRestart(t *testing.T) {
client, err := newClient(t, address)
if err != nil {
t.Fatal(err)
}
defer client.Close()
var (
image Image
ctx, cancel = testContext(t)
id = t.Name()
)
defer cancel()
image, err = client.GetImage(ctx, testImage)
if err != nil {
t.Fatal(err)
}
container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withProcessArgs("sleep", "30")))
if err != nil {
t.Fatal(err)
}
defer container.Delete(ctx, WithSnapshotCleanup)
task, err := container.NewTask(ctx, empty())
if err != nil {
t.Fatal(err)
}
defer task.Delete(ctx)
statusC, err := task.Wait(ctx)
if err != nil {
t.Fatal(err)
}
if err := task.Start(ctx); err != nil {
t.Fatal(err)
}
var exitStatus ExitStatus
if err := ctrd.Restart(func() {
exitStatus = <-statusC
}); err != nil {
t.Fatal(err)
}
if exitStatus.Error() == nil {
t.Errorf(`first task.Wait() should have failed with "transport is closing"`)
}
waitCtx, waitCancel := context.WithTimeout(ctx, 2*time.Second)
serving, err := client.IsServing(waitCtx)
waitCancel()
if !serving {
t.Fatalf("containerd did not start within 2s: %v", err)
}
statusC, err = task.Wait(ctx)
if err != nil {
t.Fatal(err)
}
if err := task.Kill(ctx, syscall.SIGKILL); err != nil {
t.Fatal(err)
}
<-statusC
}
func TestShimDoesNotLeakPipes(t *testing.T) {
containerdPid := ctrd.cmd.Process.Pid
initialPipes, err := numPipes(containerdPid)
@ -690,57 +620,6 @@ func TestContainerAttach(t *testing.T) {
}
}
func newDirectIO(ctx context.Context, terminal bool) (*directIO, error) {
fifos, err := cio.NewFIFOSetInDir("", "", terminal)
if err != nil {
return nil, err
}
dio, err := cio.NewDirectIO(ctx, fifos)
if err != nil {
return nil, err
}
return &directIO{DirectIO: *dio}, nil
}
type directIO struct {
cio.DirectIO
}
// ioCreate returns IO available for use with task creation
func (f *directIO) IOCreate(id string) (cio.IO, error) {
return f, nil
}
// ioAttach returns IO available for use with task attachment
func (f *directIO) IOAttach(set *cio.FIFOSet) (cio.IO, error) {
return f, nil
}
func (f *directIO) Cancel() {
// nothing to cancel as all operations are handled externally
}
// Close closes all open fds
func (f *directIO) Close() error {
err := f.Stdin.Close()
if f.Stdout != nil {
if err2 := f.Stdout.Close(); err == nil {
err = err2
}
}
if f.Stderr != nil {
if err2 := f.Stderr.Close(); err == nil {
err = err2
}
}
return err
}
// Delete removes the underlying directory containing fifos
func (f *directIO) Delete() error {
return f.DirectIO.Close()
}
func TestContainerUsername(t *testing.T) {
t.Parallel()
@ -1372,85 +1251,10 @@ func TestContainerRuntimeOptionsv2(t *testing.T) {
}
}
func initContainerAndCheckChildrenDieOnKill(t *testing.T, opts ...oci.SpecOpts) {
client, err := newClient(t, address)
if err != nil {
t.Fatal(err)
}
defer client.Close()
var (
image Image
ctx, cancel = testContext(t)
id = t.Name()
)
defer cancel()
image, err = client.GetImage(ctx, testImage)
if err != nil {
t.Fatal(err)
}
opts = append(opts, oci.WithImageConfig(image))
opts = append(opts, withProcessArgs("sh", "-c", "sleep 42; echo hi"))
container, err := client.NewContainer(ctx, id,
WithNewSnapshot(id, image),
WithNewSpec(opts...),
)
if err != nil {
t.Fatal(err)
}
defer container.Delete(ctx, WithSnapshotCleanup)
stdout := bytes.NewBuffer(nil)
task, err := container.NewTask(ctx, cio.NewCreator(withByteBuffers(stdout)))
if err != nil {
t.Fatal(err)
}
defer task.Delete(ctx)
statusC, err := task.Wait(ctx)
if err != nil {
t.Fatal(err)
}
if err := task.Start(ctx); err != nil {
t.Fatal(err)
}
if err := task.Kill(ctx, syscall.SIGKILL); err != nil {
t.Error(err)
}
// Give the shim time to reap the init process and kill the orphans
select {
case <-statusC:
case <-time.After(100 * time.Millisecond):
}
b, err := exec.Command("ps", "ax").CombinedOutput()
if err != nil {
t.Fatal(err)
}
if strings.Contains(string(b), "sleep 42") {
t.Fatalf("killing init didn't kill all its children:\n%v", string(b))
}
if _, err := task.Delete(ctx, WithProcessKill); err != nil {
t.Error(err)
}
}
func TestContainerKillInitPidHost(t *testing.T) {
initContainerAndCheckChildrenDieOnKill(t, oci.WithHostNamespace(specs.PIDNamespace))
}
func TestContainerKillInitKillsChildWhenNotHostPid(t *testing.T) {
initContainerAndCheckChildrenDieOnKill(t)
}
func TestUserNamespaces(t *testing.T) {
t.Parallel()
t.Run("WritableRootFS", func(t *testing.T) { testUserNamespaces(t, false) })
@ -1570,49 +1374,6 @@ func testUserNamespaces(t *testing.T, readonlyRootFS bool) {
}
}
func TestTaskResize(t *testing.T) {
t.Parallel()
client, err := newClient(t, address)
if err != nil {
t.Fatal(err)
}
defer client.Close()
var (
image Image
ctx, cancel = testContext(t)
id = t.Name()
)
defer cancel()
image, err = client.GetImage(ctx, testImage)
if err != nil {
t.Fatal(err)
}
container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withExitStatus(7)))
if err != nil {
t.Fatal(err)
}
defer container.Delete(ctx, WithSnapshotCleanup)
task, err := container.NewTask(ctx, empty())
if err != nil {
t.Fatal(err)
}
defer task.Delete(ctx)
statusC, err := task.Wait(ctx)
if err != nil {
t.Fatal(err)
}
if err := task.Resize(ctx, 32, 32); err != nil {
t.Fatal(err)
}
task.Kill(ctx, syscall.SIGKILL)
<-statusC
}
func TestUIDNoGID(t *testing.T) {
t.Parallel()
@ -1868,73 +1629,3 @@ func TestShimOOMScore(t *testing.T) {
<-statusC
}
func TestTaskSpec(t *testing.T) {
t.Parallel()
client, err := newClient(t, address)
if err != nil {
t.Fatal(err)
}
defer client.Close()
var (
image Image
ctx, cancel = testContext(t)
id = t.Name()
)
defer cancel()
image, err = client.GetImage(ctx, testImage)
if err != nil {
t.Fatal(err)
}
container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), longCommand))
if err != nil {
t.Fatal(err)
}
defer container.Delete(ctx, WithSnapshotCleanup)
task, err := container.NewTask(ctx, empty())
if err != nil {
t.Fatal(err)
}
defer task.Delete(ctx)
statusC, err := task.Wait(ctx)
if err != nil {
t.Fatal(err)
}
spec, err := task.Spec(ctx)
if err != nil {
t.Fatal(err)
}
if spec == nil {
t.Fatal("spec from task is nil")
}
direct, err := newDirectIO(ctx, false)
if err != nil {
t.Fatal(err)
}
defer direct.Delete()
lt, err := container.Task(ctx, direct.IOAttach)
if err != nil {
t.Fatal(err)
}
spec, err = lt.Spec(ctx)
if err != nil {
t.Fatal(err)
}
if spec == nil {
t.Fatal("spec from loaded task is nil")
}
if err := task.Kill(ctx, syscall.SIGKILL); err != nil {
t.Fatal(err)
}
<-statusC
}

View File

@ -54,7 +54,7 @@ func empty() cio.Creator {
// TODO (@mlaventure) windows searches for pipes
// when none are provided
if runtime.GOOS == "windows" {
return cio.NewCreator(cio.WithStdio)
return cio.NewCreator(cio.WithStdio, cio.WithTerminal)
}
return cio.NullIO
}
@ -1941,6 +1941,238 @@ func TestRegressionIssue4769(t *testing.T) {
}
}
func TestDaemonRestart(t *testing.T) {
client, err := newClient(t, address)
if err != nil {
t.Fatal(err)
}
defer client.Close()
var (
image Image
ctx, cancel = testContext(t)
id = t.Name()
)
defer cancel()
image, err = client.GetImage(ctx, testImage)
if err != nil {
t.Fatal(err)
}
container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), longCommand))
if err != nil {
t.Fatal(err)
}
defer container.Delete(ctx, WithSnapshotCleanup)
task, err := container.NewTask(ctx, empty())
if err != nil {
t.Fatal(err)
}
defer task.Delete(ctx)
statusC, err := task.Wait(ctx)
if err != nil {
t.Fatal(err)
}
if err := task.Start(ctx); err != nil {
t.Fatal(err)
}
var exitStatus ExitStatus
if err := ctrd.Restart(func() {
exitStatus = <-statusC
}); err != nil {
t.Fatal(err)
}
if exitStatus.Error() == nil {
t.Errorf(`first task.Wait() should have failed with "transport is closing"`)
}
waitCtx, waitCancel := context.WithTimeout(ctx, 2*time.Second)
serving, err := client.IsServing(waitCtx)
waitCancel()
if !serving {
t.Fatalf("containerd did not start within 2s: %v", err)
}
statusC, err = task.Wait(ctx)
if err != nil {
t.Fatal(err)
}
if err := task.Kill(ctx, syscall.SIGKILL); err != nil {
t.Fatal(err)
}
<-statusC
}
type directIO struct {
cio.DirectIO
}
// ioCreate returns IO available for use with task creation
func (f *directIO) IOCreate(id string) (cio.IO, error) {
return f, nil
}
// ioAttach returns IO available for use with task attachment
func (f *directIO) IOAttach(set *cio.FIFOSet) (cio.IO, error) {
return f, nil
}
func (f *directIO) Cancel() {
// nothing to cancel as all operations are handled externally
}
// Close closes all open fds
func (f *directIO) Close() error {
err := f.Stdin.Close()
if f.Stdout != nil {
if err2 := f.Stdout.Close(); err == nil {
err = err2
}
}
if f.Stderr != nil {
if err2 := f.Stderr.Close(); err == nil {
err = err2
}
}
return err
}
// Delete removes the underlying directory containing fifos
func (f *directIO) Delete() error {
return f.DirectIO.Close()
}
func initContainerAndCheckChildrenDieOnKill(t *testing.T, opts ...oci.SpecOpts) {
client, err := newClient(t, address)
if err != nil {
t.Fatal(err)
}
defer client.Close()
var (
image Image
ctx, cancel = testContext(t)
id = t.Name()
)
defer cancel()
image, err = client.GetImage(ctx, testImage)
if err != nil {
t.Fatal(err)
}
opts = append(opts, oci.WithImageConfig(image))
opts = append(opts, longCommand)
container, err := client.NewContainer(ctx, id,
WithNewSnapshot(id, image),
WithNewSpec(opts...),
)
if err != nil {
t.Fatal(err)
}
defer container.Delete(ctx, WithSnapshotCleanup)
stdout := bytes.NewBuffer(nil)
task, err := container.NewTask(ctx, cio.NewCreator(withByteBuffers(stdout)))
if err != nil {
t.Fatal(err)
}
defer task.Delete(ctx)
statusC, err := task.Wait(ctx)
if err != nil {
t.Fatal(err)
}
if err := task.Start(ctx); err != nil {
t.Fatal(err)
}
if err := task.Kill(ctx, syscall.SIGKILL); err != nil {
t.Error(err)
}
// Give the shim time to reap the init process and kill the orphans
select {
case <-statusC:
case <-time.After(100 * time.Millisecond):
}
command := []string{"ps", "ax"}
if runtime.GOOS == "windows" {
command = []string{"tasklist"}
}
b, err := exec.Command(command[0], command[1:]...).CombinedOutput()
if err != nil {
t.Fatal(err)
}
// The container is using longCommand, which contains sleep 1 on Linux, and ping -t localhost on Windows.
if strings.Contains(string(b), "sleep 1") || strings.Contains(string(b), "ping -t localhost") {
t.Fatalf("killing init didn't kill all its children:\n%v", string(b))
}
if _, err := task.Delete(ctx, WithProcessKill); err != nil {
t.Error(err)
}
}
func TestContainerKillInitKillsChildWhenNotHostPid(t *testing.T) {
initContainerAndCheckChildrenDieOnKill(t)
}
func TestTaskResize(t *testing.T) {
t.Parallel()
client, err := newClient(t, address)
if err != nil {
t.Fatal(err)
}
defer client.Close()
var (
image Image
ctx, cancel = testContext(t)
id = t.Name()
)
defer cancel()
image, err = client.GetImage(ctx, testImage)
if err != nil {
t.Fatal(err)
}
container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withExitStatus(7)))
if err != nil {
t.Fatal(err)
}
defer container.Delete(ctx, WithSnapshotCleanup)
task, err := container.NewTask(ctx, empty())
if err != nil {
t.Fatal(err)
}
defer task.Delete(ctx)
statusC, err := task.Wait(ctx)
if err != nil {
t.Fatal(err)
}
if err := task.Resize(ctx, 32, 32); err != nil {
t.Fatal(err)
}
task.Kill(ctx, syscall.SIGKILL)
<-statusC
}
func TestContainerImage(t *testing.T) {
t.Parallel()
@ -2050,3 +2282,73 @@ func TestContainerNoSTDIN(t *testing.T) {
t.Errorf("expected status 0 from wait but received %d", code)
}
}
func TestTaskSpec(t *testing.T) {
t.Parallel()
client, err := newClient(t, address)
if err != nil {
t.Fatal(err)
}
defer client.Close()
var (
image Image
ctx, cancel = testContext(t)
id = t.Name()
)
defer cancel()
image, err = client.GetImage(ctx, testImage)
if err != nil {
t.Fatal(err)
}
container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), longCommand))
if err != nil {
t.Fatal(err)
}
defer container.Delete(ctx, WithSnapshotCleanup)
task, err := container.NewTask(ctx, empty())
if err != nil {
t.Fatal(err)
}
defer task.Delete(ctx)
statusC, err := task.Wait(ctx)
if err != nil {
t.Fatal(err)
}
spec, err := task.Spec(ctx)
if err != nil {
t.Fatal(err)
}
if spec == nil {
t.Fatal("spec from task is nil")
}
direct, err := newDirectIO(ctx, false)
if err != nil {
t.Fatal(err)
}
defer direct.Delete()
lt, err := container.Task(ctx, direct.IOAttach)
if err != nil {
t.Fatal(err)
}
spec, err = lt.Spec(ctx)
if err != nil {
t.Fatal(err)
}
if spec == nil {
t.Fatal("spec from loaded task is nil")
}
if err := task.Kill(ctx, syscall.SIGKILL); err != nil {
t.Fatal(err)
}
<-statusC
}

View File

@ -18,8 +18,6 @@ package client
import (
"bufio"
"bytes"
"context"
"fmt"
"os"
"path/filepath"
@ -31,91 +29,10 @@ import (
"github.com/containerd/cgroups"
. "github.com/containerd/containerd"
"github.com/containerd/containerd/oci"
"github.com/containerd/containerd/pkg/testutil"
"github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/runtime/v2/runc/options"
srvconfig "github.com/containerd/containerd/services/server/config"
exec "golang.org/x/sys/execabs"
)
// the following nolint is for shutting up gometalinter on non-linux.
// nolint: unused
func newDaemonWithConfig(t *testing.T, configTOML string) (*Client, *daemon, func()) {
if testing.Short() {
t.Skip()
}
testutil.RequiresRoot(t)
var (
ctrd = daemon{}
configTOMLDecoded srvconfig.Config
buf = bytes.NewBuffer(nil)
)
tempDir, err := os.MkdirTemp("", "containerd-test-new-daemon-with-config")
if err != nil {
t.Fatal(err)
}
defer func() {
if err != nil {
os.RemoveAll(tempDir)
}
}()
configTOMLFile := filepath.Join(tempDir, "config.toml")
if err = os.WriteFile(configTOMLFile, []byte(configTOML), 0600); err != nil {
t.Fatal(err)
}
if err = srvconfig.LoadConfig(configTOMLFile, &configTOMLDecoded); err != nil {
t.Fatal(err)
}
address := configTOMLDecoded.GRPC.Address
if address == "" {
address = filepath.Join(tempDir, "containerd.sock")
}
args := []string{"-c", configTOMLFile}
if configTOMLDecoded.Root == "" {
args = append(args, "--root", filepath.Join(tempDir, "root"))
}
if configTOMLDecoded.State == "" {
args = append(args, "--state", filepath.Join(tempDir, "state"))
}
if err = ctrd.start("containerd", address, args, buf, buf); err != nil {
t.Fatalf("%v: %s", err, buf.String())
}
waitCtx, waitCancel := context.WithTimeout(context.TODO(), 2*time.Second)
client, err := ctrd.waitForStart(waitCtx)
waitCancel()
if err != nil {
ctrd.Kill()
ctrd.Wait()
t.Fatalf("%v: %s", err, buf.String())
}
cleanup := func() {
if err := client.Close(); err != nil {
t.Fatalf("failed to close client: %v", err)
}
if err := ctrd.Stop(); err != nil {
if err := ctrd.Kill(); err != nil {
t.Fatalf("failed to signal containerd: %v", err)
}
}
if err := ctrd.Wait(); err != nil {
if _, ok := err.(*exec.ExitError); !ok {
t.Fatalf("failed to wait for: %v", err)
}
}
if err := os.RemoveAll(tempDir); err != nil {
t.Fatalf("failed to remove %s: %v", tempDir, err)
}
// cleaning config-specific resources is up to the caller
}
return client, &ctrd, cleanup
}
// TestDaemonRuntimeRoot ensures plugin.linux.runtime_root is not ignored
func TestDaemonRuntimeRoot(t *testing.T) {
runtimeRoot, err := os.MkdirTemp("", "containerd-test-runtime-root")

View File

@ -19,6 +19,7 @@ package client
import (
"context"
"io"
"runtime"
"sync"
"syscall"
@ -110,8 +111,12 @@ func (d *daemon) Restart(stopCb func()) error {
return errors.New("daemon is not running")
}
signal := syscall.SIGTERM
if runtime.GOOS == "windows" {
signal = syscall.SIGKILL
}
var err error
if err = d.cmd.Process.Signal(syscall.SIGTERM); err != nil {
if err = d.cmd.Process.Signal(signal); err != nil {
return errors.Wrap(err, "failed to signal daemon")
}

View File

@ -23,6 +23,7 @@ import (
"context"
"fmt"
"github.com/containerd/containerd/cio"
"github.com/containerd/containerd/containers"
"github.com/containerd/containerd/oci"
specs "github.com/opencontainers/runtime-spec/specs-go"
@ -56,3 +57,15 @@ func withExecExitStatus(s *specs.Process, es int) {
func withExecArgs(s *specs.Process, args ...string) {
s.Args = args
}
func newDirectIO(ctx context.Context, terminal bool) (*directIO, error) {
fifos, err := cio.NewFIFOSetInDir("", "", terminal)
if err != nil {
return nil, err
}
dio, err := cio.NewDirectIO(ctx, fifos)
if err != nil {
return nil, err
}
return &directIO{DirectIO: *dio}, nil
}

View File

@ -17,9 +17,12 @@
package client
import (
"bytes"
"context"
"io"
"strconv"
"github.com/containerd/containerd/cio"
"github.com/containerd/containerd/containers"
"github.com/containerd/containerd/oci"
specs "github.com/opencontainers/runtime-spec/specs-go"
@ -53,3 +56,21 @@ func withExecExitStatus(s *specs.Process, es int) {
func withExecArgs(s *specs.Process, args ...string) {
s.Args = append([]string{"cmd", "/c"}, args...)
}
type bytesBuffer struct {
*bytes.Buffer
}
// Close is a noop operation.
func (b bytesBuffer) Close() error {
return nil
}
func newDirectIO(ctx context.Context, terminal bool) (*directIO, error) {
readb := bytesBuffer{bytes.NewBuffer(nil)}
writeb := io.NopCloser(bytes.NewBuffer(nil))
errb := io.NopCloser(bytes.NewBuffer(nil))
dio := cio.NewDirectIO(readb, writeb, errb, terminal)
return &directIO{DirectIO: *dio}, nil
}

View File

@ -28,10 +28,6 @@ import (
)
func TestLeaseResources(t *testing.T) {
if runtime.GOOS == "windows" {
t.Skip()
}
ctx, cancel := testContext(t)
defer cancel()
@ -41,11 +37,15 @@ func TestLeaseResources(t *testing.T) {
}
defer client.Close()
snapshotterName := "native"
if runtime.GOOS == "windows" {
snapshotterName = "windows"
}
var (
ls = client.LeasesService()
cs = client.ContentStore()
imgSrv = client.ImageService()
sn = client.SnapshotService("native")
sn = client.SnapshotService(snapshotterName)
)
l, err := ls.Create(ctx, leases.WithRandomID())
@ -57,7 +57,7 @@ func TestLeaseResources(t *testing.T) {
// step 1: download image
imageName := "k8s.gcr.io/pause:3.6"
image, err := client.Pull(ctx, imageName, WithPullUnpack, WithPullSnapshotter("native"))
image, err := client.Pull(ctx, imageName, WithPullUnpack, WithPullSnapshotter(snapshotterName))
if err != nil {
t.Fatal(err)
}
@ -86,7 +86,7 @@ func TestLeaseResources(t *testing.T) {
// step 2: reference snapshotter with lease
r := leases.Resource{
ID: chainID.String(),
Type: "snapshots/native",
Type: "snapshots/" + snapshotterName,
}
if err := ls.AddResource(ctx, l, r); err != nil {

View File

@ -17,8 +17,12 @@
package client
import (
"bytes"
"context"
"fmt"
"os"
"path/filepath"
"runtime"
"syscall"
"testing"
"time"
@ -26,8 +30,93 @@ import (
. "github.com/containerd/containerd"
"github.com/containerd/containerd/containers"
"github.com/containerd/containerd/oci"
"github.com/containerd/containerd/pkg/testutil"
srvconfig "github.com/containerd/containerd/services/server/config"
exec "golang.org/x/sys/execabs"
)
// the following nolint is for shutting up gometalinter on non-linux.
// nolint: unused
func newDaemonWithConfig(t *testing.T, configTOML string) (*Client, *daemon, func()) {
if testing.Short() {
t.Skip()
}
testutil.RequiresRoot(t)
var (
ctrd = daemon{}
configTOMLDecoded srvconfig.Config
buf = bytes.NewBuffer(nil)
)
tempDir, err := os.MkdirTemp("", "containerd-test-new-daemon-with-config")
if err != nil {
t.Fatal(err)
}
defer func() {
if err != nil {
os.RemoveAll(tempDir)
}
}()
configTOMLFile := filepath.Join(tempDir, "config.toml")
if err = os.WriteFile(configTOMLFile, []byte(configTOML), 0600); err != nil {
t.Fatal(err)
}
if err = srvconfig.LoadConfig(configTOMLFile, &configTOMLDecoded); err != nil {
t.Fatal(err)
}
address := configTOMLDecoded.GRPC.Address
if address == "" {
if runtime.GOOS == "windows" {
address = fmt.Sprintf(`\\.\pipe\containerd-containerd-test-%s`, filepath.Base(tempDir))
} else {
address = filepath.Join(tempDir, "containerd.sock")
}
}
args := []string{"-c", configTOMLFile}
if configTOMLDecoded.Root == "" {
args = append(args, "--root", filepath.Join(tempDir, "root"))
}
if configTOMLDecoded.State == "" {
args = append(args, "--state", filepath.Join(tempDir, "state"))
}
if err = ctrd.start("containerd", address, args, buf, buf); err != nil {
t.Fatalf("%v: %s", err, buf.String())
}
waitCtx, waitCancel := context.WithTimeout(context.TODO(), 2*time.Second)
client, err := ctrd.waitForStart(waitCtx)
waitCancel()
if err != nil {
ctrd.Kill()
ctrd.Wait()
t.Fatalf("%v: %s", err, buf.String())
}
cleanup := func() {
if err := client.Close(); err != nil {
t.Fatalf("failed to close client: %v", err)
}
if err := ctrd.Stop(); err != nil {
if err := ctrd.Kill(); err != nil {
t.Fatalf("failed to signal containerd: %v", err)
}
}
if err := ctrd.Wait(); err != nil {
if _, ok := err.(*exec.ExitError); !ok {
t.Fatalf("failed to wait for: %v", err)
}
}
if err := os.RemoveAll(tempDir); err != nil {
t.Fatalf("failed to remove %s: %v", tempDir, err)
}
// cleaning config-specific resources is up to the caller
}
return client, &ctrd, cleanup
}
// TestRestartMonitor tests restarting containers
// with the restart monitor service plugin
func TestRestartMonitor(t *testing.T) {
@ -60,7 +149,7 @@ version = 2
WithNewSnapshot(id, image),
WithNewSpec(
oci.WithImageConfig(image),
withProcessArgs("sleep", "infinity"),
longCommand,
),
withRestartStatus(Running),
)