diff --git a/hub/kv.go b/hub/kv.go index 9fbdcaf00..32c7f9e31 100644 --- a/hub/kv.go +++ b/hub/kv.go @@ -17,6 +17,7 @@ limitations under the License. package hub import ( + "maps" "sync" "kmodules.xyz/resource-metadata/apis/meta/v1alpha1" @@ -41,6 +42,18 @@ func NewKVMap(cache map[string]*v1alpha1.ResourceDescriptor) KV { return &KVMap{cache: cache} } +// NewKVMapFromKnown returns a KVMap seeded with a shallow copy of the +// embedded known-descriptors map. Use this when constructing per-cluster +// registries so that each registry mutates its own map: KnownDescriptors() +// returns the package-global map, and sharing it across registries leads to +// concurrent-map-writes when several clusters discover CRDs simultaneously. +func NewKVMapFromKnown() KV { + known := resourcedescriptors.KnownDescriptors() + cache := make(map[string]*v1alpha1.ResourceDescriptor, len(known)) + maps.Copy(cache, known) + return &KVMap{cache: cache} +} + func (s *KVMap) Set(key string, val *v1alpha1.ResourceDescriptor) { s.m.Lock() s.cache[key] = val @@ -72,9 +85,7 @@ var _ KV = &KVLocal{} func NewKVLocal() KV { return &KVLocal{ - known: &KVMap{ - cache: resourcedescriptors.KnownDescriptors(), - }, + known: NewKVMapFromKnown(), cache: map[string]*v1alpha1.ResourceDescriptor{}, } } diff --git a/hub/registry.go b/hub/registry.go index 251a83bdf..cd439ceae 100644 --- a/hub/registry.go +++ b/hub/registry.go @@ -94,9 +94,7 @@ func NewRegistry(uid string, cache KV) *Registry { } func NewRegistryOfKnownResources() *Registry { - return NewRegistry(KnownUID, &KVMap{ - cache: resourcedescriptors.KnownDescriptors(), - }) + return NewRegistry(KnownUID, NewKVMapFromKnown()) } func (r *Registry) DiscoverResources(cfg *rest.Config) error {