Jelajahi Sumber

Ensure that we return a copy of ClusterInfo in InfoFor to avoid write corruption. Add an AsMap() method to ClusterMap to ensure we atomically recreate the map.

Matt Bolt 5 tahun lalu
induk
melakukan
44eaef7de6
2 mengubah file dengan 33 tambahan dan 7 penghapusan
  1. 32 1
      pkg/costmodel/clusters/clustermap.go
  2. 1 6
      pkg/costmodel/router.go

+ 32 - 1
pkg/costmodel/clusters/clustermap.go

@@ -27,10 +27,28 @@ type ClusterInfo struct {
 	Provisioner string `json:"provisioner"`
 }
 
+// Clone creates a copy of ClusterInfo and returns it
+func (ci *ClusterInfo) Clone() *ClusterInfo {
+	if ci == nil {
+		return nil
+	}
+
+	return &ClusterInfo{
+		ID:          ci.ID,
+		Name:        ci.Name,
+		Profile:     ci.Profile,
+		Provider:    ci.Provider,
+		Provisioner: ci.Provisioner,
+	}
+}
+
 type ClusterMap interface {
 	// GetClusterIDs returns a slice containing all of the cluster identifiers.
 	GetClusterIDs() []string
 
+	// AsMap returns the cluster map as a standard go map
+	AsMap() map[string]*ClusterInfo
+
 	// InfoFor returns the ClusterInfo entry for the provided clusterID or nil if it
 	// doesn't exist
 	InfoFor(clusterID string) *ClusterInfo
@@ -201,6 +219,19 @@ func (pcm *PrometheusClusterMap) GetClusterIDs() []string {
 	return clusterIDs
 }
 
+// AsMap returns the cluster map as a standard go map
+func (pcm *PrometheusClusterMap) AsMap() map[string]*ClusterInfo {
+	pcm.lock.RLock()
+	defer pcm.lock.RUnlock()
+
+	m := make(map[string]*ClusterInfo)
+	for k, v := range pcm.clusters {
+		m[k] = v.Clone()
+	}
+
+	return m
+}
+
 // InfoFor returns the ClusterInfo entry for the provided clusterID or nil if it
 // doesn't exist
 func (pcm *PrometheusClusterMap) InfoFor(clusterID string) *ClusterInfo {
@@ -208,7 +239,7 @@ func (pcm *PrometheusClusterMap) InfoFor(clusterID string) *ClusterInfo {
 	defer pcm.lock.RUnlock()
 
 	if info, ok := pcm.clusters[clusterID]; ok {
-		return info
+		return info.Clone()
 	}
 
 	return nil

+ 1 - 6
pkg/costmodel/router.go

@@ -625,12 +625,7 @@ func (p *Accesses) GetClusterInfoMap(w http.ResponseWriter, r *http.Request, ps
 	w.Header().Set("Content-Type", "application/json")
 	w.Header().Set("Access-Control-Allow-Origin", "*")
 
-	data := make(map[string]*clusters.ClusterInfo)
-
-	cm := p.ClusterMap
-	for _, id := range cm.GetClusterIDs() {
-		data[id] = cm.InfoFor(id)
-	}
+	data := p.ClusterMap.AsMap()
 
 	w.Write(WrapData(data, nil))
 }