options.go 4.2 KB

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