github.com/demonoid81/containerd@v1.3.4/container_linux_test.go (about)

     1  // +build linux
     2  
     3  /*
     4     Copyright The containerd Authors.
     5  
     6     Licensed under the Apache License, Version 2.0 (the "License");
     7     you may not use this file except in compliance with the License.
     8     You may obtain a copy of the License at
     9  
    10         http://www.apache.org/licenses/LICENSE-2.0
    11  
    12     Unless required by applicable law or agreed to in writing, software
    13     distributed under the License is distributed on an "AS IS" BASIS,
    14     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15     See the License for the specific language governing permissions and
    16     limitations under the License.
    17  */
    18  
    19  package containerd
    20  
    21  import (
    22  	"bytes"
    23  	"context"
    24  	"fmt"
    25  	"io"
    26  	"io/ioutil"
    27  	"os"
    28  	"os/exec"
    29  	"path/filepath"
    30  	"runtime"
    31  	"strings"
    32  	"sync"
    33  	"syscall"
    34  	"testing"
    35  	"time"
    36  
    37  	"github.com/containerd/cgroups"
    38  	"github.com/containerd/containerd/cio"
    39  	"github.com/containerd/containerd/containers"
    40  	"github.com/containerd/containerd/errdefs"
    41  	"github.com/containerd/containerd/oci"
    42  	"github.com/containerd/containerd/plugin"
    43  	"github.com/containerd/containerd/runtime/linux/runctypes"
    44  	"github.com/containerd/containerd/runtime/v2/runc/options"
    45  	"github.com/containerd/containerd/sys"
    46  	specs "github.com/opencontainers/runtime-spec/specs-go"
    47  	"github.com/pkg/errors"
    48  	"golang.org/x/sys/unix"
    49  )
    50  
    51  func TestTaskUpdate(t *testing.T) {
    52  	t.Parallel()
    53  
    54  	client, err := newClient(t, address)
    55  	if err != nil {
    56  		t.Fatal(err)
    57  	}
    58  	defer client.Close()
    59  
    60  	var (
    61  		ctx, cancel = testContext(t)
    62  		id          = t.Name()
    63  	)
    64  	defer cancel()
    65  
    66  	image, err := client.GetImage(ctx, testImage)
    67  	if err != nil {
    68  		t.Fatal(err)
    69  	}
    70  	limit := int64(32 * 1024 * 1024)
    71  	memory := func(_ context.Context, _ oci.Client, _ *containers.Container, s *specs.Spec) error {
    72  		s.Linux.Resources.Memory = &specs.LinuxMemory{
    73  			Limit: &limit,
    74  		}
    75  		return nil
    76  	}
    77  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image),
    78  		WithNewSpec(oci.WithImageConfig(image), withProcessArgs("sleep", "30"), memory))
    79  	if err != nil {
    80  		t.Fatal(err)
    81  	}
    82  	defer container.Delete(ctx, WithSnapshotCleanup)
    83  
    84  	task, err := container.NewTask(ctx, empty())
    85  	if err != nil {
    86  		t.Fatal(err)
    87  	}
    88  	defer task.Delete(ctx)
    89  
    90  	statusC, err := task.Wait(ctx)
    91  	if err != nil {
    92  		t.Fatal(err)
    93  	}
    94  
    95  	// check that the task has a limit of 32mb
    96  	cgroup, err := cgroups.Load(cgroups.V1, cgroups.PidPath(int(task.Pid())))
    97  	if err != nil {
    98  		t.Fatal(err)
    99  	}
   100  	stat, err := cgroup.Stat(cgroups.IgnoreNotExist)
   101  	if err != nil {
   102  		t.Fatal(err)
   103  	}
   104  	if int64(stat.Memory.Usage.Limit) != limit {
   105  		t.Fatalf("expected memory limit to be set to %d but received %d", limit, stat.Memory.Usage.Limit)
   106  	}
   107  	limit = 64 * 1024 * 1024
   108  	if err := task.Update(ctx, WithResources(&specs.LinuxResources{
   109  		Memory: &specs.LinuxMemory{
   110  			Limit: &limit,
   111  		},
   112  	})); err != nil {
   113  		t.Error(err)
   114  	}
   115  	// check that the task has a limit of 64mb
   116  	if stat, err = cgroup.Stat(cgroups.IgnoreNotExist); err != nil {
   117  		t.Fatal(err)
   118  	}
   119  	if int64(stat.Memory.Usage.Limit) != limit {
   120  		t.Errorf("expected memory limit to be set to %d but received %d", limit, stat.Memory.Usage.Limit)
   121  	}
   122  	if err := task.Kill(ctx, unix.SIGKILL); err != nil {
   123  		t.Fatal(err)
   124  	}
   125  
   126  	<-statusC
   127  }
   128  
   129  func TestShimInCgroup(t *testing.T) {
   130  	t.Parallel()
   131  
   132  	client, err := newClient(t, address)
   133  	if err != nil {
   134  		t.Fatal(err)
   135  	}
   136  	defer client.Close()
   137  	var (
   138  		ctx, cancel = testContext(t)
   139  		id          = t.Name()
   140  	)
   141  	defer cancel()
   142  
   143  	image, err := client.GetImage(ctx, testImage)
   144  	if err != nil {
   145  		t.Fatal(err)
   146  	}
   147  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), oci.WithProcessArgs("sleep", "30")))
   148  	if err != nil {
   149  		t.Fatal(err)
   150  	}
   151  	defer container.Delete(ctx, WithSnapshotCleanup)
   152  	// create a cgroup for the shim to use
   153  	path := "/containerd/shim"
   154  	cg, err := cgroups.New(cgroups.V1, cgroups.StaticPath(path), &specs.LinuxResources{})
   155  	if err != nil {
   156  		t.Fatal(err)
   157  	}
   158  	defer cg.Delete()
   159  
   160  	task, err := container.NewTask(ctx, empty(), WithShimCgroup(path))
   161  	if err != nil {
   162  		t.Fatal(err)
   163  	}
   164  	defer task.Delete(ctx)
   165  
   166  	statusC, err := task.Wait(ctx)
   167  	if err != nil {
   168  		t.Fatal(err)
   169  	}
   170  
   171  	// check to see if the shim is inside the cgroup
   172  	processes, err := cg.Processes(cgroups.Devices, false)
   173  	if err != nil {
   174  		t.Fatal(err)
   175  	}
   176  	if len(processes) == 0 {
   177  		t.Errorf("created cgroup should have at least one process inside: %d", len(processes))
   178  	}
   179  	if err := task.Kill(ctx, unix.SIGKILL); err != nil {
   180  		t.Fatal(err)
   181  	}
   182  
   183  	<-statusC
   184  }
   185  
   186  func TestDaemonRestart(t *testing.T) {
   187  	client, err := newClient(t, address)
   188  	if err != nil {
   189  		t.Fatal(err)
   190  	}
   191  	defer client.Close()
   192  
   193  	var (
   194  		image       Image
   195  		ctx, cancel = testContext(t)
   196  		id          = t.Name()
   197  	)
   198  	defer cancel()
   199  
   200  	image, err = client.GetImage(ctx, testImage)
   201  	if err != nil {
   202  		t.Fatal(err)
   203  	}
   204  
   205  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withProcessArgs("sleep", "30")))
   206  	if err != nil {
   207  		t.Fatal(err)
   208  	}
   209  	defer container.Delete(ctx, WithSnapshotCleanup)
   210  
   211  	task, err := container.NewTask(ctx, empty())
   212  	if err != nil {
   213  		t.Fatal(err)
   214  	}
   215  	defer task.Delete(ctx)
   216  
   217  	statusC, err := task.Wait(ctx)
   218  	if err != nil {
   219  		t.Fatal(err)
   220  	}
   221  
   222  	if err := task.Start(ctx); err != nil {
   223  		t.Fatal(err)
   224  	}
   225  
   226  	var exitStatus ExitStatus
   227  	if err := ctrd.Restart(func() {
   228  		exitStatus = <-statusC
   229  	}); err != nil {
   230  		t.Fatal(err)
   231  	}
   232  
   233  	if exitStatus.Error() == nil {
   234  		t.Errorf(`first task.Wait() should have failed with "transport is closing"`)
   235  	}
   236  
   237  	waitCtx, waitCancel := context.WithTimeout(ctx, 2*time.Second)
   238  	serving, err := client.IsServing(waitCtx)
   239  	waitCancel()
   240  	if !serving {
   241  		t.Fatalf("containerd did not start within 2s: %v", err)
   242  	}
   243  
   244  	statusC, err = task.Wait(ctx)
   245  	if err != nil {
   246  		t.Fatal(err)
   247  	}
   248  
   249  	if err := task.Kill(ctx, syscall.SIGKILL); err != nil {
   250  		t.Fatal(err)
   251  	}
   252  
   253  	<-statusC
   254  }
   255  
   256  func TestShimDoesNotLeakPipes(t *testing.T) {
   257  	containerdPid := ctrd.cmd.Process.Pid
   258  	initialPipes, err := numPipes(containerdPid)
   259  	if err != nil {
   260  		t.Fatal(err)
   261  	}
   262  
   263  	client, err := newClient(t, address)
   264  	if err != nil {
   265  		t.Fatal(err)
   266  	}
   267  	defer client.Close()
   268  
   269  	var (
   270  		image       Image
   271  		ctx, cancel = testContext(t)
   272  		id          = t.Name()
   273  	)
   274  	defer cancel()
   275  
   276  	image, err = client.GetImage(ctx, testImage)
   277  	if err != nil {
   278  		t.Fatal(err)
   279  	}
   280  
   281  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withProcessArgs("sleep", "30")))
   282  	if err != nil {
   283  		t.Fatal(err)
   284  	}
   285  
   286  	task, err := container.NewTask(ctx, empty())
   287  	if err != nil {
   288  		t.Fatal(err)
   289  	}
   290  
   291  	exitChannel, err := task.Wait(ctx)
   292  	if err != nil {
   293  		t.Fatal(err)
   294  	}
   295  
   296  	if err := task.Start(ctx); err != nil {
   297  		t.Fatal(err)
   298  	}
   299  
   300  	if err := task.Kill(ctx, syscall.SIGKILL); err != nil {
   301  		t.Fatal(err)
   302  	}
   303  
   304  	<-exitChannel
   305  
   306  	if _, err := task.Delete(ctx); err != nil {
   307  		t.Fatal(err)
   308  	}
   309  
   310  	if err := container.Delete(ctx, WithSnapshotCleanup); err != nil {
   311  		t.Fatal(err)
   312  	}
   313  
   314  	currentPipes, err := numPipes(containerdPid)
   315  	if err != nil {
   316  		t.Fatal(err)
   317  	}
   318  
   319  	if initialPipes != currentPipes {
   320  		t.Errorf("Pipes have leaked after container has been deleted. Initially there were %d pipes, after container deletion there were %d pipes", initialPipes, currentPipes)
   321  	}
   322  }
   323  
   324  func numPipes(pid int) (int, error) {
   325  	cmd := exec.Command("sh", "-c", fmt.Sprintf("lsof -p %d | grep FIFO", pid))
   326  
   327  	var stdout bytes.Buffer
   328  	cmd.Stdout = &stdout
   329  	if err := cmd.Run(); err != nil {
   330  		return 0, err
   331  	}
   332  	return strings.Count(stdout.String(), "\n"), nil
   333  }
   334  
   335  func TestDaemonReconnectsToShimIOPipesOnRestart(t *testing.T) {
   336  	client, err := newClient(t, address)
   337  	if err != nil {
   338  		t.Fatal(err)
   339  	}
   340  	defer client.Close()
   341  
   342  	var (
   343  		image       Image
   344  		ctx, cancel = testContext(t)
   345  		id          = t.Name()
   346  	)
   347  	defer cancel()
   348  
   349  	image, err = client.GetImage(ctx, testImage)
   350  	if err != nil {
   351  		t.Fatal(err)
   352  	}
   353  
   354  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withProcessArgs("sleep", "30")))
   355  	if err != nil {
   356  		t.Fatal(err)
   357  	}
   358  	defer container.Delete(ctx, WithSnapshotCleanup)
   359  
   360  	task, err := container.NewTask(ctx, empty())
   361  	if err != nil {
   362  		t.Fatal(err)
   363  	}
   364  	defer task.Delete(ctx)
   365  
   366  	_, err = task.Wait(ctx)
   367  	if err != nil {
   368  		t.Fatal(err)
   369  	}
   370  
   371  	if err := task.Start(ctx); err != nil {
   372  		t.Fatal(err)
   373  	}
   374  
   375  	if err := ctrd.Restart(nil); err != nil {
   376  		t.Fatal(err)
   377  	}
   378  
   379  	waitCtx, waitCancel := context.WithTimeout(ctx, 2*time.Second)
   380  	serving, err := client.IsServing(waitCtx)
   381  	waitCancel()
   382  	if !serving {
   383  		t.Fatalf("containerd did not start within 2s: %v", err)
   384  	}
   385  
   386  	// After we restared containerd we write some messages to the log pipes, simulating shim writing stuff there.
   387  	// Then we make sure that these messages are available on the containerd log thus proving that the server reconnected to the log pipes
   388  	runtimeVersion := getRuntimeVersion()
   389  	logDirPath := getLogDirPath(runtimeVersion, id)
   390  
   391  	switch runtimeVersion {
   392  	case "v1":
   393  		writeToFile(t, filepath.Join(logDirPath, "shim.stdout.log"), fmt.Sprintf("%s writing to stdout\n", id))
   394  		writeToFile(t, filepath.Join(logDirPath, "shim.stderr.log"), fmt.Sprintf("%s writing to stderr\n", id))
   395  	case "v2":
   396  		writeToFile(t, filepath.Join(logDirPath, "log"), fmt.Sprintf("%s writing to log\n", id))
   397  	}
   398  
   399  	statusC, err := task.Wait(ctx)
   400  	if err != nil {
   401  		t.Fatal(err)
   402  	}
   403  
   404  	if err := task.Kill(ctx, syscall.SIGKILL); err != nil {
   405  		t.Fatal(err)
   406  	}
   407  
   408  	<-statusC
   409  
   410  	stdioContents, err := ioutil.ReadFile(ctrdStdioFilePath)
   411  	if err != nil {
   412  		t.Fatal(err)
   413  	}
   414  
   415  	switch runtimeVersion {
   416  	case "v1":
   417  		if !strings.Contains(string(stdioContents), fmt.Sprintf("%s writing to stdout", id)) {
   418  			t.Fatal("containerd did not connect to the shim stdout pipe")
   419  		}
   420  		if !strings.Contains(string(stdioContents), fmt.Sprintf("%s writing to stderr", id)) {
   421  			t.Fatal("containerd did not connect to the shim stderr pipe")
   422  		}
   423  	case "v2":
   424  		if !strings.Contains(string(stdioContents), fmt.Sprintf("%s writing to log", id)) {
   425  			t.Fatal("containerd did not connect to the shim log pipe")
   426  		}
   427  	}
   428  }
   429  
   430  func writeToFile(t *testing.T, filePath, message string) {
   431  	writer, err := os.OpenFile(filePath, os.O_WRONLY, 0600)
   432  	if err != nil {
   433  		t.Fatal(err)
   434  	}
   435  	if _, err := writer.WriteString(message); err != nil {
   436  		t.Fatal(err)
   437  	}
   438  	if err := writer.Close(); err != nil {
   439  		t.Fatal(err)
   440  	}
   441  }
   442  
   443  func getLogDirPath(runtimeVersion, id string) string {
   444  	switch runtimeVersion {
   445  	case "v1":
   446  		return filepath.Join(defaultRoot, plugin.RuntimeLinuxV1, testNamespace, id)
   447  	case "v2":
   448  		return filepath.Join(defaultState, "io.containerd.runtime.v2.task", testNamespace, id)
   449  	default:
   450  		panic(fmt.Errorf("Unsupported runtime version %s", runtimeVersion))
   451  	}
   452  }
   453  
   454  func getRuntimeVersion() string {
   455  	switch rt := os.Getenv("TEST_RUNTIME"); rt {
   456  	case plugin.RuntimeRuncV1, plugin.RuntimeRuncV2:
   457  		return "v2"
   458  	default:
   459  		return "v1"
   460  	}
   461  }
   462  
   463  func TestContainerPTY(t *testing.T) {
   464  	t.Parallel()
   465  
   466  	client, err := newClient(t, address)
   467  	if err != nil {
   468  		t.Fatal(err)
   469  	}
   470  	defer client.Close()
   471  
   472  	var (
   473  		image       Image
   474  		ctx, cancel = testContext(t)
   475  		id          = t.Name()
   476  	)
   477  	defer cancel()
   478  
   479  	image, err = client.GetImage(ctx, testImage)
   480  	if err != nil {
   481  		t.Fatal(err)
   482  	}
   483  
   484  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), oci.WithTTY, withProcessArgs("echo", "hello")))
   485  	if err != nil {
   486  		t.Fatal(err)
   487  	}
   488  	defer container.Delete(ctx, WithSnapshotCleanup)
   489  
   490  	direct, err := newDirectIO(ctx, true)
   491  	if err != nil {
   492  		t.Fatal(err)
   493  	}
   494  	defer direct.Delete()
   495  	var (
   496  		wg  sync.WaitGroup
   497  		buf = bytes.NewBuffer(nil)
   498  	)
   499  	wg.Add(1)
   500  	go func() {
   501  		defer wg.Done()
   502  		io.Copy(buf, direct.Stdout)
   503  	}()
   504  
   505  	task, err := container.NewTask(ctx, direct.IOCreate)
   506  	if err != nil {
   507  		t.Fatal(err)
   508  	}
   509  	defer task.Delete(ctx)
   510  
   511  	status, err := task.Wait(ctx)
   512  	if err != nil {
   513  		t.Error(err)
   514  	}
   515  
   516  	if err := task.Start(ctx); err != nil {
   517  		t.Fatal(err)
   518  	}
   519  
   520  	<-status
   521  	wg.Wait()
   522  
   523  	if err := direct.Close(); err != nil {
   524  		t.Error(err)
   525  	}
   526  
   527  	out := buf.String()
   528  	if !strings.ContainsAny(fmt.Sprintf("%#q", out), `\x00`) {
   529  		t.Fatal(`expected \x00 in output`)
   530  	}
   531  }
   532  
   533  func TestContainerAttach(t *testing.T) {
   534  	t.Parallel()
   535  
   536  	if runtime.GOOS == "windows" {
   537  		// On windows, closing the write side of the pipe closes the read
   538  		// side, sending an EOF to it and preventing reopening it.
   539  		// Hence this test will always fails on windows
   540  		t.Skip("invalid logic on windows")
   541  	}
   542  
   543  	client, err := newClient(t, address)
   544  	if err != nil {
   545  		t.Fatal(err)
   546  	}
   547  	defer client.Close()
   548  
   549  	var (
   550  		image       Image
   551  		ctx, cancel = testContext(t)
   552  		id          = t.Name()
   553  	)
   554  	defer cancel()
   555  
   556  	image, err = client.GetImage(ctx, testImage)
   557  	if err != nil {
   558  		t.Fatal(err)
   559  	}
   560  
   561  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withCat()))
   562  	if err != nil {
   563  		t.Fatal(err)
   564  	}
   565  	defer container.Delete(ctx, WithSnapshotCleanup)
   566  
   567  	expected := "hello" + newLine
   568  
   569  	direct, err := newDirectIO(ctx, false)
   570  	if err != nil {
   571  		t.Fatal(err)
   572  	}
   573  	defer direct.Delete()
   574  	var (
   575  		wg  sync.WaitGroup
   576  		buf = bytes.NewBuffer(nil)
   577  	)
   578  	wg.Add(1)
   579  	go func() {
   580  		defer wg.Done()
   581  		io.Copy(buf, direct.Stdout)
   582  	}()
   583  
   584  	task, err := container.NewTask(ctx, direct.IOCreate)
   585  	if err != nil {
   586  		t.Fatal(err)
   587  	}
   588  	defer task.Delete(ctx)
   589  
   590  	status, err := task.Wait(ctx)
   591  	if err != nil {
   592  		t.Error(err)
   593  	}
   594  
   595  	if err := task.Start(ctx); err != nil {
   596  		t.Fatal(err)
   597  	}
   598  
   599  	if _, err := fmt.Fprint(direct.Stdin, expected); err != nil {
   600  		t.Error(err)
   601  	}
   602  
   603  	// load the container and re-load the task
   604  	if container, err = client.LoadContainer(ctx, id); err != nil {
   605  		t.Fatal(err)
   606  	}
   607  
   608  	if task, err = container.Task(ctx, direct.IOAttach); err != nil {
   609  		t.Fatal(err)
   610  	}
   611  
   612  	if _, err := fmt.Fprint(direct.Stdin, expected); err != nil {
   613  		t.Error(err)
   614  	}
   615  
   616  	direct.Stdin.Close()
   617  
   618  	if err := task.CloseIO(ctx, WithStdinCloser); err != nil {
   619  		t.Error(err)
   620  	}
   621  
   622  	<-status
   623  
   624  	wg.Wait()
   625  	if _, err := task.Delete(ctx); err != nil {
   626  		t.Error(err)
   627  	}
   628  
   629  	output := buf.String()
   630  
   631  	// we wrote the same thing after attach
   632  	expected = expected + expected
   633  	if output != expected {
   634  		t.Errorf("expected output %q but received %q", expected, output)
   635  	}
   636  }
   637  
   638  func newDirectIO(ctx context.Context, terminal bool) (*directIO, error) {
   639  	fifos, err := cio.NewFIFOSetInDir("", "", terminal)
   640  	if err != nil {
   641  		return nil, err
   642  	}
   643  	dio, err := cio.NewDirectIO(ctx, fifos)
   644  	if err != nil {
   645  		return nil, err
   646  	}
   647  	return &directIO{DirectIO: *dio}, nil
   648  }
   649  
   650  type directIO struct {
   651  	cio.DirectIO
   652  }
   653  
   654  // ioCreate returns IO available for use with task creation
   655  func (f *directIO) IOCreate(id string) (cio.IO, error) {
   656  	return f, nil
   657  }
   658  
   659  // ioAttach returns IO available for use with task attachment
   660  func (f *directIO) IOAttach(set *cio.FIFOSet) (cio.IO, error) {
   661  	return f, nil
   662  }
   663  
   664  func (f *directIO) Cancel() {
   665  	// nothing to cancel as all operations are handled externally
   666  }
   667  
   668  // Close closes all open fds
   669  func (f *directIO) Close() error {
   670  	err := f.Stdin.Close()
   671  	if err2 := f.Stdout.Close(); err == nil {
   672  		err = err2
   673  	}
   674  	if err2 := f.Stderr.Close(); err == nil {
   675  		err = err2
   676  	}
   677  	return err
   678  }
   679  
   680  // Delete removes the underlying directory containing fifos
   681  func (f *directIO) Delete() error {
   682  	return f.DirectIO.Close()
   683  }
   684  
   685  func TestContainerUsername(t *testing.T) {
   686  	t.Parallel()
   687  
   688  	client, err := newClient(t, address)
   689  	if err != nil {
   690  		t.Fatal(err)
   691  	}
   692  	defer client.Close()
   693  
   694  	var (
   695  		image       Image
   696  		ctx, cancel = testContext(t)
   697  		id          = t.Name()
   698  	)
   699  	defer cancel()
   700  
   701  	image, err = client.GetImage(ctx, testImage)
   702  	if err != nil {
   703  		t.Fatal(err)
   704  	}
   705  	direct, err := newDirectIO(ctx, false)
   706  	if err != nil {
   707  		t.Fatal(err)
   708  	}
   709  	defer direct.Delete()
   710  	var (
   711  		wg  sync.WaitGroup
   712  		buf = bytes.NewBuffer(nil)
   713  	)
   714  	wg.Add(1)
   715  	go func() {
   716  		defer wg.Done()
   717  		io.Copy(buf, direct.Stdout)
   718  	}()
   719  
   720  	// squid user in the alpine image has a uid of 31
   721  	container, err := client.NewContainer(ctx, id,
   722  		WithNewSnapshot(id, image),
   723  		WithNewSpec(oci.WithImageConfig(image), oci.WithUsername("squid"), oci.WithProcessArgs("id", "-u")),
   724  	)
   725  	if err != nil {
   726  		t.Fatal(err)
   727  	}
   728  	defer container.Delete(ctx, WithSnapshotCleanup)
   729  
   730  	task, err := container.NewTask(ctx, direct.IOCreate)
   731  	if err != nil {
   732  		t.Fatal(err)
   733  	}
   734  	defer task.Delete(ctx)
   735  
   736  	statusC, err := task.Wait(ctx)
   737  	if err != nil {
   738  		t.Fatal(err)
   739  	}
   740  
   741  	if err := task.Start(ctx); err != nil {
   742  		t.Fatal(err)
   743  	}
   744  	<-statusC
   745  
   746  	wg.Wait()
   747  
   748  	output := strings.TrimSuffix(buf.String(), "\n")
   749  	if output != "31" {
   750  		t.Errorf("expected squid uid to be 31 but received %q", output)
   751  	}
   752  }
   753  
   754  func TestContainerUser(t *testing.T) {
   755  	t.Parallel()
   756  	t.Run("UserNameAndGroupName", func(t *testing.T) { testContainerUser(t, "squid:squid", "31:31") })
   757  	t.Run("UserIDAndGroupName", func(t *testing.T) { testContainerUser(t, "1001:squid", "1001:31") })
   758  	t.Run("UserNameAndGroupID", func(t *testing.T) { testContainerUser(t, "squid:1002", "31:1002") })
   759  	t.Run("UserIDAndGroupID", func(t *testing.T) { testContainerUser(t, "1001:1002", "1001:1002") })
   760  }
   761  
   762  func testContainerUser(t *testing.T, userstr, expectedOutput string) {
   763  	client, err := newClient(t, address)
   764  	if err != nil {
   765  		t.Fatal(err)
   766  	}
   767  	defer client.Close()
   768  
   769  	var (
   770  		image       Image
   771  		ctx, cancel = testContext(t)
   772  		id          = strings.Replace(t.Name(), "/", "_", -1)
   773  	)
   774  	defer cancel()
   775  
   776  	image, err = client.GetImage(ctx, testImage)
   777  	if err != nil {
   778  		t.Fatal(err)
   779  	}
   780  	direct, err := newDirectIO(ctx, false)
   781  	if err != nil {
   782  		t.Fatal(err)
   783  	}
   784  	defer direct.Delete()
   785  	var (
   786  		wg  sync.WaitGroup
   787  		buf = bytes.NewBuffer(nil)
   788  	)
   789  	wg.Add(1)
   790  	go func() {
   791  		defer wg.Done()
   792  		io.Copy(buf, direct.Stdout)
   793  	}()
   794  
   795  	container, err := client.NewContainer(ctx, id,
   796  		WithNewSnapshot(id, image),
   797  		WithNewSpec(oci.WithImageConfig(image), oci.WithUser(userstr), oci.WithProcessArgs("sh", "-c", "echo $(id -u):$(id -g)")),
   798  	)
   799  	if err != nil {
   800  		t.Fatal(err)
   801  	}
   802  	defer container.Delete(ctx, WithSnapshotCleanup)
   803  
   804  	task, err := container.NewTask(ctx, direct.IOCreate)
   805  	if err != nil {
   806  		t.Fatal(err)
   807  	}
   808  	defer task.Delete(ctx)
   809  
   810  	statusC, err := task.Wait(ctx)
   811  	if err != nil {
   812  		t.Fatal(err)
   813  	}
   814  
   815  	if err := task.Start(ctx); err != nil {
   816  		t.Fatal(err)
   817  	}
   818  	<-statusC
   819  
   820  	wg.Wait()
   821  
   822  	output := strings.TrimSuffix(buf.String(), "\n")
   823  	if output != expectedOutput {
   824  		t.Errorf("expected uid:gid to be %q, but received %q", expectedOutput, output)
   825  	}
   826  }
   827  
   828  func TestContainerAttachProcess(t *testing.T) {
   829  	t.Parallel()
   830  
   831  	if runtime.GOOS == "windows" {
   832  		// On windows, closing the write side of the pipe closes the read
   833  		// side, sending an EOF to it and preventing reopening it.
   834  		// Hence this test will always fails on windows
   835  		t.Skip("invalid logic on windows")
   836  	}
   837  
   838  	client, err := newClient(t, address)
   839  	if err != nil {
   840  		t.Fatal(err)
   841  	}
   842  	defer client.Close()
   843  
   844  	var (
   845  		image       Image
   846  		ctx, cancel = testContext(t)
   847  		id          = t.Name()
   848  	)
   849  	defer cancel()
   850  
   851  	image, err = client.GetImage(ctx, testImage)
   852  	if err != nil {
   853  		t.Fatal(err)
   854  	}
   855  
   856  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withProcessArgs("sleep", "100")))
   857  	if err != nil {
   858  		t.Fatal(err)
   859  	}
   860  	defer container.Delete(ctx, WithSnapshotCleanup)
   861  
   862  	expected := "hello" + newLine
   863  
   864  	// creating IO early for easy resource cleanup
   865  	direct, err := newDirectIO(ctx, false)
   866  	if err != nil {
   867  		t.Fatal(err)
   868  	}
   869  	defer direct.Delete()
   870  	var (
   871  		wg  sync.WaitGroup
   872  		buf = bytes.NewBuffer(nil)
   873  	)
   874  	wg.Add(1)
   875  	go func() {
   876  		defer wg.Done()
   877  		io.Copy(buf, direct.Stdout)
   878  	}()
   879  
   880  	task, err := container.NewTask(ctx, empty())
   881  	if err != nil {
   882  		t.Fatal(err)
   883  	}
   884  	defer task.Delete(ctx)
   885  
   886  	status, err := task.Wait(ctx)
   887  	if err != nil {
   888  		t.Error(err)
   889  	}
   890  
   891  	if err := task.Start(ctx); err != nil {
   892  		t.Fatal(err)
   893  	}
   894  
   895  	spec, err := container.Spec(ctx)
   896  	if err != nil {
   897  		t.Fatal(err)
   898  	}
   899  
   900  	processSpec := spec.Process
   901  	processSpec.Args = []string{"cat"}
   902  	execID := t.Name() + "_exec"
   903  	process, err := task.Exec(ctx, execID, processSpec, direct.IOCreate)
   904  	if err != nil {
   905  		t.Fatal(err)
   906  	}
   907  	processStatusC, err := process.Wait(ctx)
   908  	if err != nil {
   909  		t.Fatal(err)
   910  	}
   911  
   912  	if err := process.Start(ctx); err != nil {
   913  		t.Fatal(err)
   914  	}
   915  
   916  	if _, err := fmt.Fprint(direct.Stdin, expected); err != nil {
   917  		t.Error(err)
   918  	}
   919  
   920  	if process, err = task.LoadProcess(ctx, execID, direct.IOAttach); err != nil {
   921  		t.Fatal(err)
   922  	}
   923  
   924  	if _, err := fmt.Fprint(direct.Stdin, expected); err != nil {
   925  		t.Error(err)
   926  	}
   927  
   928  	direct.Stdin.Close()
   929  
   930  	if err := process.CloseIO(ctx, WithStdinCloser); err != nil {
   931  		t.Error(err)
   932  	}
   933  
   934  	<-processStatusC
   935  
   936  	wg.Wait()
   937  
   938  	if err := task.Kill(ctx, syscall.SIGKILL); err != nil {
   939  		t.Error(err)
   940  	}
   941  
   942  	output := buf.String()
   943  
   944  	// we wrote the same thing after attach
   945  	expected = expected + expected
   946  	if output != expected {
   947  		t.Errorf("expected output %q but received %q", expected, output)
   948  	}
   949  	<-status
   950  }
   951  
   952  func TestContainerUserID(t *testing.T) {
   953  	t.Parallel()
   954  
   955  	client, err := newClient(t, address)
   956  	if err != nil {
   957  		t.Fatal(err)
   958  	}
   959  	defer client.Close()
   960  
   961  	var (
   962  		image       Image
   963  		ctx, cancel = testContext(t)
   964  		id          = t.Name()
   965  	)
   966  	defer cancel()
   967  
   968  	image, err = client.GetImage(ctx, testImage)
   969  	if err != nil {
   970  		t.Fatal(err)
   971  	}
   972  	direct, err := newDirectIO(ctx, false)
   973  	if err != nil {
   974  		t.Fatal(err)
   975  	}
   976  	defer direct.Delete()
   977  	var (
   978  		wg  sync.WaitGroup
   979  		buf = bytes.NewBuffer(nil)
   980  	)
   981  	wg.Add(1)
   982  	go func() {
   983  		defer wg.Done()
   984  		io.Copy(buf, direct.Stdout)
   985  	}()
   986  
   987  	// adm user in the alpine image has a uid of 3 and gid of 4.
   988  	container, err := client.NewContainer(ctx, id,
   989  		WithNewSnapshot(id, image),
   990  		WithNewSpec(oci.WithImageConfig(image), oci.WithUserID(3), oci.WithProcessArgs("sh", "-c", "echo $(id -u):$(id -g)")),
   991  	)
   992  	if err != nil {
   993  		t.Fatal(err)
   994  	}
   995  	defer container.Delete(ctx, WithSnapshotCleanup)
   996  
   997  	task, err := container.NewTask(ctx, direct.IOCreate)
   998  	if err != nil {
   999  		t.Fatal(err)
  1000  	}
  1001  	defer task.Delete(ctx)
  1002  
  1003  	statusC, err := task.Wait(ctx)
  1004  	if err != nil {
  1005  		t.Fatal(err)
  1006  	}
  1007  
  1008  	if err := task.Start(ctx); err != nil {
  1009  		t.Fatal(err)
  1010  	}
  1011  	<-statusC
  1012  
  1013  	wg.Wait()
  1014  
  1015  	output := strings.TrimSuffix(buf.String(), "\n")
  1016  	if output != "3:4" {
  1017  		t.Errorf("expected uid:gid to be 3:4, but received %q", output)
  1018  	}
  1019  }
  1020  
  1021  func TestContainerKillAll(t *testing.T) {
  1022  	t.Parallel()
  1023  
  1024  	client, err := newClient(t, address)
  1025  	if err != nil {
  1026  		t.Fatal(err)
  1027  	}
  1028  	defer client.Close()
  1029  
  1030  	var (
  1031  		image       Image
  1032  		ctx, cancel = testContext(t)
  1033  		id          = t.Name()
  1034  	)
  1035  	defer cancel()
  1036  
  1037  	image, err = client.GetImage(ctx, testImage)
  1038  	if err != nil {
  1039  		t.Fatal(err)
  1040  	}
  1041  
  1042  	container, err := client.NewContainer(ctx, id,
  1043  		WithNewSnapshot(id, image),
  1044  		WithNewSpec(oci.WithImageConfig(image),
  1045  			withProcessArgs("sh", "-c", "top"),
  1046  			oci.WithHostNamespace(specs.PIDNamespace),
  1047  		),
  1048  	)
  1049  	if err != nil {
  1050  		t.Fatal(err)
  1051  	}
  1052  	defer container.Delete(ctx, WithSnapshotCleanup)
  1053  
  1054  	stdout := bytes.NewBuffer(nil)
  1055  	task, err := container.NewTask(ctx, cio.NewCreator(withByteBuffers(stdout)))
  1056  	if err != nil {
  1057  		t.Fatal(err)
  1058  	}
  1059  	defer task.Delete(ctx)
  1060  
  1061  	statusC, err := task.Wait(ctx)
  1062  	if err != nil {
  1063  		t.Fatal(err)
  1064  	}
  1065  
  1066  	if err := task.Start(ctx); err != nil {
  1067  		t.Fatal(err)
  1068  	}
  1069  
  1070  	if err := task.Kill(ctx, syscall.SIGKILL, WithKillAll); err != nil {
  1071  		t.Error(err)
  1072  	}
  1073  
  1074  	<-statusC
  1075  	if _, err := task.Delete(ctx); err != nil {
  1076  		t.Fatal(err)
  1077  	}
  1078  }
  1079  
  1080  func TestDaemonRestartWithRunningShim(t *testing.T) {
  1081  	client, err := newClient(t, address)
  1082  	if err != nil {
  1083  		t.Fatal(err)
  1084  	}
  1085  	defer client.Close()
  1086  
  1087  	var (
  1088  		image       Image
  1089  		ctx, cancel = testContext(t)
  1090  		id          = t.Name()
  1091  	)
  1092  	defer cancel()
  1093  
  1094  	image, err = client.GetImage(ctx, testImage)
  1095  	if err != nil {
  1096  		t.Fatal(err)
  1097  	}
  1098  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), oci.WithProcessArgs("sleep", "100")))
  1099  	if err != nil {
  1100  		t.Fatal(err)
  1101  	}
  1102  	defer container.Delete(ctx, WithSnapshotCleanup)
  1103  
  1104  	task, err := container.NewTask(ctx, empty())
  1105  	if err != nil {
  1106  		t.Fatal(err)
  1107  	}
  1108  	defer task.Delete(ctx)
  1109  
  1110  	statusC, err := task.Wait(ctx)
  1111  	if err != nil {
  1112  		t.Error(err)
  1113  	}
  1114  
  1115  	pid := task.Pid()
  1116  	if pid < 1 {
  1117  		t.Fatalf("invalid task pid %d", pid)
  1118  	}
  1119  
  1120  	if err := task.Start(ctx); err != nil {
  1121  		t.Fatal(err)
  1122  	}
  1123  
  1124  	var exitStatus ExitStatus
  1125  	if err := ctrd.Restart(func() {
  1126  		exitStatus = <-statusC
  1127  	}); err != nil {
  1128  		t.Fatal(err)
  1129  	}
  1130  
  1131  	if exitStatus.Error() == nil {
  1132  		t.Errorf(`first task.Wait() should have failed with "transport is closing"`)
  1133  	}
  1134  
  1135  	waitCtx, cancel := context.WithTimeout(ctx, 1*time.Second)
  1136  	c, err := ctrd.waitForStart(waitCtx)
  1137  	cancel()
  1138  	if err != nil {
  1139  		t.Fatal(err)
  1140  	}
  1141  	c.Close()
  1142  
  1143  	statusC, err = task.Wait(ctx)
  1144  	if err != nil {
  1145  		t.Error(err)
  1146  	}
  1147  
  1148  	if err := task.Kill(ctx, syscall.SIGKILL); err != nil {
  1149  		t.Fatal(err)
  1150  	}
  1151  
  1152  	<-statusC
  1153  
  1154  	if err := unix.Kill(int(pid), 0); err != unix.ESRCH {
  1155  		t.Errorf("pid %d still exists", pid)
  1156  	}
  1157  }
  1158  
  1159  func TestContainerRuntimeOptionsv1(t *testing.T) {
  1160  	t.Parallel()
  1161  
  1162  	client, err := newClient(t, address)
  1163  	if err != nil {
  1164  		t.Fatal(err)
  1165  	}
  1166  	defer client.Close()
  1167  
  1168  	var (
  1169  		image       Image
  1170  		ctx, cancel = testContext(t)
  1171  		id          = t.Name()
  1172  	)
  1173  	defer cancel()
  1174  
  1175  	image, err = client.GetImage(ctx, testImage)
  1176  	if err != nil {
  1177  		t.Fatal(err)
  1178  	}
  1179  
  1180  	container, err := client.NewContainer(
  1181  		ctx, id,
  1182  		WithNewSnapshot(id, image),
  1183  		WithNewSpec(oci.WithImageConfig(image), withExitStatus(7)),
  1184  		WithRuntime(plugin.RuntimeLinuxV1, &runctypes.RuncOptions{Runtime: "no-runc"}),
  1185  	)
  1186  	if err != nil {
  1187  		t.Fatal(err)
  1188  	}
  1189  	defer container.Delete(ctx, WithSnapshotCleanup)
  1190  
  1191  	task, err := container.NewTask(ctx, empty())
  1192  	if err == nil {
  1193  		t.Errorf("task creation should have failed")
  1194  		task.Delete(ctx)
  1195  		return
  1196  	}
  1197  	if !strings.Contains(err.Error(), `"no-runc"`) {
  1198  		t.Errorf("task creation should have failed because of lack of executable. Instead failed with: %v", err.Error())
  1199  	}
  1200  }
  1201  
  1202  func TestContainerRuntimeOptionsv2(t *testing.T) {
  1203  	t.Parallel()
  1204  
  1205  	client, err := newClient(t, address)
  1206  	if err != nil {
  1207  		t.Fatal(err)
  1208  	}
  1209  	defer client.Close()
  1210  
  1211  	var (
  1212  		image       Image
  1213  		ctx, cancel = testContext(t)
  1214  		id          = t.Name()
  1215  	)
  1216  	defer cancel()
  1217  
  1218  	image, err = client.GetImage(ctx, testImage)
  1219  	if err != nil {
  1220  		t.Fatal(err)
  1221  	}
  1222  
  1223  	container, err := client.NewContainer(
  1224  		ctx, id,
  1225  		WithNewSnapshot(id, image),
  1226  		WithNewSpec(oci.WithImageConfig(image), withExitStatus(7)),
  1227  		WithRuntime(plugin.RuntimeRuncV1, &options.Options{BinaryName: "no-runc"}),
  1228  	)
  1229  	if err != nil {
  1230  		t.Fatal(err)
  1231  	}
  1232  	defer container.Delete(ctx, WithSnapshotCleanup)
  1233  
  1234  	task, err := container.NewTask(ctx, empty())
  1235  	if err == nil {
  1236  		t.Errorf("task creation should have failed")
  1237  		task.Delete(ctx)
  1238  		return
  1239  	}
  1240  	if !strings.Contains(err.Error(), `"no-runc"`) {
  1241  		t.Errorf("task creation should have failed because of lack of executable. Instead failed with: %v", err.Error())
  1242  	}
  1243  }
  1244  
  1245  func initContainerAndCheckChildrenDieOnKill(t *testing.T, opts ...oci.SpecOpts) {
  1246  	client, err := newClient(t, address)
  1247  	if err != nil {
  1248  		t.Fatal(err)
  1249  	}
  1250  	defer client.Close()
  1251  
  1252  	var (
  1253  		image       Image
  1254  		ctx, cancel = testContext(t)
  1255  		id          = t.Name()
  1256  	)
  1257  	defer cancel()
  1258  
  1259  	image, err = client.GetImage(ctx, testImage)
  1260  	if err != nil {
  1261  		t.Fatal(err)
  1262  	}
  1263  
  1264  	opts = append(opts, oci.WithImageConfig(image))
  1265  	opts = append(opts, withProcessArgs("sh", "-c", "sleep 42; echo hi"))
  1266  
  1267  	container, err := client.NewContainer(ctx, id,
  1268  		WithNewSnapshot(id, image),
  1269  		WithNewSpec(opts...),
  1270  	)
  1271  	if err != nil {
  1272  		t.Fatal(err)
  1273  	}
  1274  	defer container.Delete(ctx, WithSnapshotCleanup)
  1275  
  1276  	stdout := bytes.NewBuffer(nil)
  1277  	task, err := container.NewTask(ctx, cio.NewCreator(withByteBuffers(stdout)))
  1278  	if err != nil {
  1279  		t.Fatal(err)
  1280  	}
  1281  	defer task.Delete(ctx)
  1282  
  1283  	statusC, err := task.Wait(ctx)
  1284  	if err != nil {
  1285  		t.Fatal(err)
  1286  	}
  1287  
  1288  	if err := task.Start(ctx); err != nil {
  1289  		t.Fatal(err)
  1290  	}
  1291  
  1292  	if err := task.Kill(ctx, syscall.SIGKILL); err != nil {
  1293  		t.Error(err)
  1294  	}
  1295  
  1296  	// Give the shim time to reap the init process and kill the orphans
  1297  	select {
  1298  	case <-statusC:
  1299  	case <-time.After(100 * time.Millisecond):
  1300  	}
  1301  
  1302  	b, err := exec.Command("ps", "ax").CombinedOutput()
  1303  	if err != nil {
  1304  		t.Fatal(err)
  1305  	}
  1306  
  1307  	if strings.Contains(string(b), "sleep 42") {
  1308  		t.Fatalf("killing init didn't kill all its children:\n%v", string(b))
  1309  	}
  1310  
  1311  	if _, err := task.Delete(ctx, WithProcessKill); err != nil {
  1312  		t.Error(err)
  1313  	}
  1314  }
  1315  
  1316  func TestContainerKillInitPidHost(t *testing.T) {
  1317  	initContainerAndCheckChildrenDieOnKill(t, oci.WithHostNamespace(specs.PIDNamespace))
  1318  }
  1319  
  1320  func TestContainerKillInitKillsChildWhenNotHostPid(t *testing.T) {
  1321  	initContainerAndCheckChildrenDieOnKill(t)
  1322  }
  1323  
  1324  func TestUserNamespaces(t *testing.T) {
  1325  	t.Parallel()
  1326  	t.Run("WritableRootFS", func(t *testing.T) { testUserNamespaces(t, false) })
  1327  	// see #1373 and runc#1572
  1328  	t.Run("ReadonlyRootFS", func(t *testing.T) { testUserNamespaces(t, true) })
  1329  }
  1330  
  1331  func checkUserNS(t *testing.T) {
  1332  	cmd := exec.Command("true")
  1333  	cmd.SysProcAttr = &syscall.SysProcAttr{
  1334  		Cloneflags: syscall.CLONE_NEWUSER,
  1335  	}
  1336  
  1337  	if err := cmd.Run(); err != nil {
  1338  		t.Skip("User namespaces are unavailable")
  1339  	}
  1340  }
  1341  
  1342  func testUserNamespaces(t *testing.T, readonlyRootFS bool) {
  1343  	checkUserNS(t)
  1344  
  1345  	client, err := newClient(t, address)
  1346  	if err != nil {
  1347  		t.Fatal(err)
  1348  	}
  1349  	defer client.Close()
  1350  
  1351  	var (
  1352  		image       Image
  1353  		ctx, cancel = testContext(t)
  1354  		id          = strings.Replace(t.Name(), "/", "-", -1)
  1355  	)
  1356  	defer cancel()
  1357  
  1358  	image, err = client.GetImage(ctx, testImage)
  1359  	if err != nil {
  1360  		t.Fatal(err)
  1361  	}
  1362  
  1363  	opts := []NewContainerOpts{WithNewSpec(oci.WithImageConfig(image),
  1364  		withExitStatus(7),
  1365  		oci.WithUserNamespace(0, 1000, 10000),
  1366  	)}
  1367  	if readonlyRootFS {
  1368  		opts = append([]NewContainerOpts{WithRemappedSnapshotView(id, image, 1000, 1000)}, opts...)
  1369  	} else {
  1370  		opts = append([]NewContainerOpts{WithRemappedSnapshot(id, image, 1000, 1000)}, opts...)
  1371  	}
  1372  
  1373  	container, err := client.NewContainer(ctx, id, opts...)
  1374  	if err != nil {
  1375  		t.Fatal(err)
  1376  	}
  1377  	defer container.Delete(ctx, WithSnapshotCleanup)
  1378  
  1379  	var copts interface{}
  1380  	if CheckRuntime(client.runtime, "io.containerd.runc") {
  1381  		copts = &options.Options{
  1382  			IoUid: 1000,
  1383  			IoGid: 1000,
  1384  		}
  1385  	} else {
  1386  		copts = &runctypes.CreateOptions{
  1387  			IoUid: 1000,
  1388  			IoGid: 1000,
  1389  		}
  1390  	}
  1391  
  1392  	task, err := container.NewTask(ctx, cio.NewCreator(cio.WithStdio), func(_ context.Context, client *Client, r *TaskInfo) error {
  1393  		r.Options = copts
  1394  		return nil
  1395  	})
  1396  	if err != nil {
  1397  		t.Fatal(err)
  1398  	}
  1399  	defer task.Delete(ctx)
  1400  
  1401  	statusC, err := task.Wait(ctx)
  1402  	if err != nil {
  1403  		t.Fatal(err)
  1404  	}
  1405  
  1406  	if pid := task.Pid(); pid < 1 {
  1407  		t.Errorf("invalid task pid %d", pid)
  1408  	}
  1409  	if err := task.Start(ctx); err != nil {
  1410  		t.Error(err)
  1411  		task.Delete(ctx)
  1412  		return
  1413  	}
  1414  	status := <-statusC
  1415  	code, _, err := status.Result()
  1416  	if err != nil {
  1417  		t.Fatal(err)
  1418  	}
  1419  	if code != 7 {
  1420  		t.Errorf("expected status 7 from wait but received %d", code)
  1421  	}
  1422  	deleteStatus, err := task.Delete(ctx)
  1423  	if err != nil {
  1424  		t.Fatal(err)
  1425  	}
  1426  	if ec := deleteStatus.ExitCode(); ec != 7 {
  1427  		t.Errorf("expected status 7 from delete but received %d", ec)
  1428  	}
  1429  }
  1430  
  1431  func TestTaskResize(t *testing.T) {
  1432  	t.Parallel()
  1433  
  1434  	client, err := newClient(t, address)
  1435  	if err != nil {
  1436  		t.Fatal(err)
  1437  	}
  1438  	defer client.Close()
  1439  
  1440  	var (
  1441  		image       Image
  1442  		ctx, cancel = testContext(t)
  1443  		id          = t.Name()
  1444  	)
  1445  	defer cancel()
  1446  
  1447  	image, err = client.GetImage(ctx, testImage)
  1448  	if err != nil {
  1449  		t.Fatal(err)
  1450  	}
  1451  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withExitStatus(7)))
  1452  	if err != nil {
  1453  		t.Fatal(err)
  1454  	}
  1455  	defer container.Delete(ctx, WithSnapshotCleanup)
  1456  
  1457  	task, err := container.NewTask(ctx, empty())
  1458  	if err != nil {
  1459  		t.Fatal(err)
  1460  	}
  1461  	defer task.Delete(ctx)
  1462  
  1463  	statusC, err := task.Wait(ctx)
  1464  	if err != nil {
  1465  		t.Fatal(err)
  1466  	}
  1467  	if err := task.Resize(ctx, 32, 32); err != nil {
  1468  		t.Fatal(err)
  1469  	}
  1470  	task.Kill(ctx, syscall.SIGKILL)
  1471  	<-statusC
  1472  }
  1473  
  1474  func TestContainerImage(t *testing.T) {
  1475  	t.Parallel()
  1476  
  1477  	ctx, cancel := testContext(t)
  1478  	defer cancel()
  1479  	id := t.Name()
  1480  
  1481  	client, err := newClient(t, address)
  1482  	if err != nil {
  1483  		t.Fatal(err)
  1484  	}
  1485  	defer client.Close()
  1486  
  1487  	image, err := client.GetImage(ctx, testImage)
  1488  	if err != nil {
  1489  		t.Fatal(err)
  1490  	}
  1491  
  1492  	container, err := client.NewContainer(ctx, id, WithNewSpec(), WithImage(image))
  1493  	if err != nil {
  1494  		t.Fatal(err)
  1495  	}
  1496  	defer container.Delete(ctx)
  1497  
  1498  	i, err := container.Image(ctx)
  1499  	if err != nil {
  1500  		t.Fatal(err)
  1501  	}
  1502  	if i.Name() != image.Name() {
  1503  		t.Fatalf("expected container image name %s but received %s", image.Name(), i.Name())
  1504  	}
  1505  }
  1506  
  1507  func TestContainerNoImage(t *testing.T) {
  1508  	t.Parallel()
  1509  
  1510  	ctx, cancel := testContext(t)
  1511  	defer cancel()
  1512  	id := t.Name()
  1513  
  1514  	client, err := newClient(t, address)
  1515  	if err != nil {
  1516  		t.Fatal(err)
  1517  	}
  1518  	defer client.Close()
  1519  
  1520  	container, err := client.NewContainer(ctx, id, WithNewSpec())
  1521  	if err != nil {
  1522  		t.Fatal(err)
  1523  	}
  1524  	defer container.Delete(ctx)
  1525  
  1526  	_, err = container.Image(ctx)
  1527  	if err == nil {
  1528  		t.Fatal("error should not be nil when container is created without an image")
  1529  	}
  1530  	if errors.Cause(err) != errdefs.ErrNotFound {
  1531  		t.Fatalf("expected error to be %s but received %s", errdefs.ErrNotFound, err)
  1532  	}
  1533  }
  1534  
  1535  func TestUIDNoGID(t *testing.T) {
  1536  	t.Parallel()
  1537  
  1538  	ctx, cancel := testContext(t)
  1539  	defer cancel()
  1540  	id := t.Name()
  1541  
  1542  	client, err := newClient(t, address)
  1543  	if err != nil {
  1544  		t.Fatal(err)
  1545  	}
  1546  	defer client.Close()
  1547  	image, err := client.GetImage(ctx, testImage)
  1548  	if err != nil {
  1549  		t.Fatal(err)
  1550  	}
  1551  
  1552  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithUserID(1000)))
  1553  	if err != nil {
  1554  		t.Fatal(err)
  1555  	}
  1556  	defer container.Delete(ctx)
  1557  
  1558  	spec, err := container.Spec(ctx)
  1559  	if err != nil {
  1560  		t.Fatal(err)
  1561  	}
  1562  	if uid := spec.Process.User.UID; uid != 1000 {
  1563  		t.Fatalf("expected uid 1000 but received %d", uid)
  1564  	}
  1565  	if gid := spec.Process.User.GID; gid != 0 {
  1566  		t.Fatalf("expected gid 0 but received %d", gid)
  1567  	}
  1568  }
  1569  
  1570  func TestBindLowPortNonRoot(t *testing.T) {
  1571  	t.Parallel()
  1572  
  1573  	client, err := newClient(t, address)
  1574  	if err != nil {
  1575  		t.Fatal(err)
  1576  	}
  1577  	defer client.Close()
  1578  
  1579  	var (
  1580  		image       Image
  1581  		ctx, cancel = testContext(t)
  1582  		id          = t.Name()
  1583  	)
  1584  	defer cancel()
  1585  
  1586  	image, err = client.GetImage(ctx, testImage)
  1587  	if err != nil {
  1588  		t.Fatal(err)
  1589  	}
  1590  	container, err := client.NewContainer(ctx, id,
  1591  		WithNewSnapshot(id, image),
  1592  		WithNewSpec(oci.WithImageConfig(image), withProcessArgs("nc", "-l", "-p", "80"), oci.WithUIDGID(1000, 1000)),
  1593  	)
  1594  	if err != nil {
  1595  		t.Fatal(err)
  1596  	}
  1597  	defer container.Delete(ctx, WithSnapshotCleanup)
  1598  
  1599  	task, err := container.NewTask(ctx, empty())
  1600  	if err != nil {
  1601  		t.Fatal(err)
  1602  	}
  1603  	defer task.Delete(ctx)
  1604  
  1605  	statusC, err := task.Wait(ctx)
  1606  	if err != nil {
  1607  		t.Fatal(err)
  1608  	}
  1609  
  1610  	if err := task.Start(ctx); err != nil {
  1611  		t.Fatal(err)
  1612  	}
  1613  	status := <-statusC
  1614  	code, _, err := status.Result()
  1615  	if err != nil {
  1616  		t.Fatal(err)
  1617  	}
  1618  	if code != 1 {
  1619  		t.Errorf("expected status 1 from wait but received %d", code)
  1620  	}
  1621  	if _, err := task.Delete(ctx); err != nil {
  1622  		t.Fatal(err)
  1623  	}
  1624  }
  1625  
  1626  func TestBindLowPortNonOpt(t *testing.T) {
  1627  	t.Parallel()
  1628  
  1629  	client, err := newClient(t, address)
  1630  	if err != nil {
  1631  		t.Fatal(err)
  1632  	}
  1633  	defer client.Close()
  1634  
  1635  	var (
  1636  		image       Image
  1637  		ctx, cancel = testContext(t)
  1638  		id          = t.Name()
  1639  	)
  1640  	defer cancel()
  1641  
  1642  	image, err = client.GetImage(ctx, testImage)
  1643  	if err != nil {
  1644  		t.Fatal(err)
  1645  	}
  1646  	container, err := client.NewContainer(ctx, id,
  1647  		WithNewSnapshot(id, image),
  1648  		WithNewSpec(oci.WithImageConfig(image), withProcessArgs("nc", "-l", "-p", "80"), oci.WithUIDGID(1000, 1000), oci.WithAmbientCapabilities([]string{"CAP_NET_BIND_SERVICE"})),
  1649  	)
  1650  	if err != nil {
  1651  		t.Fatal(err)
  1652  	}
  1653  	defer container.Delete(ctx, WithSnapshotCleanup)
  1654  
  1655  	task, err := container.NewTask(ctx, empty())
  1656  	if err != nil {
  1657  		t.Fatal(err)
  1658  	}
  1659  	defer task.Delete(ctx)
  1660  
  1661  	statusC, err := task.Wait(ctx)
  1662  	if err != nil {
  1663  		t.Fatal(err)
  1664  	}
  1665  
  1666  	if err := task.Start(ctx); err != nil {
  1667  		t.Fatal(err)
  1668  	}
  1669  	go func() {
  1670  		time.Sleep(2 * time.Second)
  1671  		task.Kill(ctx, unix.SIGTERM)
  1672  	}()
  1673  	status := <-statusC
  1674  	code, _, err := status.Result()
  1675  	if err != nil {
  1676  		t.Fatal(err)
  1677  	}
  1678  	// 128 + sigterm
  1679  	if code != 143 {
  1680  		t.Errorf("expected status 143 from wait but received %d", code)
  1681  	}
  1682  	if _, err := task.Delete(ctx); err != nil {
  1683  		t.Fatal(err)
  1684  	}
  1685  }
  1686  
  1687  func TestContainerNoSTDIN(t *testing.T) {
  1688  	t.Parallel()
  1689  
  1690  	client, err := newClient(t, address)
  1691  	if err != nil {
  1692  		t.Fatal(err)
  1693  	}
  1694  	defer client.Close()
  1695  
  1696  	var (
  1697  		image       Image
  1698  		ctx, cancel = testContext(t)
  1699  		id          = t.Name()
  1700  	)
  1701  	defer cancel()
  1702  
  1703  	image, err = client.GetImage(ctx, testImage)
  1704  	if err != nil {
  1705  		t.Fatal(err)
  1706  	}
  1707  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withExitStatus(0)))
  1708  	if err != nil {
  1709  		t.Fatal(err)
  1710  	}
  1711  	defer container.Delete(ctx, WithSnapshotCleanup)
  1712  
  1713  	task, err := container.NewTask(ctx, cio.NewCreator(cio.WithStreams(nil, ioutil.Discard, ioutil.Discard)))
  1714  	if err != nil {
  1715  		t.Fatal(err)
  1716  	}
  1717  	defer task.Delete(ctx)
  1718  
  1719  	statusC, err := task.Wait(ctx)
  1720  	if err != nil {
  1721  		t.Fatal(err)
  1722  	}
  1723  	if err := task.Start(ctx); err != nil {
  1724  		t.Fatal(err)
  1725  	}
  1726  	status := <-statusC
  1727  	code, _, err := status.Result()
  1728  	if err != nil {
  1729  		t.Fatal(err)
  1730  	}
  1731  	if code != 0 {
  1732  		t.Errorf("expected status 0 from wait but received %d", code)
  1733  	}
  1734  }
  1735  
  1736  func TestShimOOMScore(t *testing.T) {
  1737  	containerdPid := ctrd.cmd.Process.Pid
  1738  	containerdScore, err := sys.GetOOMScoreAdj(containerdPid)
  1739  	if err != nil {
  1740  		t.Fatal(err)
  1741  	}
  1742  
  1743  	client, err := newClient(t, address)
  1744  	if err != nil {
  1745  		t.Fatal(err)
  1746  	}
  1747  	defer client.Close()
  1748  
  1749  	var (
  1750  		image       Image
  1751  		ctx, cancel = testContext(t)
  1752  		id          = t.Name()
  1753  	)
  1754  	defer cancel()
  1755  
  1756  	path := "/containerd/oomshim"
  1757  	cg, err := cgroups.New(cgroups.V1, cgroups.StaticPath(path), &specs.LinuxResources{})
  1758  	if err != nil {
  1759  		t.Fatal(err)
  1760  	}
  1761  	defer cg.Delete()
  1762  
  1763  	image, err = client.GetImage(ctx, testImage)
  1764  	if err != nil {
  1765  		t.Fatal(err)
  1766  	}
  1767  
  1768  	container, err := client.NewContainer(ctx, id, WithNewSnapshot(id, image), WithNewSpec(oci.WithImageConfig(image), withProcessArgs("sleep", "30")))
  1769  	if err != nil {
  1770  		t.Fatal(err)
  1771  	}
  1772  	defer container.Delete(ctx, WithSnapshotCleanup)
  1773  
  1774  	task, err := container.NewTask(ctx, empty(), WithShimCgroup(path))
  1775  	if err != nil {
  1776  		t.Fatal(err)
  1777  	}
  1778  	defer task.Delete(ctx)
  1779  
  1780  	statusC, err := task.Wait(ctx)
  1781  	if err != nil {
  1782  		t.Fatal(err)
  1783  	}
  1784  
  1785  	processes, err := cg.Processes(cgroups.Devices, false)
  1786  	if err != nil {
  1787  		t.Fatal(err)
  1788  	}
  1789  	expectedScore := containerdScore + 1
  1790  	// find the shim's pid
  1791  	for _, p := range processes {
  1792  		score, err := sys.GetOOMScoreAdj(p.Pid)
  1793  		if err != nil {
  1794  			t.Fatal(err)
  1795  		}
  1796  		if score != expectedScore {
  1797  			t.Errorf("expected score %d but got %d for shim process", expectedScore, score)
  1798  		}
  1799  	}
  1800  
  1801  	if err := task.Kill(ctx, unix.SIGKILL); err != nil {
  1802  		t.Fatal(err)
  1803  	}
  1804  
  1805  	<-statusC
  1806  }