integration: Enable some tests for Windows (part 2)
Some of the tests that are currently running only on Linux can be made to run on Windows with a few changes. Signed-off-by: Claudiu Belu <cbelu@cloudbasesolutions.com>
This commit is contained in:
parent
d97b40c300
commit
830b3c26ec
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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")
|
||||
|
@ -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")
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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),
|
||||
)
|
Loading…
Reference in New Issue
Block a user