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 }