...

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

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

     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 docker
    15  
    16  import (
    17  	"context"
    18  	"fmt"
    19  	"net/http"
    20  
    21  	"github.com/docker/docker/api/types"
    22  	dockerclient "github.com/docker/docker/client"
    23  
    24  	"github.com/chaos-mesh/chaos-mesh/pkg/mock"
    25  )
    26  
    27  const (
    28  	dockerProtocolPrefix = "docker://"
    29  )
    30  
    31  // DockerClientInterface represents the DockerClient, it's used to simply unit test
    32  type DockerClientInterface interface {
    33  	ContainerInspect(ctx context.Context, containerID string) (types.ContainerJSON, error)
    34  	ContainerKill(ctx context.Context, containerID, signal string) error
    35  }
    36  
    37  // DockerClient can get information from docker
    38  type DockerClient struct {
    39  	client DockerClientInterface
    40  }
    41  
    42  // FormatContainerID strips protocol prefix from the container ID
    43  func (c DockerClient) FormatContainerID(ctx context.Context, containerID string) (string, error) {
    44  	if len(containerID) < len(dockerProtocolPrefix) {
    45  		return "", fmt.Errorf("container id %s is not a docker container id", containerID)
    46  	}
    47  	if containerID[0:len(dockerProtocolPrefix)] != dockerProtocolPrefix {
    48  		return "", fmt.Errorf("expected %s but got %s", dockerProtocolPrefix, containerID[0:len(dockerProtocolPrefix)])
    49  	}
    50  	return containerID[len(dockerProtocolPrefix):], nil
    51  }
    52  
    53  // GetPidFromContainerID fetches PID according to container id
    54  func (c DockerClient) GetPidFromContainerID(ctx context.Context, containerID string) (uint32, error) {
    55  	id, err := c.FormatContainerID(ctx, containerID)
    56  	if err != nil {
    57  		return 0, err
    58  	}
    59  	container, err := c.client.ContainerInspect(ctx, id)
    60  	if err != nil {
    61  		return 0, err
    62  	}
    63  
    64  	if container.State.Pid == 0 {
    65  		return 0, fmt.Errorf("container is not running, status: %s", container.State.Status)
    66  	}
    67  
    68  	return uint32(container.State.Pid), nil
    69  }
    70  
    71  // ContainerKillByContainerID kills container according to container id
    72  func (c DockerClient) ContainerKillByContainerID(ctx context.Context, containerID string) error {
    73  	id, err := c.FormatContainerID(ctx, containerID)
    74  	if err != nil {
    75  		return err
    76  	}
    77  	err = c.client.ContainerKill(ctx, id, "SIGKILL")
    78  
    79  	return err
    80  }
    81  
    82  func New(host string, version string, client *http.Client, httpHeaders map[string]string) (*DockerClient, error) {
    83  	// Mock point to return error or mock client in unit test
    84  	if err := mock.On("NewDockerClientError"); err != nil {
    85  		return nil, err.(error)
    86  	}
    87  	if client := mock.On("MockDockerClient"); client != nil {
    88  		return &DockerClient{
    89  			client: client.(DockerClientInterface),
    90  		}, nil
    91  	}
    92  
    93  	c, err := dockerclient.NewClientWithOpts(
    94  		dockerclient.WithHost(host),
    95  		dockerclient.WithVersion(version),
    96  		dockerclient.WithHTTPClient(client),
    97  		dockerclient.WithHTTPHeaders(httpHeaders))
    98  	if err != nil {
    99  		return nil, err
   100  	}
   101  	// The real logic
   102  	return &DockerClient{
   103  		client: c,
   104  	}, nil
   105  }
   106