github.com/chenbh/concourse/v6@v6.4.2/worker/runtime/libcontainerd/client.go (about)

     1  package libcontainerd
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"time"
     7  
     8  	"github.com/containerd/containerd"
     9  	"github.com/opencontainers/runtime-spec/specs-go"
    10  )
    11  
    12  //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 . Client
    13  //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 github.com/containerd/containerd.Container
    14  //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 github.com/containerd/containerd.Task
    15  //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 github.com/containerd/containerd.Process
    16  //go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 github.com/containerd/containerd/cio.IO
    17  
    18  // Client represents the minimum interface used to communicate with containerd
    19  // to manage containers.
    20  //
    21  type Client interface {
    22  
    23  	// Init provides the initialization of internal structures necessary by
    24  	// the client, e.g., instantiation of the gRPC client.
    25  	//
    26  	Init() (err error)
    27  
    28  	// Version queries containerd's version service in order to verify
    29  	// connectivity.
    30  	//
    31  	Version(ctx context.Context) (err error)
    32  
    33  	// Stop deallocates any initialization performed by `Init()` and
    34  	// subsequent calls to methods of this interface.
    35  	//
    36  	Stop() (err error)
    37  
    38  	// NewContainer creates a container in containerd.
    39  	//
    40  	NewContainer(
    41  		ctx context.Context,
    42  		id string,
    43  		labels map[string]string,
    44  		oci *specs.Spec,
    45  	) (
    46  		container containerd.Container, err error,
    47  	)
    48  
    49  	// Containers lists containers available in containerd matching a given
    50  	// labelset.
    51  	//
    52  	Containers(
    53  		ctx context.Context,
    54  		labels ...string,
    55  	) (
    56  		containers []containerd.Container, err error,
    57  	)
    58  
    59  	// GetContainer retrieves a created container that matches the specified handle.
    60  	//
    61  	GetContainer(
    62  		ctx context.Context,
    63  		handle string,
    64  	) (
    65  		container containerd.Container, err error,
    66  	)
    67  
    68  	// Destroy stops any running tasks on a container and removes the container.
    69  	// If a task cannot be stopped gracefully, it will be forcefully stopped after
    70  	// a timeout period (default 10 seconds).
    71  	//
    72  	Destroy(ctx context.Context, handle string) error
    73  }
    74  
    75  type client struct {
    76  	addr           string
    77  	namespace      string
    78  	requestTimeout time.Duration
    79  
    80  	containerd *containerd.Client
    81  }
    82  
    83  var _ Client = (*client)(nil)
    84  
    85  func New(addr, namespace string, requestTimeout time.Duration) *client {
    86  	return &client{
    87  		addr:           addr,
    88  		namespace:      namespace,
    89  		requestTimeout: requestTimeout,
    90  	}
    91  }
    92  
    93  func (c *client) Init() (err error) {
    94  	c.containerd, err = containerd.New(
    95  		c.addr,
    96  		containerd.WithDefaultNamespace(c.namespace),
    97  	)
    98  	if err != nil {
    99  		err = fmt.Errorf("failed to connect to addr %s: %w", c.addr, err)
   100  		return
   101  	}
   102  
   103  	return
   104  }
   105  
   106  func (c *client) Stop() (err error) {
   107  	if c.containerd == nil {
   108  		return
   109  	}
   110  
   111  	err = c.containerd.Close()
   112  	return
   113  }
   114  
   115  func (c *client) NewContainer(
   116  	ctx context.Context, id string, labels map[string]string, oci *specs.Spec,
   117  ) (
   118  	containerd.Container, error,
   119  ) {
   120  	ctx, cancel := context.WithTimeout(ctx, c.requestTimeout)
   121  	defer cancel()
   122  
   123  	return c.containerd.NewContainer(ctx, id,
   124  		containerd.WithSpec(oci),
   125  		containerd.WithContainerLabels(labels),
   126  	)
   127  }
   128  
   129  func (c *client) Containers(
   130  	ctx context.Context, labels ...string,
   131  ) (
   132  	[]containerd.Container, error,
   133  ) {
   134  	ctx, cancel := context.WithTimeout(ctx, c.requestTimeout)
   135  	defer cancel()
   136  
   137  	return c.containerd.Containers(ctx, labels...)
   138  }
   139  
   140  func (c *client) GetContainer(ctx context.Context, handle string) (containerd.Container, error) {
   141  	ctx, cancel := context.WithTimeout(ctx, c.requestTimeout)
   142  	defer cancel()
   143  
   144  	cont, err := c.containerd.LoadContainer(ctx, handle)
   145  	if err != nil {
   146  		return nil, err
   147  	}
   148  
   149  	return &container{
   150  		requestTimeout: c.requestTimeout,
   151  		container:      cont,
   152  	}, nil
   153  }
   154  
   155  func (c *client) Version(ctx context.Context) (err error) {
   156  	ctx, cancel := context.WithTimeout(ctx, c.requestTimeout)
   157  	defer cancel()
   158  
   159  	_, err = c.containerd.Version(ctx)
   160  	return
   161  }
   162  func (c *client) Destroy(ctx context.Context, handle string) error {
   163  	ctx, cancel := context.WithTimeout(ctx, c.requestTimeout)
   164  	defer cancel()
   165  
   166  	container, err := c.GetContainer(ctx, handle)
   167  	if err != nil {
   168  		return err
   169  	}
   170  
   171  	return container.Delete(ctx)
   172  }