123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- package client
- import (
- "context"
- "net"
- "net/http"
- "os"
- "path/filepath"
- "time"
- "github.com/docker/go-connections/sockets"
- "github.com/docker/go-connections/tlsconfig"
- "github.com/pkg/errors"
- )
- // Opt is a configuration option to initialize a client
- type Opt func(*Client) error
- // FromEnv configures the client with values from environment variables.
- //
- // Supported environment variables:
- // DOCKER_HOST to set the url to the docker server.
- // DOCKER_API_VERSION to set the version of the API to reach, leave empty for latest.
- // DOCKER_CERT_PATH to load the TLS certificates from.
- // DOCKER_TLS_VERIFY to enable or disable TLS verification, off by default.
- func FromEnv(c *Client) error {
- if dockerCertPath := os.Getenv("DOCKER_CERT_PATH"); dockerCertPath != "" {
- options := tlsconfig.Options{
- CAFile: filepath.Join(dockerCertPath, "ca.pem"),
- CertFile: filepath.Join(dockerCertPath, "cert.pem"),
- KeyFile: filepath.Join(dockerCertPath, "key.pem"),
- InsecureSkipVerify: os.Getenv("DOCKER_TLS_VERIFY") == "",
- }
- tlsc, err := tlsconfig.Client(options)
- if err != nil {
- return err
- }
- c.client = &http.Client{
- Transport: &http.Transport{TLSClientConfig: tlsc},
- CheckRedirect: CheckRedirect,
- }
- }
- if host := os.Getenv("DOCKER_HOST"); host != "" {
- if err := WithHost(host)(c); err != nil {
- return err
- }
- }
- if version := os.Getenv("DOCKER_API_VERSION"); version != "" {
- if err := WithVersion(version)(c); err != nil {
- return err
- }
- }
- return nil
- }
- // WithDialer applies the dialer.DialContext to the client transport. This can be
- // used to set the Timeout and KeepAlive settings of the client.
- // Deprecated: use WithDialContext
- func WithDialer(dialer *net.Dialer) Opt {
- return WithDialContext(dialer.DialContext)
- }
- // WithDialContext applies the dialer to the client transport. This can be
- // used to set the Timeout and KeepAlive settings of the client.
- func WithDialContext(dialContext func(ctx context.Context, network, addr string) (net.Conn, error)) Opt {
- return func(c *Client) error {
- if transport, ok := c.client.Transport.(*http.Transport); ok {
- transport.DialContext = dialContext
- return nil
- }
- return errors.Errorf("cannot apply dialer to transport: %T", c.client.Transport)
- }
- }
- // WithHost overrides the client host with the specified one.
- func WithHost(host string) Opt {
- return func(c *Client) error {
- hostURL, err := ParseHostURL(host)
- if err != nil {
- return err
- }
- c.host = host
- c.proto = hostURL.Scheme
- c.addr = hostURL.Host
- c.basePath = hostURL.Path
- if transport, ok := c.client.Transport.(*http.Transport); ok {
- return sockets.ConfigureTransport(transport, c.proto, c.addr)
- }
- return errors.Errorf("cannot apply host to transport: %T", c.client.Transport)
- }
- }
- // WithHTTPClient overrides the client http client with the specified one
- func WithHTTPClient(client *http.Client) Opt {
- return func(c *Client) error {
- if client != nil {
- c.client = client
- }
- return nil
- }
- }
- // WithTimeout configures the time limit for requests made by the HTTP client
- func WithTimeout(timeout time.Duration) Opt {
- return func(c *Client) error {
- c.client.Timeout = timeout
- return nil
- }
- }
- // WithHTTPHeaders overrides the client default http headers
- func WithHTTPHeaders(headers map[string]string) Opt {
- return func(c *Client) error {
- c.customHTTPHeaders = headers
- return nil
- }
- }
- // WithScheme overrides the client scheme with the specified one
- func WithScheme(scheme string) Opt {
- return func(c *Client) error {
- c.scheme = scheme
- return nil
- }
- }
- // WithTLSClientConfig applies a tls config to the client transport.
- func WithTLSClientConfig(cacertPath, certPath, keyPath string) Opt {
- return func(c *Client) error {
- opts := tlsconfig.Options{
- CAFile: cacertPath,
- CertFile: certPath,
- KeyFile: keyPath,
- ExclusiveRootPools: true,
- }
- config, err := tlsconfig.Client(opts)
- if err != nil {
- return errors.Wrap(err, "failed to create tls config")
- }
- if transport, ok := c.client.Transport.(*http.Transport); ok {
- transport.TLSClientConfig = config
- return nil
- }
- return errors.Errorf("cannot apply tls config to transport: %T", c.client.Transport)
- }
- }
- // WithVersion overrides the client version with the specified one. If an empty
- // version is specified, the value will be ignored to allow version negotiation.
- func WithVersion(version string) Opt {
- return func(c *Client) error {
- if version != "" {
- c.version = version
- c.manualOverride = true
- }
- return nil
- }
- }
- // WithAPIVersionNegotiation enables automatic API version negotiation for the client.
- // With this option enabled, the client automatically negotiates the API version
- // to use when making requests. API version negotiation is performed on the first
- // request; subsequent requests will not re-negotiate.
- func WithAPIVersionNegotiation() Opt {
- return func(c *Client) error {
- c.negotiateVersion = true
- return nil
- }
- }
|