Add support for cloning a Client's tls.Config (#21424)

Additional fixes:
- handle a failed type assert in api.Config.configureTLS()

Co-authored-by: Anton Averchenkov <84287187+averche@users.noreply.github.com>
This commit is contained in:
Ben Ash
2023-06-28 14:56:39 -07:00
committed by GitHub
parent 3e60da075b
commit 3ca3397676
3 changed files with 74 additions and 1 deletions

View File

@@ -185,6 +185,9 @@ type Config struct {
// CloneToken from parent. // CloneToken from parent.
CloneToken bool CloneToken bool
// CloneTLSConfig from parent (tls.Config).
CloneTLSConfig bool
// ReadYourWrites ensures isolated read-after-write semantics by // ReadYourWrites ensures isolated read-after-write semantics by
// providing discovered cluster replication states in each request. // providing discovered cluster replication states in each request.
// The shared state is automatically propagated to all Client clones. // The shared state is automatically propagated to all Client clones.
@@ -290,7 +293,14 @@ func (c *Config) configureTLS(t *TLSConfig) error {
if c.HttpClient == nil { if c.HttpClient == nil {
c.HttpClient = DefaultConfig().HttpClient c.HttpClient = DefaultConfig().HttpClient
} }
clientTLSConfig := c.HttpClient.Transport.(*http.Transport).TLSClientConfig
transport, ok := c.HttpClient.Transport.(*http.Transport)
if !ok {
return fmt.Errorf(
"unsupported HTTPClient transport type %T", c.HttpClient.Transport)
}
clientTLSConfig := transport.TLSClientConfig
var clientCert tls.Certificate var clientCert tls.Certificate
foundClientCert := false foundClientCert := false
@@ -1143,6 +1153,26 @@ func (c *Client) ReadYourWrites() bool {
return c.config.ReadYourWrites return c.config.ReadYourWrites
} }
// SetCloneTLSConfig from parent.
func (c *Client) SetCloneTLSConfig(clone bool) {
c.modifyLock.Lock()
defer c.modifyLock.Unlock()
c.config.modifyLock.Lock()
defer c.config.modifyLock.Unlock()
c.config.CloneTLSConfig = clone
}
// CloneTLSConfig gets the configured CloneTLSConfig value.
func (c *Client) CloneTLSConfig() bool {
c.modifyLock.RLock()
defer c.modifyLock.RUnlock()
c.config.modifyLock.RLock()
defer c.config.modifyLock.RUnlock()
return c.config.CloneTLSConfig
}
// Clone creates a new client with the same configuration. Note that the same // Clone creates a new client with the same configuration. Note that the same
// underlying http.Client is used; modifying the client from more than one // underlying http.Client is used; modifying the client from more than one
// goroutine at once may not be safe, so modify the client as needed and then // goroutine at once may not be safe, so modify the client as needed and then
@@ -1189,6 +1219,11 @@ func (c *Client) clone(cloneHeaders bool) (*Client, error) {
CloneToken: config.CloneToken, CloneToken: config.CloneToken,
ReadYourWrites: config.ReadYourWrites, ReadYourWrites: config.ReadYourWrites,
} }
if config.CloneTLSConfig {
newConfig.clientTLSConfig = config.clientTLSConfig
}
client, err := NewClient(newConfig) client, err := NewClient(newConfig)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -6,6 +6,7 @@ package api
import ( import (
"bytes" "bytes"
"context" "context"
"crypto/tls"
"crypto/x509" "crypto/x509"
"encoding/base64" "encoding/base64"
"fmt" "fmt"
@@ -591,6 +592,24 @@ func TestClone(t *testing.T) {
}, },
token: "cloneToken", token: "cloneToken",
}, },
{
name: "cloneTLSConfig-enabled",
config: &Config{
CloneTLSConfig: true,
clientTLSConfig: &tls.Config{
ServerName: "foo.bar.baz",
},
},
},
{
name: "cloneTLSConfig-disabled",
config: &Config{
CloneTLSConfig: false,
clientTLSConfig: &tls.Config{
ServerName: "foo.bar.baz",
},
},
},
} }
for _, tt := range tests { for _, tt := range tests {
@@ -699,6 +718,22 @@ func TestClone(t *testing.T) {
t.Fatalf("expected replicationStateStore %v, actual %v", parent.replicationStateStore, t.Fatalf("expected replicationStateStore %v, actual %v", parent.replicationStateStore,
clone.replicationStateStore) clone.replicationStateStore)
} }
if tt.config.CloneTLSConfig {
if !reflect.DeepEqual(parent.config.TLSConfig(), clone.config.TLSConfig()) {
t.Fatalf("config.clientTLSConfig doesn't match: %v vs %v",
parent.config.TLSConfig(), clone.config.TLSConfig())
}
} else if tt.config.clientTLSConfig != nil {
if reflect.DeepEqual(parent.config.TLSConfig(), clone.config.TLSConfig()) {
t.Fatalf("config.clientTLSConfig should not match: %v vs %v",
parent.config.TLSConfig(), clone.config.TLSConfig())
}
} else {
if !reflect.DeepEqual(parent.config.TLSConfig(), clone.config.TLSConfig()) {
t.Fatalf("config.clientTLSConfig doesn't match: %v vs %v",
parent.config.TLSConfig(), clone.config.TLSConfig())
}
}
}) })
} }
} }

3
changelog/21424.txt Normal file
View File

@@ -0,0 +1,3 @@
```release-note:improvement
api: add support for cloning a Client's tls.Config.
```