github.com/sameo/containerd@v0.2.8/integration-test/exec_test.go (about)

     1  // +build !solaris
     2  
     3  package main
     4  
     5  import (
     6  	"path/filepath"
     7  	"syscall"
     8  	"time"
     9  
    10  	"github.com/docker/containerd/api/grpc/types"
    11  	"github.com/docker/docker/pkg/integration/checker"
    12  	"github.com/go-check/check"
    13  )
    14  
    15  func (cs *ContainerdSuite) TestBusyboxTopExecEcho(t *check.C) {
    16  	bundleName := "busybox-top"
    17  	if err := CreateBusyboxBundle(bundleName, []string{"top"}); err != nil {
    18  		t.Fatal(err)
    19  	}
    20  
    21  	var (
    22  		err   error
    23  		initp *ContainerProcess
    24  		echop *ContainerProcess
    25  	)
    26  
    27  	containerID := "top"
    28  	initp, err = cs.StartContainer(containerID, bundleName)
    29  	t.Assert(err, checker.Equals, nil)
    30  
    31  	echop, err = cs.AddProcessToContainer(initp, "echo", "/", []string{"PATH=/bin"}, []string{"sh", "-c", "echo -n Ay Caramba! ; exit 1"}, 0, 0)
    32  	t.Assert(err, checker.Equals, nil)
    33  
    34  	for _, evt := range []types.Event{
    35  		{
    36  			Type:   "start-container",
    37  			Id:     containerID,
    38  			Status: 0,
    39  			Pid:    "",
    40  		},
    41  		{
    42  			Type:   "start-process",
    43  			Id:     containerID,
    44  			Status: 0,
    45  			Pid:    "echo",
    46  		},
    47  		{
    48  			Type:   "exit",
    49  			Id:     containerID,
    50  			Status: 1,
    51  			Pid:    "echo",
    52  		},
    53  	} {
    54  		ch := initp.GetEventsChannel()
    55  		e := <-ch
    56  		evt.Timestamp = e.Timestamp
    57  
    58  		t.Assert(*e, checker.Equals, evt)
    59  	}
    60  
    61  	t.Assert(echop.io.stdoutBuffer.String(), checker.Equals, "Ay Caramba!")
    62  }
    63  
    64  func (cs *ContainerdSuite) TestBusyboxTopExecTop(t *check.C) {
    65  	bundleName := "busybox-top"
    66  	if err := CreateBusyboxBundle(bundleName, []string{"top"}); err != nil {
    67  		t.Fatal(err)
    68  	}
    69  
    70  	var (
    71  		err   error
    72  		initp *ContainerProcess
    73  	)
    74  
    75  	containerID := "top"
    76  	initp, err = cs.StartContainer(containerID, bundleName)
    77  	t.Assert(err, checker.Equals, nil)
    78  
    79  	execID := "top1"
    80  	_, err = cs.AddProcessToContainer(initp, execID, "/", []string{"PATH=/usr/bin"}, []string{"top"}, 0, 0)
    81  	t.Assert(err, checker.Equals, nil)
    82  
    83  	for idx, evt := range []types.Event{
    84  		{
    85  			Type:   "start-container",
    86  			Id:     containerID,
    87  			Status: 0,
    88  			Pid:    "",
    89  		},
    90  		{
    91  			Type:   "start-process",
    92  			Id:     containerID,
    93  			Status: 0,
    94  			Pid:    execID,
    95  		},
    96  		{
    97  			Type:   "exit",
    98  			Id:     containerID,
    99  			Status: 137,
   100  			Pid:    execID,
   101  		},
   102  	} {
   103  		ch := initp.GetEventsChannel()
   104  		e := <-ch
   105  		evt.Timestamp = e.Timestamp
   106  		t.Assert(*e, checker.Equals, evt)
   107  		if idx == 1 {
   108  			// Process Started, kill it
   109  			cs.SignalContainerProcess(containerID, "top1", uint32(syscall.SIGKILL))
   110  		}
   111  	}
   112  
   113  	// Container should still be running
   114  	containers, err := cs.ListRunningContainers()
   115  	if err != nil {
   116  		t.Fatal(err)
   117  	}
   118  	t.Assert(len(containers), checker.Equals, 1)
   119  	t.Assert(containers[0].Id, checker.Equals, "top")
   120  	t.Assert(containers[0].Status, checker.Equals, "running")
   121  	t.Assert(containers[0].BundlePath, check.Equals, filepath.Join(cs.cwd, GetBundle(bundleName).Path))
   122  }
   123  
   124  func (cs *ContainerdSuite) TestBusyboxTopExecTopKillInit(t *check.C) {
   125  	bundleName := "busybox-top"
   126  	if err := CreateBusyboxBundle(bundleName, []string{"top"}); err != nil {
   127  		t.Fatal(err)
   128  	}
   129  
   130  	var (
   131  		err   error
   132  		initp *ContainerProcess
   133  	)
   134  
   135  	containerID := "top"
   136  	initp, err = cs.StartContainer(containerID, bundleName)
   137  	t.Assert(err, checker.Equals, nil)
   138  
   139  	execID := "top1"
   140  	_, err = cs.AddProcessToContainer(initp, execID, "/", []string{"PATH=/usr/bin"}, []string{"top"}, 0, 0)
   141  	t.Assert(err, checker.Equals, nil)
   142  
   143  	ch := initp.GetEventsChannel()
   144  	for _, evt := range []types.Event{
   145  		{
   146  			Type:   "start-container",
   147  			Id:     containerID,
   148  			Status: 0,
   149  			Pid:    "",
   150  		},
   151  		{
   152  			Type:   "start-process",
   153  			Id:     containerID,
   154  			Status: 0,
   155  			Pid:    execID,
   156  		},
   157  	} {
   158  		e := <-ch
   159  		evt.Timestamp = e.Timestamp
   160  		t.Assert(*e, checker.Equals, evt)
   161  	}
   162  
   163  	cs.SignalContainerProcess(containerID, "init", uint32(syscall.SIGTERM))
   164  	for i := 0; i < 2; i++ {
   165  		e := <-ch
   166  		switch e.Pid {
   167  		case "init":
   168  			evt := types.Event{
   169  				Type:      "exit",
   170  				Id:        containerID,
   171  				Status:    143,
   172  				Pid:       "init",
   173  				Timestamp: e.Timestamp,
   174  			}
   175  			t.Assert(*e, checker.Equals, evt)
   176  		case execID:
   177  			evt := types.Event{
   178  				Type:      "exit",
   179  				Id:        containerID,
   180  				Status:    137,
   181  				Pid:       execID,
   182  				Timestamp: e.Timestamp,
   183  			}
   184  			t.Assert(*e, checker.Equals, evt)
   185  		default:
   186  			t.Fatalf("Unexpected event %v", e)
   187  		}
   188  	}
   189  
   190  }
   191  
   192  func (cs *ContainerdSuite) TestBusyboxExecCreateDetachedChild(t *check.C) {
   193  	bundleName := "busybox-top"
   194  	if err := CreateBusyboxBundle(bundleName, []string{"top"}); err != nil {
   195  		t.Fatal(err)
   196  	}
   197  
   198  	var (
   199  		err   error
   200  		initp *ContainerProcess
   201  	)
   202  
   203  	containerID := "top"
   204  	initp, err = cs.StartContainer(containerID, bundleName)
   205  	t.Assert(err, checker.Equals, nil)
   206  
   207  	ch := initp.GetEventsChannel()
   208  	for _, evt := range []types.Event{
   209  		{
   210  			Type:   "start-container",
   211  			Id:     containerID,
   212  			Status: 0,
   213  			Pid:    "",
   214  		},
   215  	} {
   216  		e := <-ch
   217  		evt.Timestamp = e.Timestamp
   218  		t.Assert(*e, checker.Equals, evt)
   219  	}
   220  
   221  	execID := "sh-sleep"
   222  	_, err = cs.AddProcessToContainer(initp, execID, "/", []string{"PATH=/bin"}, []string{"sh", "-c", "sleep 1000 2>&- 1>&- 0<&- &"}, 0, 0)
   223  	t.Assert(err, checker.Equals, nil)
   224  	for _, evt := range []types.Event{
   225  		{
   226  			Type:   "start-process",
   227  			Id:     containerID,
   228  			Status: 0,
   229  			Pid:    execID,
   230  		},
   231  		{
   232  			Type:   "exit",
   233  			Id:     containerID,
   234  			Status: 0,
   235  			Pid:    execID,
   236  		},
   237  	} {
   238  		e := <-ch
   239  		evt.Timestamp = e.Timestamp
   240  		t.Assert(*e, checker.Equals, evt)
   241  	}
   242  
   243  	// Check that sleep is still running
   244  	execOutput, err := cs.AddProcessToContainer(initp, "ps", "/", []string{"PATH=/bin"}, []string{"ps", "aux"}, 0, 0)
   245  	t.Assert(err, checker.Equals, nil)
   246  	t.Assert(execOutput.io.stdoutBuffer.String(), checker.Contains, "sleep 1000")
   247  }
   248  
   249  func (cs *ContainerdSuite) TestBusyboxExecCreateAttachedChild(t *check.C) {
   250  	bundleName := "busybox-top"
   251  	if err := CreateBusyboxBundle(bundleName, []string{"top"}); err != nil {
   252  		t.Fatal(err)
   253  	}
   254  
   255  	var (
   256  		err   error
   257  		initp *ContainerProcess
   258  	)
   259  
   260  	containerID := "top"
   261  	initp, err = cs.StartContainer(containerID, bundleName)
   262  	t.Assert(err, checker.Equals, nil)
   263  
   264  	ch := initp.GetEventsChannel()
   265  	for _, evt := range []types.Event{
   266  		{
   267  			Type:   "start-container",
   268  			Id:     containerID,
   269  			Status: 0,
   270  			Pid:    "",
   271  		},
   272  	} {
   273  		e := <-ch
   274  		evt.Timestamp = e.Timestamp
   275  		t.Assert(*e, checker.Equals, evt)
   276  	}
   277  
   278  	doneCh := make(chan struct{})
   279  	go func() {
   280  		execID := "sh-sleep"
   281  		_, err = cs.AddProcessToContainer(initp, execID, "/", []string{"PATH=/bin"}, []string{"sh", "-c", "sleep 5 &"}, 0, 0)
   282  		t.Assert(err, checker.Equals, nil)
   283  		for _, evt := range []types.Event{
   284  			{
   285  				Type:   "start-process",
   286  				Id:     containerID,
   287  				Status: 0,
   288  				Pid:    execID,
   289  			},
   290  			{
   291  				Type:   "exit",
   292  				Id:     containerID,
   293  				Status: 0,
   294  				Pid:    execID,
   295  			},
   296  		} {
   297  			e := <-ch
   298  			evt.Timestamp = e.Timestamp
   299  			t.Assert(*e, checker.Equals, evt)
   300  		}
   301  		close(doneCh)
   302  	}()
   303  
   304  	select {
   305  	case <-doneCh:
   306  		break
   307  	case <-time.After(8 * time.Second):
   308  		t.Fatal("exec did not exit within 5 seconds")
   309  	}
   310  }
   311  
   312  func (cs *ContainerdSuite) TestBusyboxRestoreDeadExec(t *check.C) {
   313  	bundleName := "busybox-top"
   314  	if err := CreateBusyboxBundle(bundleName, []string{"top"}); err != nil {
   315  		t.Fatal(err)
   316  	}
   317  
   318  	var (
   319  		err   error
   320  		initp *ContainerProcess
   321  	)
   322  
   323  	containerID := "top"
   324  	initp, err = cs.StartContainer(containerID, bundleName)
   325  	t.Assert(err, checker.Equals, nil)
   326  
   327  	ch := initp.GetEventsChannel()
   328  	for _, evt := range []types.Event{
   329  		{
   330  			Type:   "start-container",
   331  			Id:     containerID,
   332  			Status: 0,
   333  			Pid:    "",
   334  		},
   335  	} {
   336  		e := <-ch
   337  		evt.Timestamp = e.Timestamp
   338  		t.Assert(*e, checker.Equals, evt)
   339  	}
   340  
   341  	createCh := make(chan struct{})
   342  	killCh := make(chan struct{})
   343  	doneCh := make(chan struct{})
   344  	restartCh := make(chan struct{})
   345  	go func() {
   346  		execID := "sleep"
   347  		p, err := cs.AddProcessToContainer(initp, execID, "/", []string{"PATH=/bin"}, []string{"sleep", "10"}, 0, 0)
   348  		t.Assert(err, checker.Equals, nil)
   349  		for idx, evt := range []types.Event{
   350  			{
   351  				Type:   "start-process",
   352  				Id:     containerID,
   353  				Status: 0,
   354  				Pid:    execID,
   355  			},
   356  			{
   357  				Type:   "exit",
   358  				Id:     containerID,
   359  				Status: 137,
   360  				Pid:    execID,
   361  			},
   362  		} {
   363  			e := <-ch
   364  			evt.Timestamp = e.Timestamp
   365  			t.Assert(*e, checker.Equals, evt)
   366  			if idx == 0 {
   367  				close(createCh)
   368  				<-killCh
   369  				syscall.Kill(int(p.systemPid), syscall.SIGKILL)
   370  				close(restartCh)
   371  			}
   372  		}
   373  		close(doneCh)
   374  	}()
   375  
   376  	// wait for sleep to be created
   377  	<-createCh
   378  	// stop containerd
   379  	cs.StopDaemon(false)
   380  	// notify go routine to go ahead and kill the sleep exec
   381  	close(killCh)
   382  	// wait for the kill signal to have been sent
   383  	<-restartCh
   384  	if err := cs.StartDaemon(); err != nil {
   385  		t.Fatal(err)
   386  	}
   387  	// wait a tiny bit more just in case
   388  	time.Sleep(100 * time.Millisecond)
   389  
   390  	select {
   391  	case <-doneCh:
   392  		break
   393  	case <-time.After(8 * time.Second):
   394  		t.Fatal("exec did not exit within 5 seconds")
   395  	}
   396  }