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 bool
// CloneTLSConfig from parent (tls.Config).
CloneTLSConfig bool
// ReadYourWrites ensures isolated read-after-write semantics by
// providing discovered cluster replication states in each request.
// 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 {
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
foundClientCert := false
@@ -1143,6 +1153,26 @@ func (c *Client) ReadYourWrites() bool {
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
// 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
@@ -1189,6 +1219,11 @@ func (c *Client) clone(cloneHeaders bool) (*Client, error) {
CloneToken: config.CloneToken,
ReadYourWrites: config.ReadYourWrites,
}
if config.CloneTLSConfig {
newConfig.clientTLSConfig = config.clientTLSConfig
}
client, err := NewClient(newConfig)
if err != nil {
return nil, err

View File

@@ -6,6 +6,7 @@ package api
import (
"bytes"
"context"
"crypto/tls"
"crypto/x509"
"encoding/base64"
"fmt"
@@ -591,6 +592,24 @@ func TestClone(t *testing.T) {
},
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 {
@@ -699,6 +718,22 @@ func TestClone(t *testing.T) {
t.Fatalf("expected replicationStateStore %v, actual %v", parent.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.
```