github.com/emc-advanced-dev/unik@v0.0.0-20190717152701-a58d3e8e33b7/pkg/util/container.go (about) 1 // +build !container-binary 2 3 package util 4 5 import ( 6 "encoding/json" 7 "fmt" 8 "os" 9 "os/exec" 10 "runtime" 11 "strings" 12 13 "github.com/sirupsen/logrus" 14 "github.com/emc-advanced-dev/pkg/errors" 15 "github.com/solo-io/unik/containers" 16 "github.com/pborman/uuid" 17 ) 18 19 var containerVersions map[string]string 20 21 func InitContainers() error { 22 versionData, err := versiondata.Asset("containers/versions.json") 23 if err != nil { 24 return errors.New("failed to get version data from containers/versions.json", err) 25 } 26 if err := json.Unmarshal(versionData, &containerVersions); err != nil { 27 return errors.New("failed to unmarshall version data "+string(versionData), err) 28 } 29 logrus.WithField("versions", containerVersions).Info("using container versions") 30 return nil 31 } 32 33 type Container struct { 34 env map[string]string 35 privileged bool 36 volumes map[string]string 37 interactive bool 38 network string 39 containerName string 40 name string 41 entrypoint string 42 } 43 44 func NewContainer(imageName string) *Container { 45 c := &Container{} 46 47 c.name = imageName 48 c.env = make(map[string]string) 49 c.volumes = make(map[string]string) 50 51 return c 52 } 53 54 func (c *Container) WithEntrypoint(entrypoint string) *Container { 55 c.entrypoint = entrypoint 56 return c 57 } 58 59 func (c *Container) WithVolume(hostdir, containerdir string) *Container { 60 c.volumes[hostdir] = containerdir 61 return c 62 } 63 64 func (c *Container) WithVolumes(vols map[string]string) *Container { 65 for k, v := range vols { 66 c.WithVolume(k, v) 67 } 68 return c 69 } 70 71 func (c *Container) WithEnv(key, value string) *Container { 72 c.env[key] = value 73 return c 74 } 75 76 func (c *Container) WithEnvs(vars map[string]string) *Container { 77 for k, v := range vars { 78 c.WithEnv(k, v) 79 } 80 return c 81 } 82 83 func (c *Container) WithNet(net string) *Container { 84 c.network = net 85 return c 86 } 87 88 func (c *Container) WithName(name string) *Container { 89 c.containerName = name 90 return c 91 } 92 93 func (c *Container) Interactive(i bool) *Container { 94 c.interactive = i 95 return c 96 } 97 98 func (c *Container) Privileged(p bool) *Container { 99 c.privileged = p 100 return c 101 } 102 103 func (c *Container) Run(arguments ...string) error { 104 cmd := c.BuildCmd(arguments...) 105 106 LogCommand(cmd, true) 107 108 return cmd.Run() 109 } 110 111 func (c *Container) Output(arguments ...string) ([]byte, error) { 112 return c.BuildCmd(arguments...).Output() 113 } 114 115 func (c *Container) CombinedOutput(arguments ...string) ([]byte, error) { 116 return c.BuildCmd(arguments...).CombinedOutput() 117 } 118 119 func (c *Container) Stop() error { 120 return exec.Command("docker", "stop", c.containerName).Run() 121 } 122 123 func (c *Container) BuildCmd(arguments ...string) *exec.Cmd { 124 if c.containerName == "" { 125 c.containerName = uuid.New() 126 } 127 128 args := []string{"run", "--rm"} 129 if c.privileged { 130 args = append(args, "--privileged") 131 } 132 if c.interactive { 133 args = append(args, "-i") 134 } 135 if c.network != "" { 136 args = append(args, fmt.Sprintf("--net=%s", c.network)) 137 } 138 for key, val := range c.env { 139 args = append(args, "-e", fmt.Sprintf("%s=%s", key, val)) 140 } 141 for key, val := range c.volumes { 142 if IsDockerToolbox() { 143 key = GetToolboxMountPath(key) 144 } 145 args = append(args, "-v", fmt.Sprintf("%s:%s", key, val)) 146 } 147 148 if c.entrypoint != "" { 149 args = append(args, "--entrypoint", c.entrypoint) 150 } 151 152 args = append(args, fmt.Sprintf("--name=%s", c.containerName)) 153 154 containerVer, ok := containerVersions[c.name] 155 if !ok { 156 logrus.Warnf("version for container %s not found, using version 'latest'", c.name) 157 containerVer = "latest" 158 } 159 160 finalName := c.name + ":" + containerVer 161 if !strings.Contains(finalName, "/") { /*projectunik container*/ 162 finalName = "projectunik/" + finalName 163 } 164 165 args = append(args, finalName) 166 args = append(args, arguments...) 167 168 logrus.WithField("args", args).Info("Build cmd for container ", finalName) 169 170 cmd := exec.Command("docker", args...) 171 172 return cmd 173 } 174 175 func IsDockerToolbox() bool { 176 return runtime.GOOS == "windows" && os.Getenv("DOCKER_TOOLBOX_INSTALL_PATH") != "" 177 } 178 179 func GetToolboxMountPath(path string) string { 180 path = strings.Replace(path, "\\", "/", -1) 181 if len(path) >= 2 && path[1] == ':' { 182 path = "/" + strings.ToLower(string(path[0])) + path[2:] 183 } 184 return path 185 }