github.com/zhuohuang-hust/src-cbuild@v0.0.0-20230105071821-c7aab3e7c840/mergeCode/containerd/integration-test/container_utils_test.go (about)

     1  package main
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io"
     7  	"io/ioutil"
     8  	"os"
     9  	"path/filepath"
    10  	"sort"
    11  	"syscall"
    12  	"time"
    13  
    14  	"github.com/docker/containerd/api/grpc/types"
    15  	"github.com/golang/protobuf/ptypes"
    16  	"github.com/golang/protobuf/ptypes/timestamp"
    17  	"golang.org/x/net/context"
    18  	"golang.org/x/sys/unix"
    19  )
    20  
    21  func (cs *ContainerdSuite) GetLogs() string {
    22  	b, _ := ioutil.ReadFile(cs.logFile.Name())
    23  	return string(b)
    24  }
    25  
    26  func (cs *ContainerdSuite) Events(from time.Time, storedOnly bool, id string) (types.API_EventsClient, error) {
    27  	var (
    28  		ftsp *timestamp.Timestamp
    29  		err  error
    30  	)
    31  	if !from.IsZero() {
    32  		ftsp, err = ptypes.TimestampProto(from)
    33  		if err != nil {
    34  			return nil, err
    35  		}
    36  	}
    37  
    38  	return cs.grpcClient.Events(context.Background(), &types.EventsRequest{Timestamp: ftsp, StoredOnly: storedOnly, Id: id})
    39  }
    40  
    41  func (cs *ContainerdSuite) ListRunningContainers() ([]*types.Container, error) {
    42  	resp, err := cs.grpcClient.State(context.Background(), &types.StateRequest{})
    43  	if err != nil {
    44  		return nil, err
    45  	}
    46  	return resp.Containers, nil
    47  }
    48  
    49  func (cs *ContainerdSuite) SignalContainerProcess(id string, procID string, sig uint32) error {
    50  	_, err := cs.grpcClient.Signal(context.Background(), &types.SignalRequest{
    51  		Id:     id,
    52  		Pid:    procID,
    53  		Signal: sig,
    54  	})
    55  	return err
    56  }
    57  
    58  func (cs *ContainerdSuite) SignalContainer(id string, sig uint32) error {
    59  	return cs.SignalContainerProcess(id, "init", sig)
    60  }
    61  
    62  func (cs *ContainerdSuite) KillContainer(id string) error {
    63  	return cs.SignalContainerProcess(id, "init", uint32(syscall.SIGKILL))
    64  }
    65  
    66  func (cs *ContainerdSuite) UpdateContainerResource(id string, rs *types.UpdateResource) error {
    67  	_, err := cs.grpcClient.UpdateContainer(context.Background(), &types.UpdateContainerRequest{
    68  		Id:        id,
    69  		Pid:       "init",
    70  		Status:    "",
    71  		Resources: rs,
    72  	})
    73  	return err
    74  }
    75  
    76  func (cs *ContainerdSuite) PauseContainer(id string) error {
    77  	_, err := cs.grpcClient.UpdateContainer(context.Background(), &types.UpdateContainerRequest{
    78  		Id:     id,
    79  		Pid:    "init",
    80  		Status: "paused",
    81  	})
    82  	return err
    83  }
    84  
    85  func (cs *ContainerdSuite) ResumeContainer(id string) error {
    86  	_, err := cs.grpcClient.UpdateContainer(context.Background(), &types.UpdateContainerRequest{
    87  		Id:     id,
    88  		Pid:    "init",
    89  		Status: "running",
    90  	})
    91  	return err
    92  }
    93  
    94  func (cs *ContainerdSuite) GetContainerStats(id string) (*types.StatsResponse, error) {
    95  	stats, err := cs.grpcClient.Stats(context.Background(), &types.StatsRequest{
    96  		Id: id,
    97  	})
    98  	return stats, err
    99  }
   100  
   101  type stdio struct {
   102  	stdin        string
   103  	stdout       string
   104  	stderr       string
   105  	stdinf       *os.File
   106  	stdoutf      *os.File
   107  	stderrf      *os.File
   108  	stdoutBuffer bytes.Buffer
   109  	stderrBuffer bytes.Buffer
   110  }
   111  
   112  type ContainerProcess struct {
   113  	containerID string
   114  	pid         string
   115  	bundle      *Bundle
   116  	io          stdio
   117  	eventsCh    chan *types.Event
   118  	cs          *ContainerdSuite
   119  	hasExited   bool
   120  }
   121  
   122  func (c *ContainerProcess) openIo() (err error) {
   123  	defer func() {
   124  		if err != nil {
   125  			c.Cleanup()
   126  		}
   127  	}()
   128  
   129  	c.io.stdinf, err = os.OpenFile(c.io.stdin, os.O_RDWR, 0)
   130  	if err != nil {
   131  		return err
   132  	}
   133  
   134  	c.io.stdoutf, err = os.OpenFile(c.io.stdout, os.O_RDWR, 0)
   135  	if err != nil {
   136  		return err
   137  	}
   138  	go io.Copy(&c.io.stdoutBuffer, c.io.stdoutf)
   139  
   140  	c.io.stderrf, err = os.OpenFile(c.io.stderr, os.O_RDWR, 0)
   141  	if err != nil {
   142  		return err
   143  	}
   144  	go io.Copy(&c.io.stderrBuffer, c.io.stderrf)
   145  
   146  	return nil
   147  }
   148  
   149  func (c *ContainerProcess) GetEventsChannel() chan *types.Event {
   150  	return c.eventsCh
   151  }
   152  
   153  func (c *ContainerProcess) GetNextEvent() *types.Event {
   154  	if c.hasExited {
   155  		return nil
   156  	}
   157  
   158  	e := <-c.eventsCh
   159  
   160  	if e.Type == "exit" && e.Pid == c.pid {
   161  		c.Cleanup()
   162  		c.hasExited = true
   163  		close(c.eventsCh)
   164  	}
   165  
   166  	return e
   167  }
   168  
   169  func (c *ContainerProcess) CloseStdin() error {
   170  	_, err := c.cs.grpcClient.UpdateProcess(context.Background(), &types.UpdateProcessRequest{
   171  		Id:         c.containerID,
   172  		Pid:        c.pid,
   173  		CloseStdin: true,
   174  	})
   175  	return err
   176  }
   177  
   178  func (c *ContainerProcess) Cleanup() {
   179  	for _, f := range []*os.File{
   180  		c.io.stdinf,
   181  		c.io.stdoutf,
   182  		c.io.stderrf,
   183  	} {
   184  		if f != nil {
   185  			f.Close()
   186  			f = nil
   187  		}
   188  	}
   189  }
   190  
   191  func NewContainerProcess(cs *ContainerdSuite, bundle *Bundle, cid, pid string) (c *ContainerProcess, err error) {
   192  	c = &ContainerProcess{
   193  		containerID: cid,
   194  		pid:         "init",
   195  		bundle:      bundle,
   196  		eventsCh:    make(chan *types.Event, 8),
   197  		cs:          cs,
   198  		hasExited:   false,
   199  	}
   200  
   201  	for name, path := range map[string]*string{
   202  		"stdin":  &c.io.stdin,
   203  		"stdout": &c.io.stdout,
   204  		"stderr": &c.io.stderr,
   205  	} {
   206  		*path = filepath.Join(bundle.Path, "io", cid+"-"+pid+"-"+name)
   207  		if err = unix.Mkfifo(*path, 0755); err != nil && !os.IsExist(err) {
   208  			return nil, err
   209  		}
   210  	}
   211  
   212  	if err = c.openIo(); err != nil {
   213  		return nil, err
   214  	}
   215  
   216  	return c, nil
   217  }
   218  
   219  func (cs *ContainerdSuite) StartContainerWithEventFilter(id, bundleName string, filter func(*types.Event)) (c *ContainerProcess, err error) {
   220  	bundle := GetBundle(bundleName)
   221  	if bundle == nil {
   222  		return nil, fmt.Errorf("No such bundle '%s'", bundleName)
   223  	}
   224  
   225  	c, err = NewContainerProcess(cs, bundle, id, "init")
   226  	if err != nil {
   227  		return nil, err
   228  	}
   229  
   230  	r := &types.CreateContainerRequest{
   231  		Id:         id,
   232  		BundlePath: filepath.Join(cs.cwd, bundle.Path),
   233  		Stdin:      filepath.Join(cs.cwd, c.io.stdin),
   234  		Stdout:     filepath.Join(cs.cwd, c.io.stdout),
   235  		Stderr:     filepath.Join(cs.cwd, c.io.stderr),
   236  	}
   237  
   238  	if filter == nil {
   239  		filter = func(event *types.Event) {
   240  			c.eventsCh <- event
   241  		}
   242  	}
   243  
   244  	cs.SetContainerEventFilter(id, filter)
   245  
   246  	if _, err := cs.grpcClient.CreateContainer(context.Background(), r); err != nil {
   247  		c.Cleanup()
   248  		return nil, err
   249  	}
   250  
   251  	return c, nil
   252  }
   253  
   254  func (cs *ContainerdSuite) StartContainer(id, bundleName string) (c *ContainerProcess, err error) {
   255  	return cs.StartContainerWithEventFilter(id, bundleName, nil)
   256  }
   257  
   258  func (cs *ContainerdSuite) RunContainer(id, bundleName string) (c *ContainerProcess, err error) {
   259  	c, err = cs.StartContainer(id, bundleName)
   260  	if err != nil {
   261  		return nil, err
   262  	}
   263  
   264  	for {
   265  		e := c.GetNextEvent()
   266  		if e.Type == "exit" && e.Pid == "init" {
   267  			break
   268  		}
   269  	}
   270  
   271  	return c, err
   272  }
   273  
   274  func (cs *ContainerdSuite) AddProcessToContainer(init *ContainerProcess, pid, cwd string, env, args []string, uid, gid uint32) (c *ContainerProcess, err error) {
   275  	c, err = NewContainerProcess(cs, init.bundle, init.containerID, pid)
   276  	if err != nil {
   277  		return nil, err
   278  	}
   279  
   280  	pr := &types.AddProcessRequest{
   281  		Id:   init.containerID,
   282  		Pid:  pid,
   283  		Args: args,
   284  		Cwd:  cwd,
   285  		Env:  env,
   286  		User: &types.User{
   287  			Uid: uid,
   288  			Gid: gid,
   289  		},
   290  		Stdin:  filepath.Join(cs.cwd, c.io.stdin),
   291  		Stdout: filepath.Join(cs.cwd, c.io.stdout),
   292  		Stderr: filepath.Join(cs.cwd, c.io.stderr),
   293  	}
   294  
   295  	_, err = cs.grpcClient.AddProcess(context.Background(), pr)
   296  	if err != nil {
   297  		c.Cleanup()
   298  		return nil, err
   299  	}
   300  
   301  	return c, nil
   302  }
   303  
   304  type containerSorter struct {
   305  	c []*types.Container
   306  }
   307  
   308  func (s *containerSorter) Len() int {
   309  	return len(s.c)
   310  }
   311  
   312  func (s *containerSorter) Swap(i, j int) {
   313  	s.c[i], s.c[j] = s.c[j], s.c[i]
   314  }
   315  
   316  func (s *containerSorter) Less(i, j int) bool {
   317  	return s.c[i].Id < s.c[j].Id
   318  }
   319  
   320  func sortContainers(c []*types.Container) {
   321  	sort.Sort(&containerSorter{c})
   322  }