istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/model/addressmap.go (about) 1 // Copyright Istio Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package model 16 17 import ( 18 "sync" 19 20 "istio.io/istio/pkg/cluster" 21 ) 22 23 // AddressMap provides a thread-safe mapping of addresses for each Kubernetes cluster. 24 type AddressMap struct { 25 // Addresses hold the underlying map. Most code should only access this through the available methods. 26 // Should only be used by tests and construction/initialization logic, where there is no concern 27 // for race conditions. 28 Addresses map[cluster.ID][]string 29 30 // NOTE: The copystructure library is not able to copy unexported fields, so the mutex will not be copied. 31 mutex sync.RWMutex 32 } 33 34 func (m *AddressMap) Len() int { 35 if m == nil { 36 return 0 37 } 38 m.mutex.RLock() 39 defer m.mutex.RUnlock() 40 41 return len(m.Addresses) 42 } 43 44 func (m *AddressMap) DeepCopy() *AddressMap { 45 if m == nil { 46 return nil 47 } 48 return &AddressMap{ 49 Addresses: m.GetAddresses(), 50 } 51 } 52 53 // GetAddresses returns the mapping of clusters to addresses. 54 func (m *AddressMap) GetAddresses() map[cluster.ID][]string { 55 if m == nil { 56 return nil 57 } 58 59 m.mutex.RLock() 60 defer m.mutex.RUnlock() 61 62 if m.Addresses == nil { 63 return nil 64 } 65 66 out := make(map[cluster.ID][]string) 67 for k, v := range m.Addresses { 68 if v == nil { 69 out[k] = nil 70 } else { 71 out[k] = append([]string{}, v...) 72 } 73 } 74 return out 75 } 76 77 // SetAddresses sets the addresses per cluster. 78 func (m *AddressMap) SetAddresses(addrs map[cluster.ID][]string) { 79 if len(addrs) == 0 { 80 addrs = nil 81 } 82 83 m.mutex.Lock() 84 m.Addresses = addrs 85 m.mutex.Unlock() 86 } 87 88 func (m *AddressMap) GetAddressesFor(c cluster.ID) []string { 89 if m == nil { 90 return nil 91 } 92 93 m.mutex.RLock() 94 defer m.mutex.RUnlock() 95 96 if m.Addresses == nil { 97 return nil 98 } 99 100 // Copy the Addresses array. 101 return append([]string{}, m.Addresses[c]...) 102 } 103 104 func (m *AddressMap) SetAddressesFor(c cluster.ID, addresses []string) *AddressMap { 105 m.mutex.Lock() 106 defer m.mutex.Unlock() 107 108 if len(addresses) == 0 { 109 // Setting an empty array for the cluster. Remove the entry for the cluster if it exists. 110 if m.Addresses != nil { 111 delete(m.Addresses, c) 112 113 // Delete the map if there's nothing left. 114 if len(m.Addresses) == 0 { 115 m.Addresses = nil 116 } 117 } 118 } else { 119 // Create the map if it doesn't already exist. 120 if m.Addresses == nil { 121 m.Addresses = make(map[cluster.ID][]string) 122 } 123 m.Addresses[c] = addresses 124 } 125 return m 126 } 127 128 func (m *AddressMap) AddAddressesFor(c cluster.ID, addresses []string) *AddressMap { 129 if len(addresses) == 0 { 130 return m 131 } 132 133 m.mutex.Lock() 134 defer m.mutex.Unlock() 135 136 // Create the map if nil. 137 if m.Addresses == nil { 138 m.Addresses = make(map[cluster.ID][]string) 139 } 140 141 m.Addresses[c] = append(m.Addresses[c], addresses...) 142 return m 143 } 144 145 func (m *AddressMap) ForEach(fn func(c cluster.ID, addresses []string)) { 146 if m == nil { 147 return 148 } 149 150 m.mutex.RLock() 151 defer m.mutex.RUnlock() 152 153 if m.Addresses == nil { 154 return 155 } 156 157 for c, addresses := range m.Addresses { 158 fn(c, addresses) 159 } 160 }