diff --git a/credentials/tls/certprovider/store.go b/credentials/tls/certprovider/store.go index a6ebfba9be8e..29f042419e50 100644 --- a/credentials/tls/certprovider/store.go +++ b/credentials/tls/certprovider/store.go @@ -45,7 +45,7 @@ type storeKey struct { // wrappedProvider wraps a provider instance with a reference count. type wrappedProvider struct { - provider Provider + Provider refCount int // A reference to the key and store are also kept here to override the @@ -54,11 +54,21 @@ type wrappedProvider struct { store *store } -// wrappedProviderCloser wraps a provider instance with a reference count to avoid double +// closedProvider always returns errProviderClosed error. +type closedProvider struct{} + +func (c closedProvider) KeyMaterial(ctx context.Context) (*KeyMaterial, error) { + return nil, errProviderClosed +} + +func (c closedProvider) Close() { +} + +// singleCloseWrappedProvider wraps a provider instance with a reference count to avoid double // close still in use provider. -type wrappedProviderCloser struct { - mu sync.RWMutex - wp *wrappedProvider +type singleCloseWrappedProvider struct { + mu sync.RWMutex + provider Provider } // store is a collection of provider instances, safe for concurrent access. @@ -78,32 +88,27 @@ func (wp *wrappedProvider) Close() { wp.refCount-- if wp.refCount == 0 { - wp.provider.Close() + wp.Provider.Close() delete(ps.providers, wp.storeKey) } } // Close overrides the Close method of the embedded provider to avoid release the // already released reference. -func (w *wrappedProviderCloser) Close() { +func (w *singleCloseWrappedProvider) Close() { w.mu.Lock() defer w.mu.Unlock() - if wp := w.wp; wp != nil { - w.wp = nil - wp.Close() - } + w.provider.Close() + w.provider = closedProvider{} } // KeyMaterial returns the key material sourced by the Provider. // Callers are expected to use the returned value as read-only. -func (w *wrappedProviderCloser) KeyMaterial(ctx context.Context) (*KeyMaterial, error) { +func (w *singleCloseWrappedProvider) KeyMaterial(ctx context.Context) (*KeyMaterial, error) { w.mu.RLock() defer w.mu.RUnlock() - if w.wp == nil { - return nil, errProviderClosed - } - return w.wp.provider.KeyMaterial(ctx) + return w.provider.KeyMaterial(ctx) } // BuildableConfig wraps parsed provider configuration and functionality to @@ -143,7 +148,7 @@ func (bc *BuildableConfig) Build(opts BuildOptions) (Provider, error) { } if wp, ok := provStore.providers[sk]; ok { wp.refCount++ - return &wrappedProviderCloser{wp: wp}, nil + return &singleCloseWrappedProvider{provider: wp}, nil } provider := bc.starter(opts) @@ -151,13 +156,13 @@ func (bc *BuildableConfig) Build(opts BuildOptions) (Provider, error) { return nil, fmt.Errorf("provider(%q, %q).Build(%v) failed", sk.name, sk.config, opts) } wp := &wrappedProvider{ - provider: provider, + Provider: provider, refCount: 1, storeKey: sk, store: provStore, } provStore.providers[sk] = wp - return &wrappedProviderCloser{wp: wp}, nil + return &singleCloseWrappedProvider{provider: wp}, nil } // String returns the provider name and config as a colon separated string.