docker-gen/internal/dockerclient/docker_cli.go
2021-09-16 07:51:24 +02:00

140 lines
3.3 KiB
Go

package dockerclient
import (
"errors"
"fmt"
"os"
"strconv"
"strings"
docker "github.com/fsouza/go-dockerclient"
"github.com/nginx-proxy/docker-gen/internal/utils"
)
func GetEndpoint(endpoint string) (string, error) {
defaultEndpoint := "unix:///var/run/docker.sock"
if os.Getenv("DOCKER_HOST") != "" {
defaultEndpoint = os.Getenv("DOCKER_HOST")
}
if endpoint != "" {
defaultEndpoint = endpoint
}
_, _, err := parseHost(defaultEndpoint)
if err != nil {
return "", err
}
return defaultEndpoint, nil
}
func NewDockerClient(endpoint string, tlsVerify bool, tlsCert, tlsCaCert, tlsKey string) (*docker.Client, error) {
if strings.HasPrefix(endpoint, "unix:") {
return docker.NewClient(endpoint)
} else if tlsVerify || tlsEnabled(tlsCert, tlsCaCert, tlsKey) {
if tlsVerify {
if e, err := utils.PathExists(tlsCaCert); !e || err != nil {
return nil, errors.New("TLS verification was requested, but CA cert does not exist")
}
}
return docker.NewTLSClient(endpoint, tlsCert, tlsKey, tlsCaCert)
}
return docker.NewClient(endpoint)
}
func tlsEnabled(tlsCert, tlsCaCert, tlsKey string) bool {
for _, v := range []string{tlsCert, tlsCaCert, tlsKey} {
if e, err := utils.PathExists(v); e && err == nil {
return true
}
}
return false
}
type DockerContainer struct {
}
// based off of https://github.com/dotcloud/docker/blob/2a711d16e05b69328f2636f88f8eac035477f7e4/utils/utils.go
func parseHost(addr string) (string, string, error) {
var (
proto string
host string
port int
)
addr = strings.TrimSpace(addr)
switch {
case addr == "tcp://":
return "", "", fmt.Errorf("invalid bind address format: %s", addr)
case strings.HasPrefix(addr, "unix://"):
proto = "unix"
addr = strings.TrimPrefix(addr, "unix://")
if addr == "" {
addr = "/var/run/docker.sock"
}
case strings.HasPrefix(addr, "tcp://"):
proto = "tcp"
addr = strings.TrimPrefix(addr, "tcp://")
case strings.HasPrefix(addr, "fd://"):
return "fd", addr, nil
case addr == "":
proto = "unix"
addr = "/var/run/docker.sock"
default:
if strings.Contains(addr, "://") {
return "", "", fmt.Errorf("invalid bind address protocol: %s", addr)
}
proto = "tcp"
}
if proto != "unix" && strings.Contains(addr, ":") {
hostParts := strings.Split(addr, ":")
if len(hostParts) != 2 {
return "", "", fmt.Errorf("invalid bind address format: %s", addr)
}
if hostParts[0] != "" {
host = hostParts[0]
} else {
host = "127.0.0.1"
}
if p, err := strconv.Atoi(hostParts[1]); err == nil && p != 0 {
port = p
} else {
return "", "", fmt.Errorf("invalid bind address format: %s", addr)
}
} else if proto == "tcp" && !strings.Contains(addr, ":") {
return "", "", fmt.Errorf("invalid bind address format: %s", addr)
} else {
host = addr
}
if proto == "unix" {
return proto, host, nil
}
return proto, fmt.Sprintf("%s:%d", host, port), nil
}
func SplitDockerImage(img string) (string, string, string) {
index := 0
repository := img
var registry, tag string
if strings.Contains(img, "/") {
separator := strings.Index(img, "/")
registry = img[index:separator]
index = separator + 1
repository = img[index:]
}
if strings.Contains(repository, ":") {
separator := strings.Index(repository, ":")
tag = repository[separator+1:]
repository = repository[0:separator]
}
return registry, repository, tag
}