github.com/adityamillind98/moby@v23.0.0-rc.4+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 // FromEnv uses the following environment variables: 22 // 23 // DOCKER_HOST (EnvOverrideHost) to set the URL to the docker server. 24 // 25 // DOCKER_API_VERSION (EnvOverrideAPIVersion) to set the version of the API to 26 // use, leave empty for latest. 27 // 28 // DOCKER_CERT_PATH (EnvOverrideCertPath) to specify the directory from which to 29 // load the TLS certificates (ca.pem, cert.pem, key.pem). 30 // 31 // DOCKER_TLS_VERIFY (EnvTLSVerify) to enable or disable TLS verification (off by 32 // default). 33 func FromEnv(c *Client) error { 34 ops := []Opt{ 35 WithTLSClientConfigFromEnv(), 36 WithHostFromEnv(), 37 WithVersionFromEnv(), 38 } 39 for _, op := range ops { 40 if err := op(c); err != nil { 41 return err 42 } 43 } 44 return nil 45 } 46 47 // WithDialContext applies the dialer to the client transport. This can be 48 // used to set the Timeout and KeepAlive settings of the client. 49 func WithDialContext(dialContext func(ctx context.Context, network, addr string) (net.Conn, error)) Opt { 50 return func(c *Client) error { 51 if transport, ok := c.client.Transport.(*http.Transport); ok { 52 transport.DialContext = dialContext 53 return nil 54 } 55 return errors.Errorf("cannot apply dialer to transport: %T", c.client.Transport) 56 } 57 } 58 59 // WithHost overrides the client host with the specified one. 60 func WithHost(host string) Opt { 61 return func(c *Client) error { 62 hostURL, err := ParseHostURL(host) 63 if err != nil { 64 return err 65 } 66 c.host = host 67 c.proto = hostURL.Scheme 68 c.addr = hostURL.Host 69 c.basePath = hostURL.Path 70 if transport, ok := c.client.Transport.(*http.Transport); ok { 71 return sockets.ConfigureTransport(transport, c.proto, c.addr) 72 } 73 return errors.Errorf("cannot apply host to transport: %T", c.client.Transport) 74 } 75 } 76 77 // WithHostFromEnv overrides the client host with the host specified in the 78 // DOCKER_HOST (EnvOverrideHost) environment variable. If DOCKER_HOST is not set, 79 // or set to an empty value, the host is not modified. 80 func WithHostFromEnv() Opt { 81 return func(c *Client) error { 82 if host := os.Getenv(EnvOverrideHost); host != "" { 83 return WithHost(host)(c) 84 } 85 return nil 86 } 87 } 88 89 // WithHTTPClient overrides the client http client with the specified one 90 func WithHTTPClient(client *http.Client) Opt { 91 return func(c *Client) error { 92 if client != nil { 93 c.client = client 94 } 95 return nil 96 } 97 } 98 99 // WithTimeout configures the time limit for requests made by the HTTP client 100 func WithTimeout(timeout time.Duration) Opt { 101 return func(c *Client) error { 102 c.client.Timeout = timeout 103 return nil 104 } 105 } 106 107 // WithHTTPHeaders overrides the client default http headers 108 func WithHTTPHeaders(headers map[string]string) Opt { 109 return func(c *Client) error { 110 c.customHTTPHeaders = headers 111 return nil 112 } 113 } 114 115 // WithScheme overrides the client scheme with the specified one 116 func WithScheme(scheme string) Opt { 117 return func(c *Client) error { 118 c.scheme = scheme 119 return nil 120 } 121 } 122 123 // WithTLSClientConfig applies a tls config to the client transport. 124 func WithTLSClientConfig(cacertPath, certPath, keyPath string) Opt { 125 return func(c *Client) error { 126 opts := tlsconfig.Options{ 127 CAFile: cacertPath, 128 CertFile: certPath, 129 KeyFile: keyPath, 130 ExclusiveRootPools: true, 131 } 132 config, err := tlsconfig.Client(opts) 133 if err != nil { 134 return errors.Wrap(err, "failed to create tls config") 135 } 136 if transport, ok := c.client.Transport.(*http.Transport); ok { 137 transport.TLSClientConfig = config 138 return nil 139 } 140 return errors.Errorf("cannot apply tls config to transport: %T", c.client.Transport) 141 } 142 } 143 144 // WithTLSClientConfigFromEnv configures the client's TLS settings with the 145 // settings in the DOCKER_CERT_PATH and DOCKER_TLS_VERIFY environment variables. 146 // If DOCKER_CERT_PATH is not set or empty, TLS configuration is not modified. 147 // 148 // WithTLSClientConfigFromEnv uses the following environment variables: 149 // 150 // DOCKER_CERT_PATH (EnvOverrideCertPath) to specify the directory from which to 151 // load the TLS certificates (ca.pem, cert.pem, key.pem). 152 // 153 // DOCKER_TLS_VERIFY (EnvTLSVerify) to enable or disable TLS verification (off by 154 // default). 155 func WithTLSClientConfigFromEnv() Opt { 156 return func(c *Client) error { 157 dockerCertPath := os.Getenv(EnvOverrideCertPath) 158 if dockerCertPath == "" { 159 return nil 160 } 161 options := tlsconfig.Options{ 162 CAFile: filepath.Join(dockerCertPath, "ca.pem"), 163 CertFile: filepath.Join(dockerCertPath, "cert.pem"), 164 KeyFile: filepath.Join(dockerCertPath, "key.pem"), 165 InsecureSkipVerify: os.Getenv(EnvTLSVerify) == "", 166 } 167 tlsc, err := tlsconfig.Client(options) 168 if err != nil { 169 return err 170 } 171 172 c.client = &http.Client{ 173 Transport: &http.Transport{TLSClientConfig: tlsc}, 174 CheckRedirect: CheckRedirect, 175 } 176 return nil 177 } 178 } 179 180 // WithVersion overrides the client version with the specified one. If an empty 181 // version is specified, the value will be ignored to allow version negotiation. 182 func WithVersion(version string) Opt { 183 return func(c *Client) error { 184 if version != "" { 185 c.version = version 186 c.manualOverride = true 187 } 188 return nil 189 } 190 } 191 192 // WithVersionFromEnv overrides the client version with the version specified in 193 // the DOCKER_API_VERSION environment variable. If DOCKER_API_VERSION is not set, 194 // the version is not modified. 195 func WithVersionFromEnv() Opt { 196 return func(c *Client) error { 197 return WithVersion(os.Getenv(EnvOverrideAPIVersion))(c) 198 } 199 } 200 201 // WithAPIVersionNegotiation enables automatic API version negotiation for the client. 202 // With this option enabled, the client automatically negotiates the API version 203 // to use when making requests. API version negotiation is performed on the first 204 // request; subsequent requests will not re-negotiate. 205 func WithAPIVersionNegotiation() Opt { 206 return func(c *Client) error { 207 c.negotiateVersion = true 208 return nil 209 } 210 }