forked from toolshed/abra
		
	
		
			
				
	
	
		
			119 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			119 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Package client provides Docker client initiatialisation functions.
 | |
| package client
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"errors"
 | |
| 	"net/http"
 | |
| 	"os"
 | |
| 	"path"
 | |
| 	"strings"
 | |
| 	"time"
 | |
| 
 | |
| 	"coopcloud.tech/abra/pkg/config"
 | |
| 	contextPkg "coopcloud.tech/abra/pkg/context"
 | |
| 	"coopcloud.tech/abra/pkg/i18n"
 | |
| 	"coopcloud.tech/abra/pkg/log"
 | |
| 	sshPkg "coopcloud.tech/abra/pkg/ssh"
 | |
| 	commandconnPkg "coopcloud.tech/abra/pkg/upstream/commandconn"
 | |
| 	"github.com/docker/docker/client"
 | |
| )
 | |
| 
 | |
| // Conf is a Docker client configuration.
 | |
| type Conf struct {
 | |
| 	Timeout int
 | |
| }
 | |
| 
 | |
| // Opt is a Docker client option.
 | |
| type Opt func(c *Conf)
 | |
| 
 | |
| // WithTimeout specifies a timeout for a Docker client.
 | |
| func WithTimeout(timeout int) Opt {
 | |
| 	return func(c *Conf) {
 | |
| 		c.Timeout = timeout
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // New initiates a new Docker client. New client connections are validated so
 | |
| // that we ensure connections via SSH to the daemon can succeed. It takes into
 | |
| // account that you may only want the local client and not communicate via SSH.
 | |
| // For this use-case, please pass "default" as the contextName.
 | |
| func New(serverName string, opts ...Opt) (*client.Client, error) {
 | |
| 	var clientOpts []client.Opt
 | |
| 
 | |
| 	ctx, err := GetContext(serverName)
 | |
| 	if err != nil {
 | |
| 		serverDir := path.Join(config.SERVERS_DIR, serverName)
 | |
| 		if _, err := os.Stat(serverDir); err == nil {
 | |
| 			return nil, errors.New(i18n.G("server missing context, run \"abra server add %s\"?", serverName))
 | |
| 		}
 | |
| 
 | |
| 		return nil, errors.New(i18n.G("unknown server, run \"abra server add %s\"?", serverName))
 | |
| 	}
 | |
| 
 | |
| 	ctxEndpoint, err := contextPkg.GetContextEndpoint(ctx)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	var isUnix bool
 | |
| 	if strings.Contains(ctxEndpoint, "unix://") {
 | |
| 		isUnix = true
 | |
| 	}
 | |
| 
 | |
| 	if serverName != "default" && !isUnix {
 | |
| 		conf := &Conf{}
 | |
| 
 | |
| 		for _, opt := range opts {
 | |
| 			opt(conf)
 | |
| 		}
 | |
| 
 | |
| 		helper, err := commandconnPkg.NewConnectionHelper(ctxEndpoint, conf.Timeout)
 | |
| 		if err != nil {
 | |
| 			return nil, err
 | |
| 		}
 | |
| 
 | |
| 		httpClient := &http.Client{
 | |
| 			Transport: &http.Transport{
 | |
| 				DialContext:     helper.Dialer,
 | |
| 				IdleConnTimeout: 30 * time.Second,
 | |
| 			},
 | |
| 		}
 | |
| 
 | |
| 		clientOpts = append(clientOpts,
 | |
| 			client.WithHTTPClient(httpClient),
 | |
| 			client.WithHost(helper.Host),
 | |
| 			client.WithDialContext(helper.Dialer),
 | |
| 		)
 | |
| 	}
 | |
| 
 | |
| 	version := os.Getenv("DOCKER_API_VERSION")
 | |
| 	if version != "" {
 | |
| 		clientOpts = append(clientOpts, client.WithVersion(version))
 | |
| 	} else {
 | |
| 		clientOpts = append(clientOpts, client.WithAPIVersionNegotiation())
 | |
| 	}
 | |
| 
 | |
| 	cl, err := client.NewClientWithOpts(clientOpts...)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	log.Debug(i18n.G("created client for %s", serverName))
 | |
| 
 | |
| 	info, err := cl.Info(context.Background())
 | |
| 	if err != nil {
 | |
| 		return cl, sshPkg.Fatal(serverName, err)
 | |
| 	}
 | |
| 
 | |
| 	if info.Swarm.LocalNodeState == "inactive" {
 | |
| 		if serverName != "default" && !isUnix {
 | |
| 			return cl, errors.New(i18n.G("swarm mode not enabled on %s?", serverName))
 | |
| 		}
 | |
| 
 | |
| 		return cl, errors.New(i18n.G("swarm mode not enabled on local server?"))
 | |
| 	}
 | |
| 
 | |
| 	return cl, nil
 | |
| }
 |