diff --git a/auth/cache.go b/auth/cache.go index 7a20215..65084d5 100644 --- a/auth/cache.go +++ b/auth/cache.go @@ -3,7 +3,9 @@ package auth import ( - "github.com/hashicorp/terraform-svchost" + "sync" + + svchost "github.com/hashicorp/terraform-svchost" ) // CachingCredentialsSource creates a new credentials source that wraps another @@ -23,6 +25,7 @@ func CachingCredentialsSource(source CredentialsSource) CredentialsSource { type cachingCredentialsSource struct { source CredentialsSource cache map[svchost.Hostname]HostCredentials + mu sync.Mutex } // ForHost passes the given hostname on to the wrapped credentials source and @@ -33,16 +36,21 @@ type cachingCredentialsSource struct { // No cache entry is created if the wrapped source returns an error, to allow // the caller to retry the failing operation. func (s *cachingCredentialsSource) ForHost(host svchost.Hostname) (HostCredentials, error) { + s.mu.Lock() if cache, cached := s.cache[host]; cached { + s.mu.Unlock() return cache, nil } + s.mu.Unlock() result, err := s.source.ForHost(host) if err != nil { return result, err } + s.mu.Lock() s.cache[host] = result + s.mu.Unlock() return result, nil } @@ -50,7 +58,9 @@ func (s *cachingCredentialsSource) StoreForHost(host svchost.Hostname, credentia // We'll delete the cache entry even if the store fails, since that just // means that the next read will go to the real store and get a chance to // see which object (old or new) is actually present. + s.mu.Lock() delete(s.cache, host) + s.mu.Unlock() return s.source.StoreForHost(host, credentials) } @@ -58,6 +68,8 @@ func (s *cachingCredentialsSource) ForgetForHost(host svchost.Hostname) error { // We'll delete the cache entry even if the store fails, since that just // means that the next read will go to the real store and get a chance to // see if the object is still present. + s.mu.Lock() delete(s.cache, host) + s.mu.Unlock() return s.source.ForgetForHost(host) }