bitbucket.org/Aishee/synsec@v0.0.0-20210414005726-236fc01a153d/pkg/metabase/container.go (about)

     1  package metabase
     2  
     3  import (
     4  	"bufio"
     5  	"context"
     6  	"fmt"
     7  	"runtime"
     8  	"time"
     9  
    10  	"github.com/docker/docker/api/types"
    11  	"github.com/docker/docker/api/types/container"
    12  	"github.com/docker/docker/api/types/mount"
    13  	"github.com/docker/docker/client"
    14  	"github.com/docker/go-connections/nat"
    15  	log "github.com/sirupsen/logrus"
    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, name 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:          name,
    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  	os := runtime.GOOS
    96  	switch os {
    97  	case "linux":
    98  	case "windows", "darwin":
    99  		return fmt.Errorf("Mac and Windows are not supported yet")
   100  	default:
   101  		return fmt.Errorf("OS '%s' is not supported", os)
   102  	}
   103  
   104  	log.Infof("creating container '%s'", c.Name)
   105  	resp, err := c.CLI.ContainerCreate(ctx, dockerConfig, hostConfig, nil, nil, c.Name)
   106  	if err != nil {
   107  		return fmt.Errorf("failed to create container : %s", err)
   108  	}
   109  	c.ID = resp.ID
   110  
   111  	return nil
   112  }
   113  
   114  func (c *Container) Start() error {
   115  	ctx := context.Background()
   116  	if err := c.CLI.ContainerStart(ctx, c.Name, types.ContainerStartOptions{}); err != nil {
   117  		return fmt.Errorf("failed while starting %s : %s", c.ID, err)
   118  	}
   119  
   120  	return nil
   121  }
   122  
   123  func StartContainer(name string) error {
   124  	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
   125  	if err != nil {
   126  		return fmt.Errorf("failed to create docker client : %s", err)
   127  	}
   128  	ctx := context.Background()
   129  	if err := cli.ContainerStart(ctx, name, types.ContainerStartOptions{}); err != nil {
   130  		return fmt.Errorf("failed while starting %s : %s", name, err)
   131  	}
   132  
   133  	return nil
   134  }
   135  
   136  func StopContainer(name string) error {
   137  	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
   138  	if err != nil {
   139  		return fmt.Errorf("failed to create docker client : %s", err)
   140  	}
   141  	ctx := context.Background()
   142  	var to time.Duration = 20 * time.Second
   143  	if err := cli.ContainerStop(ctx, name, &to); err != nil {
   144  		return fmt.Errorf("failed while stopping %s : %s", name, err)
   145  	}
   146  	log.Printf("container stopped successfully")
   147  	return nil
   148  }
   149  
   150  func RemoveContainer(name string) error {
   151  	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
   152  	if err != nil {
   153  		return fmt.Errorf("failed to create docker client : %s", err)
   154  	}
   155  	ctx := context.Background()
   156  	log.Printf("Removing docker metabase %s", name)
   157  	if err := cli.ContainerRemove(ctx, name, types.ContainerRemoveOptions{}); err != nil {
   158  		return fmt.Errorf("failed remove container %s : %s", name, err)
   159  	}
   160  	return nil
   161  }
   162  
   163  func RemoveImageContainer() error {
   164  	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
   165  	if err != nil {
   166  		return fmt.Errorf("failed to create docker client : %s", err)
   167  	}
   168  	ctx := context.Background()
   169  	log.Printf("Removing docker image '%s'", metabaseImage)
   170  	if _, err := cli.ImageRemove(ctx, metabaseImage, types.ImageRemoveOptions{}); err != nil {
   171  		return fmt.Errorf("failed remove image container %s : %s", metabaseImage, err)
   172  	}
   173  	return nil
   174  }
   175  
   176  func IsContainerExist(name string) bool {
   177  	cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
   178  	if err != nil {
   179  		log.Fatalf("failed to create docker client : %s", err)
   180  	}
   181  	ctx := context.Background()
   182  	if _, err := cli.ContainerInspect(ctx, name); err != nil {
   183  		return false
   184  	}
   185  	return true
   186  }