github.com/crowdsecurity/crowdsec@v1.6.1/pkg/metabase/container.go (about)

     1  package metabase
     2  
     3  import (
     4  	"bufio"
     5  	"context"
     6  	"fmt"
     7  
     8  	"github.com/docker/docker/api/types"
     9  	"github.com/docker/docker/api/types/container"
    10  	"github.com/docker/docker/api/types/mount"
    11  	"github.com/docker/docker/client"
    12  	"github.com/docker/go-connections/nat"
    13  	log "github.com/sirupsen/logrus"
    14  
    15  	"github.com/crowdsecurity/go-cs-lib/ptr"
    16  )
    17  
    18  type Container struct {
    19  	ListenAddr    string
    20  	ListenPort    string
    21  	SharedFolder  string
    22  	Image         string
    23  	Name          string
    24  	ID            string
    25  	CLI           *client.Client
    26  	MBDBUri       string
    27  	DockerGroupID string
    28  }
    29  
    30  func NewContainer(listenAddr string, listenPort string, sharedFolder string, containerName string, image string, mbDBURI string, dockerGroupID string) (*Container, error) {
    31  	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
    32  	if err != nil {
    33  		return nil, fmt.Errorf("failed to create docker client : %s", err)
    34  	}
    35  	return &Container{
    36  		ListenAddr:    listenAddr,
    37  		ListenPort:    listenPort,
    38  		SharedFolder:  sharedFolder,
    39  		Image:         image,
    40  		Name:          containerName,
    41  		CLI:           cli,
    42  		MBDBUri:       mbDBURI,
    43  		DockerGroupID: dockerGroupID,
    44  	}, nil
    45  }
    46  
    47  func (c *Container) Create() error {
    48  	ctx := context.Background()
    49  	log.Printf("Pulling docker image %s", c.Image)
    50  	reader, err := c.CLI.ImagePull(ctx, c.Image, types.ImagePullOptions{})
    51  	if err != nil {
    52  		return fmt.Errorf("failed to pull docker image : %s", err)
    53  	}
    54  	defer reader.Close()
    55  	scanner := bufio.NewScanner(reader)
    56  	for scanner.Scan() {
    57  		fmt.Print(".")
    58  	}
    59  	if err := scanner.Err(); err != nil {
    60  		return fmt.Errorf("failed to read imagepull reader: %s", err)
    61  	}
    62  	fmt.Print("\n")
    63  
    64  	hostConfig := &container.HostConfig{
    65  		PortBindings: nat.PortMap{
    66  			"3000/tcp": []nat.PortBinding{
    67  				{
    68  					HostIP:   c.ListenAddr,
    69  					HostPort: c.ListenPort,
    70  				},
    71  			},
    72  		},
    73  		Mounts: []mount.Mount{
    74  			{
    75  				Type:   mount.TypeBind,
    76  				Source: c.SharedFolder,
    77  				Target: containerSharedFolder,
    78  			},
    79  		},
    80  	}
    81  
    82  	env := []string{
    83  		fmt.Sprintf("MB_DB_FILE=%s/metabase.db", containerSharedFolder),
    84  	}
    85  	if c.MBDBUri != "" {
    86  		env = append(env, c.MBDBUri)
    87  	}
    88  
    89  	env = append(env, fmt.Sprintf("MGID=%s", c.DockerGroupID))
    90  	dockerConfig := &container.Config{
    91  		Image: c.Image,
    92  		Tty:   true,
    93  		Env:   env,
    94  	}
    95  
    96  	log.Infof("creating container '%s'", c.Name)
    97  	resp, err := c.CLI.ContainerCreate(ctx, dockerConfig, hostConfig, nil, nil, c.Name)
    98  	if err != nil {
    99  		return fmt.Errorf("failed to create container : %s", err)
   100  	}
   101  	c.ID = resp.ID
   102  
   103  	return nil
   104  }
   105  
   106  func (c *Container) Start() error {
   107  	ctx := context.Background()
   108  	if err := c.CLI.ContainerStart(ctx, c.Name, types.ContainerStartOptions{}); err != nil {
   109  		return fmt.Errorf("failed while starting %s : %s", c.ID, err)
   110  	}
   111  
   112  	return nil
   113  }
   114  
   115  func StartContainer(name string) error {
   116  	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
   117  	if err != nil {
   118  		return fmt.Errorf("failed to create docker client : %s", err)
   119  	}
   120  	ctx := context.Background()
   121  	if err := cli.ContainerStart(ctx, name, types.ContainerStartOptions{}); err != nil {
   122  		return fmt.Errorf("failed while starting %s : %s", name, err)
   123  	}
   124  
   125  	return nil
   126  }
   127  
   128  func StopContainer(name string) error {
   129  	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
   130  	if err != nil {
   131  		return fmt.Errorf("failed to create docker client : %s", err)
   132  	}
   133  	ctx := context.Background()
   134  	to := container.StopOptions{Timeout: ptr.Of(20)}
   135  	if err := cli.ContainerStop(ctx, name, to); err != nil {
   136  		return fmt.Errorf("failed while stopping %s : %s", name, err)
   137  	}
   138  	log.Printf("container stopped successfully")
   139  	return nil
   140  }
   141  
   142  func RemoveContainer(name string) error {
   143  	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
   144  	if err != nil {
   145  		return fmt.Errorf("failed to create docker client : %s", err)
   146  	}
   147  	ctx := context.Background()
   148  	log.Printf("Removing docker metabase %s", name)
   149  	if err := cli.ContainerRemove(ctx, name, types.ContainerRemoveOptions{}); err != nil {
   150  		return fmt.Errorf("failed to remove container %s : %s", name, err)
   151  	}
   152  	return nil
   153  }
   154  
   155  func RemoveImageContainer(image string) error {
   156  	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
   157  	if err != nil {
   158  		return fmt.Errorf("failed to create docker client : %s", err)
   159  	}
   160  	ctx := context.Background()
   161  	log.Printf("Removing docker image '%s'", image)
   162  	if _, err := cli.ImageRemove(ctx, image, types.ImageRemoveOptions{}); err != nil {
   163  		return fmt.Errorf("failed to remove image container %s : %s", image, err)
   164  	}
   165  	return nil
   166  }
   167  
   168  func IsContainerExist(name string) bool {
   169  	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
   170  	if err != nil {
   171  		log.Fatalf("failed to create docker client : %s", err)
   172  	}
   173  	ctx := context.Background()
   174  	if _, err := cli.ContainerInspect(ctx, name); err != nil {
   175  		return false
   176  	}
   177  	return true
   178  }