[Vault-5736] Add (*Client).WithNamespace() for temporary namespace handling (#14963)
temporary namespace calls
This commit is contained in:
parent
299d3f096e
commit
3e6665f65d
|
@ -819,10 +819,39 @@ func (c *Client) setNamespace(namespace string) {
|
||||||
c.headers.Set(consts.NamespaceHeaderName, namespace)
|
c.headers.Set(consts.NamespaceHeaderName, namespace)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ClearNamespace removes the namespace header if set.
|
||||||
func (c *Client) ClearNamespace() {
|
func (c *Client) ClearNamespace() {
|
||||||
c.modifyLock.Lock()
|
c.modifyLock.Lock()
|
||||||
defer c.modifyLock.Unlock()
|
defer c.modifyLock.Unlock()
|
||||||
c.headers.Del(consts.NamespaceHeaderName)
|
if c.headers != nil {
|
||||||
|
c.headers.Del(consts.NamespaceHeaderName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Namespace returns the namespace currently set in this client. It will
|
||||||
|
// return an empty string if there is no namespace set.
|
||||||
|
func (c *Client) Namespace() string {
|
||||||
|
c.modifyLock.Lock()
|
||||||
|
defer c.modifyLock.Unlock()
|
||||||
|
if c.headers == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return c.headers.Get(consts.NamespaceHeaderName)
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithNamespace makes a shallow copy of Client, modifies it to use
|
||||||
|
// the given namespace, and returns it. Passing an empty string will
|
||||||
|
// temporarily unset the namespace.
|
||||||
|
func (c *Client) WithNamespace(namespace string) *Client {
|
||||||
|
c2 := *c
|
||||||
|
c2.modifyLock = sync.RWMutex{}
|
||||||
|
c2.headers = c.Headers()
|
||||||
|
if namespace == "" {
|
||||||
|
c2.ClearNamespace()
|
||||||
|
} else {
|
||||||
|
c2.SetNamespace(namespace)
|
||||||
|
}
|
||||||
|
return &c2
|
||||||
}
|
}
|
||||||
|
|
||||||
// Token returns the access token being used by this client. It will
|
// Token returns the access token being used by this client. It will
|
||||||
|
@ -1141,12 +1170,22 @@ func (c *Client) rawRequestWithContext(ctx context.Context, r *Request) (*Respon
|
||||||
checkRetry := c.config.CheckRetry
|
checkRetry := c.config.CheckRetry
|
||||||
backoff := c.config.Backoff
|
backoff := c.config.Backoff
|
||||||
httpClient := c.config.HttpClient
|
httpClient := c.config.HttpClient
|
||||||
|
ns := c.headers.Get(consts.NamespaceHeaderName)
|
||||||
outputCurlString := c.config.OutputCurlString
|
outputCurlString := c.config.OutputCurlString
|
||||||
logger := c.config.Logger
|
logger := c.config.Logger
|
||||||
c.config.modifyLock.RUnlock()
|
c.config.modifyLock.RUnlock()
|
||||||
|
|
||||||
c.modifyLock.RUnlock()
|
c.modifyLock.RUnlock()
|
||||||
|
|
||||||
|
// ensure that the most current namespace setting is used at the time of the call
|
||||||
|
// e.g. calls using (*Client).WithNamespace
|
||||||
|
switch ns {
|
||||||
|
case "":
|
||||||
|
r.Headers.Del(consts.NamespaceHeaderName)
|
||||||
|
default:
|
||||||
|
r.Headers.Set(consts.NamespaceHeaderName, ns)
|
||||||
|
}
|
||||||
|
|
||||||
for _, cb := range c.requestCallbacks {
|
for _, cb := range c.requestCallbacks {
|
||||||
cb(r)
|
cb(r)
|
||||||
}
|
}
|
||||||
|
@ -1278,13 +1317,19 @@ func (c *Client) httpRequestWithContext(ctx context.Context, r *Request) (*Respo
|
||||||
limiter := c.config.Limiter
|
limiter := c.config.Limiter
|
||||||
httpClient := c.config.HttpClient
|
httpClient := c.config.HttpClient
|
||||||
outputCurlString := c.config.OutputCurlString
|
outputCurlString := c.config.OutputCurlString
|
||||||
|
// add headers
|
||||||
if c.headers != nil {
|
if c.headers != nil {
|
||||||
for header, vals := range c.headers {
|
for header, vals := range c.headers {
|
||||||
for _, val := range vals {
|
for _, val := range vals {
|
||||||
req.Header.Add(header, val)
|
req.Header.Add(header, val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// explicitly set the namespace header to current client
|
||||||
|
if ns := c.headers.Get(consts.NamespaceHeaderName); ns != "" {
|
||||||
|
r.Headers.Set(consts.NamespaceHeaderName, ns)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.config.modifyLock.RUnlock()
|
c.config.modifyLock.RUnlock()
|
||||||
c.modifyLock.RUnlock()
|
c.modifyLock.RUnlock()
|
||||||
|
|
||||||
|
|
|
@ -1136,3 +1136,67 @@ func TestClient_SetCloneToken(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestClientWithNamespace(t *testing.T) {
|
||||||
|
var ns string
|
||||||
|
handler := func(w http.ResponseWriter, req *http.Request) {
|
||||||
|
ns = req.Header.Get(consts.NamespaceHeaderName)
|
||||||
|
}
|
||||||
|
config, ln := testHTTPServer(t, http.HandlerFunc(handler))
|
||||||
|
defer ln.Close()
|
||||||
|
|
||||||
|
// set up a client with a namespace
|
||||||
|
client, err := NewClient(config)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
ogNS := "test"
|
||||||
|
client.SetNamespace(ogNS)
|
||||||
|
_, err = client.rawRequestWithContext(
|
||||||
|
context.Background(),
|
||||||
|
client.NewRequest(http.MethodGet, "/"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
if ns != ogNS {
|
||||||
|
t.Fatalf("Expected namespace: \"%s\", got \"%s\"", ogNS, ns)
|
||||||
|
}
|
||||||
|
|
||||||
|
// make a call with a temporary namespace
|
||||||
|
newNS := "new-namespace"
|
||||||
|
_, err = client.WithNamespace(newNS).rawRequestWithContext(
|
||||||
|
context.Background(),
|
||||||
|
client.NewRequest(http.MethodGet, "/"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
if ns != newNS {
|
||||||
|
t.Fatalf("Expected new namespace: \"%s\", got \"%s\"", newNS, ns)
|
||||||
|
}
|
||||||
|
// ensure client has not been modified
|
||||||
|
_, err = client.rawRequestWithContext(
|
||||||
|
context.Background(),
|
||||||
|
client.NewRequest(http.MethodGet, "/"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
if ns != ogNS {
|
||||||
|
t.Fatalf("Expected original namespace: \"%s\", got \"%s\"", ogNS, ns)
|
||||||
|
}
|
||||||
|
|
||||||
|
// make call with empty ns
|
||||||
|
_, err = client.WithNamespace("").rawRequestWithContext(
|
||||||
|
context.Background(),
|
||||||
|
client.NewRequest(http.MethodGet, "/"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
if ns != "" {
|
||||||
|
t.Fatalf("Expected no namespace, got \"%s\"", ns)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure client has not been modified
|
||||||
|
if client.Namespace() != ogNS {
|
||||||
|
t.Fatalf("Expected original namespace: \"%s\", got \"%s\"", ogNS, client.Namespace())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
```release-note:improvement
|
||||||
|
api: Provide a helper method WithNamespace to create a cloned client with a new NS
|
||||||
|
```
|
Loading…
Reference in New Issue