...

Source file src/github.com/chaos-mesh/chaos-mesh/pkg/chaosdaemon/crclients/containerd/client.go

Documentation: github.com/chaos-mesh/chaos-mesh/pkg/chaosdaemon/crclients/containerd

     1  // Copyright 2021 Chaos Mesh Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package containerd
    15  
    16  import (
    17  	"context"
    18  	"fmt"
    19  	"syscall"
    20  
    21  	"github.com/containerd/containerd"
    22  
    23  	"github.com/chaos-mesh/chaos-mesh/pkg/mock"
    24  )
    25  
    26  const (
    27  	containerdProtocolPrefix = "containerd://"
    28  )
    29  
    30  // ContainerdClientInterface represents the ContainerClient, it's used to simply unit test
    31  type ContainerdClientInterface interface {
    32  	LoadContainer(ctx context.Context, id string) (containerd.Container, error)
    33  }
    34  
    35  // ContainerdClient can get information from containerd
    36  type ContainerdClient struct {
    37  	client ContainerdClientInterface
    38  }
    39  
    40  // FormatContainerID strips protocol prefix from the container ID
    41  func (c ContainerdClient) FormatContainerID(ctx context.Context, containerID string) (string, error) {
    42  	if len(containerID) < len(containerdProtocolPrefix) {
    43  		return "", fmt.Errorf("container id %s is not a containerd container id", containerID)
    44  	}
    45  	if containerID[0:len(containerdProtocolPrefix)] != containerdProtocolPrefix {
    46  		return "", fmt.Errorf("expected %s but got %s", containerdProtocolPrefix, containerID[0:len(containerdProtocolPrefix)])
    47  	}
    48  	return containerID[len(containerdProtocolPrefix):], nil
    49  }
    50  
    51  // GetPidFromContainerID fetches PID according to container id
    52  func (c ContainerdClient) GetPidFromContainerID(ctx context.Context, containerID string) (uint32, error) {
    53  	id, err := c.FormatContainerID(ctx, containerID)
    54  	if err != nil {
    55  		return 0, err
    56  	}
    57  	container, err := c.client.LoadContainer(ctx, id)
    58  	if err != nil {
    59  		return 0, err
    60  	}
    61  	task, err := container.Task(ctx, nil)
    62  	if err != nil {
    63  		return 0, err
    64  	}
    65  	return task.Pid(), nil
    66  }
    67  
    68  // ContainerKillByContainerID kills container according to container id
    69  func (c ContainerdClient) ContainerKillByContainerID(ctx context.Context, containerID string) error {
    70  	containerID, err := c.FormatContainerID(ctx, containerID)
    71  	if err != nil {
    72  		return err
    73  	}
    74  
    75  	container, err := c.client.LoadContainer(ctx, containerID)
    76  	if err != nil {
    77  		return err
    78  	}
    79  	task, err := container.Task(ctx, nil)
    80  	if err != nil {
    81  		return err
    82  	}
    83  
    84  	err = task.Kill(ctx, syscall.SIGKILL)
    85  
    86  	return err
    87  }
    88  
    89  func New(address string, opts ...containerd.ClientOpt) (*ContainerdClient, error) {
    90  	// Mock point to return error in unit test
    91  	if err := mock.On("NewContainerdClientError"); err != nil {
    92  		return nil, err.(error)
    93  	}
    94  	if client := mock.On("MockContainerdClient"); client != nil {
    95  		return &ContainerdClient{
    96  			client.(ContainerdClientInterface),
    97  		}, nil
    98  	}
    99  
   100  	c, err := containerd.New(address, opts...)
   101  	if err != nil {
   102  		return nil, err
   103  	}
   104  	// The real logic
   105  	return &ContainerdClient{
   106  		client: c,
   107  	}, nil
   108  }
   109  
   110  // WithDefaultNamespace is an alias for the function in containerd with the same name
   111  var WithDefaultNamespace = containerd.WithDefaultNamespace
   112