Просмотр исходного кода

bolt changes

Signed-off-by: Sean Holcomb <seanholcomb@gmail.com>
Sean Holcomb 4 недель назад
Родитель
Сommit
1018ea9a79

+ 6 - 13
core/pkg/exporter/encoder.go

@@ -12,11 +12,10 @@ import (
 )
 
 const (
-	BingenExt           = "bin"
-	BingenVersionExtFMT = "v%d.bin"
-	JSONExt             = "json"
-	GZipExt             = ".gz"
-	PBExt               = "binpb"
+	BingenExt = "bingen"
+	JSONExt   = "json"
+	GZipExt   = "gz"
+	PBExt     = "binpb"
 )
 
 // Encoder[T] is a generic interface for encoding an instance of a T type into a byte slice.
@@ -54,16 +53,10 @@ func NewBingenEncoder[T any, U BinaryMarshalerPtr[T]]() Encoder[T] {
 // 'T' type with the ".bingen" file extension.
 func NewBingenFileEncoder[T any, U BinaryMarshalerPtr[T]]() Encoder[T] {
 	return &BingenEncoder[T, U]{
-		fileExt: "bingen",
+		fileExt: BingenExt,
 	}
 }
 
-func NewVersionBingenEncoder[T any, U BinaryMarshalerPtr[T]](version uint8) Encoder[T] {
-	be := new(BingenEncoder[T, U])
-	be.fileExt = fmt.Sprintf(BingenVersionExtFMT, version)
-	return be
-}
-
 // Encode encodes the provided data of type T into a byte slice using the BinaryMarshaler interface.
 func (b *BingenEncoder[T, U]) Encode(data *T) ([]byte, error) {
 	var bingenData U = data
@@ -139,7 +132,7 @@ func gZipEncode(data []byte) ([]byte, error) {
 // FileExt returns the file extension for the encoded data. In this case, it returns the wrapped encoder's
 // file extension with ".gz" appended to indicate that the data is compressed with GZip.
 func (gz *GZipEncoder[T]) FileExt() string {
-	return gz.encoder.FileExt() + GZipExt
+	return fmt.Sprintf("%s.%s", gz.encoder.FileExt(), GZipExt)
 }
 
 // ProtoMessagePtr [T] is a generic constraint to ensure types passed to the encoder implement

+ 1 - 3
core/pkg/model/kubemodel/kubemodel.go

@@ -5,9 +5,7 @@ import (
 	"time"
 )
 
-// TODO: should we add a lock so that we can safely modify KubeModelSet in parallel?
-
-// @bingen:generate[stringtable]:KubeModelSet
+// @bingen:generate[stringtable,streamable]:KubeModelSet
 type KubeModelSet struct {
 	Metadata               *Metadata                         `json:"meta"`                   // @bingen:field[version=1]
 	Window                 Window                            `json:"window"`                 // @bingen:field[version=1]

+ 1 - 1
core/pkg/model/pricingmodel/pricingmodel.go

@@ -7,7 +7,7 @@ import (
 // @bingen:generate:PricingSourceType
 type PricingSourceType string
 
-// @bingen:generate:PricingModelSet
+// @bingen:generate[stringtable,streamable]:PricingModelSet
 type PricingModelSet struct {
 	TimeStamp   time.Time
 	SourceType  PricingSourceType

+ 9 - 13
core/pkg/source/decoders.go

@@ -704,11 +704,7 @@ func DecodeOwnerResult(result *QueryResult) *OwnerResult {
 	cluster, _ := result.GetCluster()
 	ownerUID, _ := result.GetString(OwnerUIDLabel)
 	ownerKind, _ := result.GetString(OwnerKindLabel)
-	controllerStr, _ := result.GetString(ControllerLabel)
-	controller := false
-	if controllerStr == "true" {
-		controller = true
-	}
+	controller, _ := result.GetBool(ControllerLabel)
 
 	return &OwnerResult{
 		UID:        uid,
@@ -1260,10 +1256,10 @@ func DecodePodNetworkBytesResult(result *QueryResult) *PodNetworkBytesResult {
 	uid, _ := result.GetString(UIDLabel)
 	cluster, _ := result.GetCluster()
 	service, _ := result.GetString(ServiceLabel)
-	internet, _ := result.GetString(InternetLabel)
-	sameRegion, _ := result.GetString(SameRegionLabel)
-	sameZone, _ := result.GetString(SameZoneLabel)
-	natGateway, _ := result.GetString(NatGatewayLabel)
+	internet, _ := result.GetBool(InternetLabel)
+	sameRegion, _ := result.GetBool(SameRegionLabel)
+	sameZone, _ := result.GetBool(SameZoneLabel)
+	natGateway, _ := result.GetBool(NatGatewayLabel)
 	var value float64
 	if len(result.Values) > 0 {
 		value = result.Values[0].Value
@@ -1275,10 +1271,10 @@ func DecodePodNetworkBytesResult(result *QueryResult) *PodNetworkBytesResult {
 		UID:        uid,
 		Cluster:    cluster,
 		Service:    service,
-		Internet:   internet == "true",
-		SameRegion: sameRegion == "true",
-		SameZone:   sameZone == "true",
-		NatGateway: natGateway == "true",
+		Internet:   internet,
+		SameRegion: sameRegion,
+		SameZone:   sameZone,
+		NatGateway: natGateway,
 		Value:      value,
 	}
 }

+ 20 - 0
core/pkg/source/queryresult.go

@@ -2,6 +2,7 @@ package source
 
 import (
 	"fmt"
+	"strconv"
 	"strings"
 
 	"github.com/opencost/opencost/core/pkg/log"
@@ -173,6 +174,25 @@ func (qr *QueryResult) GetString(field string) (string, error) {
 	return strField, nil
 }
 
+func (qr *QueryResult) GetBool(field string) (bool, error) {
+	f, ok := qr.Metric[field]
+	if !ok {
+		return false, fmt.Errorf("'%s' field does not exist in data result vector", field)
+	}
+
+	switch f.(type) {
+	case bool:
+		return f.(bool), nil
+	case string:
+		b, err := strconv.ParseBool(f.(string))
+		if err != nil {
+			return false, fmt.Errorf("string value for field could not be parsed to bool: %w", err)
+		}
+		return b, nil
+	}
+	return false, fmt.Errorf("field did not have an appropriate type for bool conversion: %T", f)
+}
+
 // GetStrings returns the requested fields, or an error if it does not exist
 func (qr *QueryResult) GetStrings(fields ...string) (map[string]string, error) {
 	values := map[string]string{}

+ 50 - 75
modules/collector-source/pkg/scrape/clustercache.go

@@ -5,7 +5,6 @@ import (
 	"slices"
 	"strconv"
 	"strings"
-	"sync"
 
 	"github.com/kubecost/events"
 	"github.com/opencost/opencost/core/pkg/clustercache"
@@ -23,34 +22,6 @@ import (
 	"k8s.io/apimachinery/pkg/util/validation"
 )
 
-// SyncMap provides thread-safe concurrent access to a generic map
-type SyncMap[U comparable, T any] struct {
-	mu   sync.RWMutex
-	data map[U]T
-}
-
-// newSyncMap creates a new thread-safe map with the specified initial capacity
-func newSyncMap[U comparable, T any](size int) *SyncMap[U, T] {
-	return &SyncMap[U, T]{
-		data: make(map[U]T, size),
-	}
-}
-
-// Set adds or updates a key-value mapping
-func (sm *SyncMap[U, T]) Set(key U, value T) {
-	sm.mu.Lock()
-	defer sm.mu.Unlock()
-	sm.data[key] = value
-}
-
-// Get retrieves a value by key. Returns the value and a boolean indicating if it was found.
-func (sm *SyncMap[U, T]) Get(key U) (T, bool) {
-	sm.mu.RLock()
-	defer sm.mu.RUnlock()
-	value, ok := sm.data[key]
-	return value, ok
-}
-
 const unmountedPVsContainer = "unmounted-pvs"
 
 type ClusterCacheScraper struct {
@@ -86,24 +57,25 @@ func (ccs *ClusterCacheScraper) Scrape() []metric.Update {
 
 	// create scrape indexes. While the pairs being mapped here don't have a 1 to 1 relationship in the general case,
 	// we are assuming that in the context of a single snapshot of the cluster they are 1 to 1.
-	nodeNameToUID := newSyncMap[string, types.UID](len(nodes))
+	nodeNameToUID := make(map[string]types.UID, len(nodes))
 	for _, node := range nodes {
-		nodeNameToUID.Set(node.Name, node.UID)
+		nodeNameToUID[node.Name] = node.UID
 	}
-	namespaceNameToUID := newSyncMap[string, types.UID](len(namespaces))
+	namespaceNameToUID := make(map[string]types.UID, len(namespaces))
 	for _, ns := range namespaces {
-		namespaceNameToUID.Set(ns.Name, ns.UID)
+		namespaceNameToUID[ns.Name] = ns.UID
 	}
-	pvcNameToUID := newSyncMap[pvcKey, types.UID](len(pvcs))
+	pvcNameToUID := make(map[pvcKey]types.UID, len(pvcs))
 	for _, pvc := range pvcs {
-		pvcNameToUID.Set(pvcKey{
+		key := pvcKey{
 			name:      pvc.Name,
 			namespace: pvc.Namespace,
-		}, pvc.UID)
+		}
+		pvcNameToUID[key] = pvc.UID
 	}
-	pvNameToUID := newSyncMap[string, types.UID](len(pvs))
+	pvNameToUID := make(map[string]types.UID, len(pvs))
 	for _, pv := range pvs {
-		pvNameToUID.Set(pv.Name, pv.UID)
+		pvNameToUID[pv.Name] = pv.UID
 	}
 
 	scrapeFuncs := []ScrapeFunc{
@@ -229,16 +201,16 @@ func (ccs *ClusterCacheScraper) scrapeNodes(nodes []*clustercache.Node) []metric
 	return scrapeResults
 }
 
-func (ccs *ClusterCacheScraper) GetScrapeDeployments(deployments []*clustercache.Deployment, namespaceIndex *SyncMap[string, types.UID]) ScrapeFunc {
+func (ccs *ClusterCacheScraper) GetScrapeDeployments(deployments []*clustercache.Deployment, namespaceIndex map[string]types.UID) ScrapeFunc {
 	return func() []metric.Update {
 		return ccs.scrapeDeployments(deployments, namespaceIndex)
 	}
 }
 
-func (ccs *ClusterCacheScraper) scrapeDeployments(deployments []*clustercache.Deployment, namespaceIndex *SyncMap[string, types.UID]) []metric.Update {
+func (ccs *ClusterCacheScraper) scrapeDeployments(deployments []*clustercache.Deployment, namespaceIndex map[string]types.UID) []metric.Update {
 	var scrapeResults []metric.Update
 	for _, deployment := range deployments {
-		nsUID, ok := namespaceIndex.Get(deployment.Namespace)
+		nsUID, ok := namespaceIndex[deployment.Namespace]
 		if !ok {
 			log.Debugf("deployment namespaceUID missing from index for namespace name '%s'", deployment.Namespace)
 		}
@@ -355,9 +327,9 @@ func (ccs *ClusterCacheScraper) scrapeNamespaces(namespaces []*clustercache.Name
 func (ccs *ClusterCacheScraper) GetScrapePods(
 	pods []*clustercache.Pod,
 	pvcs []*clustercache.PersistentVolumeClaim,
-	nodeIndex *SyncMap[string, types.UID],
-	namespaceIndex *SyncMap[string, types.UID],
-	pvcIndex *SyncMap[pvcKey, types.UID],
+	nodeIndex map[string]types.UID,
+	namespaceIndex map[string]types.UID,
+	pvcIndex map[pvcKey]types.UID,
 ) ScrapeFunc {
 	return func() []metric.Update {
 		return ccs.scrapePods(pods, pvcs, nodeIndex, namespaceIndex, pvcIndex)
@@ -367,9 +339,9 @@ func (ccs *ClusterCacheScraper) GetScrapePods(
 func (ccs *ClusterCacheScraper) scrapePods(
 	pods []*clustercache.Pod,
 	pvcs []*clustercache.PersistentVolumeClaim,
-	nodeIndex *SyncMap[string, types.UID],
-	namespaceIndex *SyncMap[string, types.UID],
-	pvcIndex *SyncMap[pvcKey, types.UID],
+	nodeIndex map[string]types.UID,
+	namespaceIndex map[string]types.UID,
+	pvcIndex map[pvcKey]types.UID,
 ) []metric.Update {
 	// this is only populated if we find gpu resources being requested
 	var nodesGpuInfo map[string]*NodeGpuInfo
@@ -382,11 +354,11 @@ func (ccs *ClusterCacheScraper) scrapePods(
 
 	var scrapeResults []metric.Update
 	for _, pod := range pods {
-		nodeUID, ok := nodeIndex.Get(pod.Spec.NodeName)
+		nodeUID, ok := nodeIndex[pod.Spec.NodeName]
 		if !ok {
 			log.Debugf("pod nodeUID missing from index for node name '%s'", pod.Spec.NodeName)
 		}
-		nsUID, ok := namespaceIndex.Get(pod.Namespace)
+		nsUID, ok := namespaceIndex[pod.Namespace]
 		if !ok {
 			log.Debugf("pod namespaceUID missing from index for namespace name '%s'", pod.Namespace)
 		}
@@ -480,10 +452,13 @@ func (ccs *ClusterCacheScraper) scrapePods(
 
 		for _, volume := range pod.Spec.Volumes {
 			if volume.PersistentVolumeClaim != nil {
-				pvcUID, _ := pvcIndex.Get(pvcKey{
+				pvcUID, ok := pvcIndex[pvcKey{
 					name:      volume.PersistentVolumeClaim.ClaimName,
 					namespace: pod.Namespace,
-				})
+				}]
+				if !ok {
+					continue
+				}
 				podPVCVolumeInfo := map[string]string{
 					source.UIDLabel:           string(pod.UID),
 					source.PVCUIDLabel:        string(pvcUID),
@@ -645,8 +620,8 @@ func scrapeResourceList(metricName string, resourceList v1.ResourceList, baseLab
 
 func (ccs *ClusterCacheScraper) GetScrapePVCs(
 	pvcs []*clustercache.PersistentVolumeClaim,
-	namespaceIndex *SyncMap[string, types.UID],
-	pvIndex *SyncMap[string, types.UID],
+	namespaceIndex map[string]types.UID,
+	pvIndex map[string]types.UID,
 ) ScrapeFunc {
 	return func() []metric.Update {
 		return ccs.scrapePVCs(pvcs, namespaceIndex, pvIndex)
@@ -655,16 +630,16 @@ func (ccs *ClusterCacheScraper) GetScrapePVCs(
 
 func (ccs *ClusterCacheScraper) scrapePVCs(
 	pvcs []*clustercache.PersistentVolumeClaim,
-	namespaceIndex *SyncMap[string, types.UID],
-	pvIndex *SyncMap[string, types.UID],
+	namespaceIndex map[string]types.UID,
+	pvIndex map[string]types.UID,
 ) []metric.Update {
 	var scrapeResults []metric.Update
 	for _, pvc := range pvcs {
-		nsUID, ok := namespaceIndex.Get(pvc.Namespace)
+		nsUID, ok := namespaceIndex[pvc.Namespace]
 		if !ok {
 			log.Debugf("pvc namespaceUID missing from index for namespace name '%s'", pvc.Namespace)
 		}
-		pvUID, ok := pvIndex.Get(pvc.Spec.VolumeName)
+		pvUID, ok := pvIndex[pvc.Spec.VolumeName]
 		if !ok && pvc.Spec.VolumeName != "" {
 			log.Debugf("pvc volume name missing from index for pv name '%s'", pvc.Spec.VolumeName)
 		}
@@ -799,16 +774,16 @@ func (ccs *ClusterCacheScraper) scrapeServices(services []*clustercache.Service)
 	return scrapeResults
 }
 
-func (ccs *ClusterCacheScraper) GetScrapeStatefulSets(statefulSets []*clustercache.StatefulSet, namespaceIndex *SyncMap[string, types.UID]) ScrapeFunc {
+func (ccs *ClusterCacheScraper) GetScrapeStatefulSets(statefulSets []*clustercache.StatefulSet, namespaceIndex map[string]types.UID) ScrapeFunc {
 	return func() []metric.Update {
 		return ccs.scrapeStatefulSets(statefulSets, namespaceIndex)
 	}
 }
 
-func (ccs *ClusterCacheScraper) scrapeStatefulSets(statefulSets []*clustercache.StatefulSet, namespaceIndex *SyncMap[string, types.UID]) []metric.Update {
+func (ccs *ClusterCacheScraper) scrapeStatefulSets(statefulSets []*clustercache.StatefulSet, namespaceIndex map[string]types.UID) []metric.Update {
 	var scrapeResults []metric.Update
 	for _, statefulSet := range statefulSets {
-		nsUID, ok := namespaceIndex.Get(statefulSet.Namespace)
+		nsUID, ok := namespaceIndex[statefulSet.Namespace]
 		if !ok {
 			log.Debugf("statefulSet namespaceUID missing from index for namespace name '%s'", statefulSet.Namespace)
 		}
@@ -871,16 +846,16 @@ func (ccs *ClusterCacheScraper) scrapeStatefulSets(statefulSets []*clustercache.
 	return scrapeResults
 }
 
-func (ccs *ClusterCacheScraper) GetScrapeDaemonSets(daemonSets []*clustercache.DaemonSet, namespaceIndex *SyncMap[string, types.UID]) ScrapeFunc {
+func (ccs *ClusterCacheScraper) GetScrapeDaemonSets(daemonSets []*clustercache.DaemonSet, namespaceIndex map[string]types.UID) ScrapeFunc {
 	return func() []metric.Update {
 		return ccs.scrapeDaemonSets(daemonSets, namespaceIndex)
 	}
 }
 
-func (ccs *ClusterCacheScraper) scrapeDaemonSets(daemonSets []*clustercache.DaemonSet, namespaceIndex *SyncMap[string, types.UID]) []metric.Update {
+func (ccs *ClusterCacheScraper) scrapeDaemonSets(daemonSets []*clustercache.DaemonSet, namespaceIndex map[string]types.UID) []metric.Update {
 	var scrapeResults []metric.Update
 	for _, daemonSet := range daemonSets {
-		nsUID, ok := namespaceIndex.Get(daemonSet.Namespace)
+		nsUID, ok := namespaceIndex[daemonSet.Namespace]
 		if !ok {
 			log.Debugf("daemonSet namespaceUID missing from index for namespace name '%s'", daemonSet.Namespace)
 		}
@@ -931,16 +906,16 @@ func (ccs *ClusterCacheScraper) scrapeDaemonSets(daemonSets []*clustercache.Daem
 	return scrapeResults
 }
 
-func (ccs *ClusterCacheScraper) GetScrapeJobs(jobs []*clustercache.Job, namespaceIndex *SyncMap[string, types.UID]) ScrapeFunc {
+func (ccs *ClusterCacheScraper) GetScrapeJobs(jobs []*clustercache.Job, namespaceIndex map[string]types.UID) ScrapeFunc {
 	return func() []metric.Update {
 		return ccs.scrapeJobs(jobs, namespaceIndex)
 	}
 }
 
-func (ccs *ClusterCacheScraper) scrapeJobs(jobs []*clustercache.Job, namespaceIndex *SyncMap[string, types.UID]) []metric.Update {
+func (ccs *ClusterCacheScraper) scrapeJobs(jobs []*clustercache.Job, namespaceIndex map[string]types.UID) []metric.Update {
 	var scrapeResults []metric.Update
 	for _, job := range jobs {
-		nsUID, ok := namespaceIndex.Get(job.Namespace)
+		nsUID, ok := namespaceIndex[job.Namespace]
 		if !ok {
 			log.Debugf("job namespaceUID missing from index for namespace name '%s'", job.Namespace)
 		}
@@ -991,16 +966,16 @@ func (ccs *ClusterCacheScraper) scrapeJobs(jobs []*clustercache.Job, namespaceIn
 	return scrapeResults
 }
 
-func (ccs *ClusterCacheScraper) GetScrapeCronJobs(cronJobs []*clustercache.CronJob, namespaceIndex *SyncMap[string, types.UID]) ScrapeFunc {
+func (ccs *ClusterCacheScraper) GetScrapeCronJobs(cronJobs []*clustercache.CronJob, namespaceIndex map[string]types.UID) ScrapeFunc {
 	return func() []metric.Update {
 		return ccs.scrapeCronJobs(cronJobs, namespaceIndex)
 	}
 }
 
-func (ccs *ClusterCacheScraper) scrapeCronJobs(cronJobs []*clustercache.CronJob, namespaceIndex *SyncMap[string, types.UID]) []metric.Update {
+func (ccs *ClusterCacheScraper) scrapeCronJobs(cronJobs []*clustercache.CronJob, namespaceIndex map[string]types.UID) []metric.Update {
 	var scrapeResults []metric.Update
 	for _, cronJob := range cronJobs {
-		nsUID, ok := namespaceIndex.Get(cronJob.Namespace)
+		nsUID, ok := namespaceIndex[cronJob.Namespace]
 		if !ok {
 			log.Debugf("cronjob namespaceUID missing from index for namespace name '%s'", cronJob.Namespace)
 		}
@@ -1051,16 +1026,16 @@ func (ccs *ClusterCacheScraper) scrapeCronJobs(cronJobs []*clustercache.CronJob,
 	return scrapeResults
 }
 
-func (ccs *ClusterCacheScraper) GetScrapeReplicaSets(replicaSets []*clustercache.ReplicaSet, namespaceIndex *SyncMap[string, types.UID]) ScrapeFunc {
+func (ccs *ClusterCacheScraper) GetScrapeReplicaSets(replicaSets []*clustercache.ReplicaSet, namespaceIndex map[string]types.UID) ScrapeFunc {
 	return func() []metric.Update {
 		return ccs.scrapeReplicaSets(replicaSets, namespaceIndex)
 	}
 }
 
-func (ccs *ClusterCacheScraper) scrapeReplicaSets(replicaSets []*clustercache.ReplicaSet, namespaceIndex *SyncMap[string, types.UID]) []metric.Update {
+func (ccs *ClusterCacheScraper) scrapeReplicaSets(replicaSets []*clustercache.ReplicaSet, namespaceIndex map[string]types.UID) []metric.Update {
 	var scrapeResults []metric.Update
 	for _, replicaSet := range replicaSets {
-		nsUID, ok := namespaceIndex.Get(replicaSet.Namespace)
+		nsUID, ok := namespaceIndex[replicaSet.Namespace]
 		if !ok {
 			log.Debugf("replicaset namespaceUID missing from index for namespace name '%s'", replicaSet.Namespace)
 		}
@@ -1148,13 +1123,13 @@ func (ccs *ClusterCacheScraper) scrapeReplicaSets(replicaSets []*clustercache.Re
 	return scrapeResults
 }
 
-func (ccs *ClusterCacheScraper) GetScrapeResourceQuotas(resourceQuotas []*clustercache.ResourceQuota, namespaceIndex *SyncMap[string, types.UID]) ScrapeFunc {
+func (ccs *ClusterCacheScraper) GetScrapeResourceQuotas(resourceQuotas []*clustercache.ResourceQuota, namespaceIndex map[string]types.UID) ScrapeFunc {
 	return func() []metric.Update {
 		return ccs.scrapeResourceQuotas(resourceQuotas, namespaceIndex)
 	}
 }
 
-func (ccs *ClusterCacheScraper) scrapeResourceQuotas(resourceQuotas []*clustercache.ResourceQuota, namespaceIndex *SyncMap[string, types.UID]) []metric.Update {
+func (ccs *ClusterCacheScraper) scrapeResourceQuotas(resourceQuotas []*clustercache.ResourceQuota, namespaceIndex map[string]types.UID) []metric.Update {
 	var scrapeResults []metric.Update
 
 	processResource := func(baseLabels map[string]string, name v1.ResourceName, quantity resource.Quantity, metricName string) metric.Update {
@@ -1172,7 +1147,7 @@ func (ccs *ClusterCacheScraper) scrapeResourceQuotas(resourceQuotas []*clusterca
 	}
 
 	for _, resourceQuota := range resourceQuotas {
-		nsUID, _ := namespaceIndex.Get(resourceQuota.Namespace)
+		nsUID, _ := namespaceIndex[resourceQuota.Namespace]
 		resourceQuotaInfo := map[string]string{
 			source.UIDLabel:           string(resourceQuota.UID),
 			source.NamespaceUIDLabel:  string(nsUID),

+ 37 - 37
modules/collector-source/pkg/scrape/clustercache_test.go

@@ -293,8 +293,8 @@ func Test_kubernetesScraper_scrapeDeployments(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			ks := &ClusterCacheScraper{}
-			nsIndex := newSyncMap[string, types.UID](0)
-			nsIndex.Set("namespace1", "ns-uuid1")
+			nsIndex := make(map[string]types.UID, 0)
+			nsIndex["namespace1"] = "ns-uuid1"
 			var scrapeResults []metric.Update
 			for _, s := range tt.scrapes {
 				res := ks.scrapeDeployments(s.Deployments, nsIndex)
@@ -423,7 +423,7 @@ func Test_kubernetesScraper_scrapePods(t *testing.T) {
 	}
 	tests := []struct {
 		name     string
-		nsSetup  func(*SyncMap[string, types.UID])
+		nsSetup  func(map[string]types.UID)
 		scrapes  []scrape
 		expected []metric.Update
 	}{
@@ -684,8 +684,8 @@ func Test_kubernetesScraper_scrapePods(t *testing.T) {
 		},
 		{
 			name: "with namespace index",
-			nsSetup: func(nsIndex *SyncMap[string, types.UID]) {
-				nsIndex.Set("namespace1", "ns-uuid1")
+			nsSetup: func(nsIndex map[string]types.UID) {
+				nsIndex["namespace1"] = "ns-uuid1"
 			},
 			scrapes: []scrape{
 				{
@@ -876,12 +876,12 @@ func Test_kubernetesScraper_scrapePods(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			ks := &ClusterCacheScraper{}
-			nodeIndex := newSyncMap[string, types.UID](0)
-			nsIndex := newSyncMap[string, types.UID](0)
+			nodeIndex := make(map[string]types.UID, 0)
+			nsIndex := make(map[string]types.UID, 0)
 			if tt.nsSetup != nil {
 				tt.nsSetup(nsIndex)
 			}
-			pvcIndex := newSyncMap[pvcKey, types.UID](0)
+			pvcIndex := make(map[pvcKey]types.UID, 0)
 			var scrapeResults []metric.Update
 			for _, s := range tt.scrapes {
 				res := ks.scrapePods(s.Pods, s.PVCs, nodeIndex, nsIndex, pvcIndex)
@@ -912,7 +912,7 @@ func Test_kubernetesScraper_scrapePVCs(t *testing.T) {
 	}
 	tests := []struct {
 		name     string
-		nsSetup  func(*SyncMap[string, types.UID])
+		nsSetup  func(map[string]types.UID)
 		scrapes  []scrape
 		expected []metric.Update
 	}{
@@ -980,8 +980,8 @@ func Test_kubernetesScraper_scrapePVCs(t *testing.T) {
 		},
 		{
 			name: "with namespace index",
-			nsSetup: func(nsIndex *SyncMap[string, types.UID]) {
-				nsIndex.Set("namespace1", "ns-uuid1")
+			nsSetup: func(nsIndex map[string]types.UID) {
+				nsIndex["namespace1"] = "ns-uuid1"
 			},
 			scrapes: []scrape{
 				{
@@ -1047,11 +1047,11 @@ func Test_kubernetesScraper_scrapePVCs(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			ks := &ClusterCacheScraper{}
-			nsIndex := newSyncMap[string, types.UID](0)
+			nsIndex := make(map[string]types.UID, 0)
 			if tt.nsSetup != nil {
 				tt.nsSetup(nsIndex)
 			}
-			pvIndex := newSyncMap[string, types.UID](0)
+			pvIndex := make(map[string]types.UID, 0)
 			var scrapeResults []metric.Update
 			for _, s := range tt.scrapes {
 				res := ks.scrapePVCs(s.PVCs, nsIndex, pvIndex)
@@ -1264,7 +1264,7 @@ func Test_kubernetesScraper_scrapeStatefulSets(t *testing.T) {
 	}
 	tests := []struct {
 		name     string
-		nsSetup  func(*SyncMap[string, types.UID])
+		nsSetup  func(map[string]types.UID)
 		scrapes  []scrape
 		expected []metric.Update
 	}{
@@ -1349,8 +1349,8 @@ func Test_kubernetesScraper_scrapeStatefulSets(t *testing.T) {
 			// statefulSetInfo map is shared; NamespaceLabel is added before MatchLabels,
 			// so all 4 metrics reflect the final state including namespace_uid.
 			name: "with namespace index",
-			nsSetup: func(nsIndex *SyncMap[string, types.UID]) {
-				nsIndex.Set("namespace1", "ns-uuid1")
+			nsSetup: func(nsIndex map[string]types.UID) {
+				nsIndex["namespace1"] = "ns-uuid1"
 			},
 			scrapes: []scrape{
 				{
@@ -1421,7 +1421,7 @@ func Test_kubernetesScraper_scrapeStatefulSets(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			ks := &ClusterCacheScraper{}
-			nsIndex := newSyncMap[string, types.UID](0)
+			nsIndex := make(map[string]types.UID, 0)
 			if tt.nsSetup != nil {
 				tt.nsSetup(nsIndex)
 			}
@@ -1455,7 +1455,7 @@ func Test_kubernetesScraper_scrapeReplicaSets(t *testing.T) {
 	}
 	tests := []struct {
 		name     string
-		nsSetup  func(*SyncMap[string, types.UID])
+		nsSetup  func(map[string]types.UID)
 		scrapes  []scrape
 		expected []metric.Update
 	}{
@@ -1586,8 +1586,8 @@ func Test_kubernetesScraper_scrapeReplicaSets(t *testing.T) {
 		},
 		{
 			name: "with namespace index",
-			nsSetup: func(nsIndex *SyncMap[string, types.UID]) {
-				nsIndex.Set("namespace1", "ns-uuid1")
+			nsSetup: func(nsIndex map[string]types.UID) {
+				nsIndex["namespace1"] = "ns-uuid1"
 			},
 			scrapes: []scrape{
 				{
@@ -1654,7 +1654,7 @@ func Test_kubernetesScraper_scrapeReplicaSets(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			ks := &ClusterCacheScraper{}
-			nsIndex := newSyncMap[string, types.UID](0)
+			nsIndex := make(map[string]types.UID, 0)
 			if tt.nsSetup != nil {
 				tt.nsSetup(nsIndex)
 			}
@@ -1687,7 +1687,7 @@ func Test_kubernetesScraper_scrapeResourceQuotas(t *testing.T) {
 	}
 	tests := []struct {
 		name     string
-		nsSetup  func(*SyncMap[string, types.UID])
+		nsSetup  func(map[string]types.UID)
 		scrapes  []scrape
 		expected []metric.Update
 	}{
@@ -1836,8 +1836,8 @@ func Test_kubernetesScraper_scrapeResourceQuotas(t *testing.T) {
 		},
 		{
 			name: "with namespace index",
-			nsSetup: func(nsIndex *SyncMap[string, types.UID]) {
-				nsIndex.Set("namespace1", "ns-uuid1")
+			nsSetup: func(nsIndex map[string]types.UID) {
+				nsIndex["namespace1"] = "ns-uuid1"
 			},
 			scrapes: []scrape{
 				{
@@ -1890,7 +1890,7 @@ func Test_kubernetesScraper_scrapeResourceQuotas(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			ks := &ClusterCacheScraper{}
-			nsIndex := newSyncMap[string, types.UID](0)
+			nsIndex := make(map[string]types.UID, 0)
 			if tt.nsSetup != nil {
 				tt.nsSetup(nsIndex)
 			}
@@ -1923,7 +1923,7 @@ func Test_kubernetesScraper_scrapeDaemonSets(t *testing.T) {
 	}
 	tests := []struct {
 		name     string
-		nsSetup  func(*SyncMap[string, types.UID])
+		nsSetup  func(map[string]types.UID)
 		scrapes  []scrape
 		expected []metric.Update
 	}{
@@ -1980,8 +1980,8 @@ func Test_kubernetesScraper_scrapeDaemonSets(t *testing.T) {
 		},
 		{
 			name: "with namespace index",
-			nsSetup: func(nsIndex *SyncMap[string, types.UID]) {
-				nsIndex.Set("namespace1", "ns-uuid1")
+			nsSetup: func(nsIndex map[string]types.UID) {
+				nsIndex["namespace1"] = "ns-uuid1"
 			},
 			scrapes: []scrape{
 				{
@@ -2037,7 +2037,7 @@ func Test_kubernetesScraper_scrapeDaemonSets(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			ks := &ClusterCacheScraper{}
-			nsIndex := newSyncMap[string, types.UID](0)
+			nsIndex := make(map[string]types.UID, 0)
 			if tt.nsSetup != nil {
 				tt.nsSetup(nsIndex)
 			}
@@ -2070,7 +2070,7 @@ func Test_kubernetesScraper_scrapeJobs(t *testing.T) {
 	}
 	tests := []struct {
 		name     string
-		nsSetup  func(*SyncMap[string, types.UID])
+		nsSetup  func(map[string]types.UID)
 		scrapes  []scrape
 		expected []metric.Update
 	}{
@@ -2127,8 +2127,8 @@ func Test_kubernetesScraper_scrapeJobs(t *testing.T) {
 		},
 		{
 			name: "with namespace index",
-			nsSetup: func(nsIndex *SyncMap[string, types.UID]) {
-				nsIndex.Set("namespace1", "ns-uuid1")
+			nsSetup: func(nsIndex map[string]types.UID) {
+				nsIndex["namespace1"] = "ns-uuid1"
 			},
 			scrapes: []scrape{
 				{
@@ -2184,7 +2184,7 @@ func Test_kubernetesScraper_scrapeJobs(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			ks := &ClusterCacheScraper{}
-			nsIndex := newSyncMap[string, types.UID](0)
+			nsIndex := make(map[string]types.UID, 0)
 			if tt.nsSetup != nil {
 				tt.nsSetup(nsIndex)
 			}
@@ -2217,7 +2217,7 @@ func Test_kubernetesScraper_scrapeCronJobs(t *testing.T) {
 	}
 	tests := []struct {
 		name     string
-		nsSetup  func(*SyncMap[string, types.UID])
+		nsSetup  func(map[string]types.UID)
 		scrapes  []scrape
 		expected []metric.Update
 	}{
@@ -2274,8 +2274,8 @@ func Test_kubernetesScraper_scrapeCronJobs(t *testing.T) {
 		},
 		{
 			name: "with namespace index",
-			nsSetup: func(nsIndex *SyncMap[string, types.UID]) {
-				nsIndex.Set("namespace1", "ns-uuid1")
+			nsSetup: func(nsIndex map[string]types.UID) {
+				nsIndex["namespace1"] = "ns-uuid1"
 			},
 			scrapes: []scrape{
 				{
@@ -2331,7 +2331,7 @@ func Test_kubernetesScraper_scrapeCronJobs(t *testing.T) {
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
 			ks := &ClusterCacheScraper{}
-			nsIndex := newSyncMap[string, types.UID](0)
+			nsIndex := make(map[string]types.UID, 0)
 			if tt.nsSetup != nil {
 				tt.nsSetup(nsIndex)
 			}