github.com/docker/docker@v299999999.0.0-20200612211812-aaf470eca7b5+incompatible/client/options.go (about)

     1  package client
     2  
     3  import (
     4  	"context"
     5  	"net"
     6  	"net/http"
     7  	"os"
     8  	"path/filepath"
     9  	"time"
    10  
    11  	"github.com/docker/go-connections/sockets"
    12  	"github.com/docker/go-connections/tlsconfig"
    13  	"github.com/pkg/errors"
    14  )
    15  
    16  // Opt is a configuration option to initialize a client
    17  type Opt func(*Client) error
    18  
    19  // FromEnv configures the client with values from environment variables.
    20  //
    21  // Supported environment variables:
    22  // DOCKER_HOST to set the url to the docker server.
    23  // DOCKER_API_VERSION to set the version of the API to reach, leave empty for latest.
    24  // DOCKER_CERT_PATH to load the TLS certificates from.
    25  // DOCKER_TLS_VERIFY to enable or disable TLS verification, off by default.
    26  func FromEnv(c *Client) error {
    27  	if dockerCertPath := os.Getenv("DOCKER_CERT_PATH"); dockerCertPath != "" {
    28  		options := tlsconfig.Options{
    29  			CAFile:             filepath.Join(dockerCertPath, "ca.pem"),
    30  			CertFile:           filepath.Join(dockerCertPath, "cert.pem"),
    31  			KeyFile:            filepath.Join(dockerCertPath, "key.pem"),
    32  			InsecureSkipVerify: os.Getenv("DOCKER_TLS_VERIFY") == "",
    33  		}
    34  		tlsc, err := tlsconfig.Client(options)
    35  		if err != nil {
    36  			return err
    37  		}
    38  
    39  		c.client = &http.Client{
    40  			Transport:     &http.Transport{TLSClientConfig: tlsc},
    41  			CheckRedirect: CheckRedirect,
    42  		}
    43  	}
    44  
    45  	if host := os.Getenv("DOCKER_HOST"); host != "" {
    46  		if err := WithHost(host)(c); err != nil {
    47  			return err
    48  		}
    49  	}
    50  
    51  	if version := os.Getenv("DOCKER_API_VERSION"); version != "" {
    52  		if err := WithVersion(version)(c); err != nil {
    53  			return err
    54  		}
    55  	}
    56  	return nil
    57  }
    58  
    59  // WithDialer applies the dialer.DialContext to the client transport. This can be
    60  // used to set the Timeout and KeepAlive settings of the client.
    61  // Deprecated: use WithDialContext
    62  func WithDialer(dialer *net.Dialer) Opt {
    63  	return WithDialContext(dialer.DialContext)
    64  }
    65  
    66  // WithDialContext applies the dialer to the client transport. This can be
    67  // used to set the Timeout and KeepAlive settings of the client.
    68  func WithDialContext(dialContext func(ctx context.Context, network, addr string) (net.Conn, error)) Opt {
    69  	return func(c *Client) error {
    70  		if transport, ok := c.client.Transport.(*http.Transport); ok {
    71  			transport.DialContext = dialContext
    72  			return nil
    73  		}
    74  		return errors.Errorf("cannot apply dialer to transport: %T", c.client.Transport)
    75  	}
    76  }
    77  
    78  // WithHost overrides the client host with the specified one.
    79  func WithHost(host string) Opt {
    80  	return func(c *Client) error {
    81  		hostURL, err := ParseHostURL(host)
    82  		if err != nil {
    83  			return err
    84  		}
    85  		c.host = host
    86  		c.proto = hostURL.Scheme
    87  		c.addr = hostURL.Host
    88  		c.basePath = hostURL.Path
    89  		if transport, ok := c.client.Transport.(*http.Transport); ok {
    90  			return sockets.ConfigureTransport(transport, c.proto, c.addr)
    91  		}
    92  		return errors.Errorf("cannot apply host to transport: %T", c.client.Transport)
    93  	}
    94  }
    95  
    96  // WithHTTPClient overrides the client http client with the specified one
    97  func WithHTTPClient(client *http.Client) Opt {
    98  	return func(c *Client) error {
    99  		if client != nil {
   100  			c.client = client
   101  		}
   102  		return nil
   103  	}
   104  }
   105  
   106  // WithTimeout configures the time limit for requests made by the HTTP client
   107  func WithTimeout(timeout time.Duration) Opt {
   108  	return func(c *Client) error {
   109  		c.client.Timeout = timeout
   110  		return nil
   111  	}
   112  }
   113  
   114  // WithHTTPHeaders overrides the client default http headers
   115  func WithHTTPHeaders(headers map[string]string) Opt {
   116  	return func(c *Client) error {
   117  		c.customHTTPHeaders = headers
   118  		return nil
   119  	}
   120  }
   121  
   122  // WithScheme overrides the client scheme with the specified one
   123  func WithScheme(scheme string) Opt {
   124  	return func(c *Client) error {
   125  		c.scheme = scheme
   126  		return nil
   127  	}
   128  }
   129  
   130  // WithTLSClientConfig applies a tls config to the client transport.
   131  func WithTLSClientConfig(cacertPath, certPath, keyPath string) Opt {
   132  	return func(c *Client) error {
   133  		opts := tlsconfig.Options{
   134  			CAFile:             cacertPath,
   135  			CertFile:           certPath,
   136  			KeyFile:            keyPath,
   137  			ExclusiveRootPools: true,
   138  		}
   139  		config, err := tlsconfig.Client(opts)
   140  		if err != nil {
   141  			return errors.Wrap(err, "failed to create tls config")
   142  		}
   143  		if transport, ok := c.client.Transport.(*http.Transport); ok {
   144  			transport.TLSClientConfig = config
   145  			return nil
   146  		}
   147  		return errors.Errorf("cannot apply tls config to transport: %T", c.client.Transport)
   148  	}
   149  }
   150  
   151  // WithVersion overrides the client version with the specified one. If an empty
   152  // version is specified, the value will be ignored to allow version negotiation.
   153  func WithVersion(version string) Opt {
   154  	return func(c *Client) error {
   155  		if version != "" {
   156  			c.version = version
   157  			c.manualOverride = true
   158  		}
   159  		return nil
   160  	}
   161  }
   162  
   163  // WithAPIVersionNegotiation enables automatic API version negotiation for the client.
   164  // With this option enabled, the client automatically negotiates the API version
   165  // to use when making requests. API version negotiation is performed on the first
   166  // request; subsequent requests will not re-negotiate.
   167  func WithAPIVersionNegotiation() Opt {
   168  	return func(c *Client) error {
   169  		c.negotiateVersion = true
   170  		return nil
   171  	}
   172  }