github.com/alloyci/alloy-runner@v1.0.1-0.20180222164613-925503ccafd6/helpers/docker/official_docker_client.go (about)

     1  package docker_helpers
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"io/ioutil"
     7  	"net/http"
     8  	"path/filepath"
     9  
    10  	"github.com/Sirupsen/logrus"
    11  	"github.com/docker/docker/api/types"
    12  	"github.com/docker/docker/client"
    13  	"github.com/docker/go-connections/tlsconfig"
    14  	"golang.org/x/net/context"
    15  )
    16  
    17  // IsErrNotFound checks whether a returned error is due to an image or container
    18  // not being found. Proxies the docker implementation.
    19  func IsErrNotFound(err error) bool {
    20  	return client.IsErrNotFound(err)
    21  }
    22  
    23  // type officialDockerClient wraps a "github.com/docker/docker/client".Client,
    24  // giving it the methods it needs to satisfy the docker_helpers.Client interface
    25  type officialDockerClient struct {
    26  	*client.Client
    27  
    28  	// Close() means "close idle connections held by engine-api's transport"
    29  	Transport *http.Transport
    30  }
    31  
    32  func newOfficialDockerClient(c DockerCredentials, apiVersion string) (*officialDockerClient, error) {
    33  	transport, err := newHTTPTransport(c)
    34  	if err != nil {
    35  		logrus.Errorln("Error creating TLS Docker client:", err)
    36  		return nil, err
    37  	}
    38  	httpClient := &http.Client{Transport: transport}
    39  
    40  	dockerClient, err := client.NewClient(c.Host, apiVersion, httpClient, nil)
    41  	if err != nil {
    42  		transport.CloseIdleConnections()
    43  		logrus.Errorln("Error creating Docker client:", err)
    44  		return nil, err
    45  	}
    46  
    47  	return &officialDockerClient{
    48  		Client:    dockerClient,
    49  		Transport: transport,
    50  	}, nil
    51  }
    52  
    53  func (c *officialDockerClient) ImageImportBlocking(ctx context.Context, source types.ImageImportSource, ref string, options types.ImageImportOptions) error {
    54  	readCloser, err := c.ImageImport(ctx, source, ref, options)
    55  	if err != nil {
    56  		return err
    57  	}
    58  	defer readCloser.Close()
    59  
    60  	// TODO: respect the context here
    61  	if _, err := io.Copy(ioutil.Discard, readCloser); err != nil {
    62  		return fmt.Errorf("Failed to import image: %s", err)
    63  	}
    64  
    65  	return nil
    66  }
    67  
    68  func (c *officialDockerClient) ImagePullBlocking(ctx context.Context, ref string, options types.ImagePullOptions) error {
    69  	readCloser, err := c.ImagePull(ctx, ref, options)
    70  	if err != nil {
    71  		return err
    72  	}
    73  	defer readCloser.Close()
    74  
    75  	// TODO: respect the context here
    76  	if _, err := io.Copy(ioutil.Discard, readCloser); err != nil {
    77  		return fmt.Errorf("Failed to pull image: %s: %s", ref, err)
    78  	}
    79  
    80  	return nil
    81  }
    82  
    83  func (c *officialDockerClient) Close() error {
    84  	c.Transport.CloseIdleConnections()
    85  	return nil
    86  }
    87  
    88  // New attempts to create a new Docker client of the specified version.
    89  //
    90  // If no host is given in the DockerCredentials, it will attempt to look up
    91  // details from the environment. If that fails, it will use the default
    92  // connection details for your platform.
    93  func New(c DockerCredentials, apiVersion string) (Client, error) {
    94  	if c.Host == "" {
    95  		c = credentialsFromEnv()
    96  	}
    97  
    98  	// Use the default if nothing is specified by caller *or* environment
    99  	if c.Host == "" {
   100  		c.Host = client.DefaultDockerHost
   101  	}
   102  
   103  	return newOfficialDockerClient(c, apiVersion)
   104  }
   105  
   106  func newHTTPTransport(c DockerCredentials) (*http.Transport, error) {
   107  	proto, addr, _, err := client.ParseHost(c.Host)
   108  	if err != nil {
   109  		return nil, err
   110  	}
   111  
   112  	tr := &http.Transport{}
   113  
   114  	if err := configureTransport(tr, proto, addr); err != nil {
   115  		return nil, err
   116  	}
   117  
   118  	// FIXME: is a TLS connection with InsecureSkipVerify == true ever wanted?
   119  	if c.TLSVerify {
   120  		options := tlsconfig.Options{}
   121  
   122  		if c.CertPath != "" {
   123  			options.CAFile = filepath.Join(c.CertPath, "ca.pem")
   124  			options.CertFile = filepath.Join(c.CertPath, "cert.pem")
   125  			options.KeyFile = filepath.Join(c.CertPath, "key.pem")
   126  		}
   127  
   128  		tlsConfig, err := tlsconfig.Client(options)
   129  		if err != nil {
   130  			tr.CloseIdleConnections()
   131  			return nil, err
   132  		}
   133  
   134  		tr.TLSClientConfig = tlsConfig
   135  	}
   136  
   137  	return tr, nil
   138  }