istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/autoregistration/connections.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 autoregistration 16 17 import ( 18 "sync" 19 "time" 20 21 "k8s.io/apimachinery/pkg/types" 22 23 "istio.io/istio/pilot/pkg/model" 24 "istio.io/istio/pkg/maps" 25 ) 26 27 // connection from a proxy to a control plane. 28 // This interface exists to avoid circular reference to xds.Connection as well 29 // as keeps the API surface scoped to what we need for auto-registration logic. 30 type connection interface { 31 ID() string 32 Proxy() *model.Proxy 33 ConnectedAt() time.Time 34 Stop() 35 } 36 37 // a single proxy may have multiple connections, so we track them here 38 // when a WorkloadGroup is deleted, we can force disconnects 39 // when OnDisconnect occurs, we only trigger cleanup when there are no more connections for that proxy 40 type adsConnections struct { 41 sync.Mutex 42 43 // keyed by proxy id, then connection id 44 byProxy map[proxyKey]map[string]connection 45 } 46 47 func newAdsConnections() *adsConnections { 48 return &adsConnections{byProxy: map[proxyKey]map[string]connection{}} 49 } 50 51 func (m *adsConnections) ConnectionsForGroup(wg types.NamespacedName) []connection { 52 // collect the proxies that should be disconnected (don't remove them, OnDisconnect will) 53 m.Lock() 54 defer m.Unlock() 55 var conns []connection 56 for key, connections := range m.byProxy { 57 if key.GroupName == wg.Name && key.Namespace == wg.Namespace { 58 conns = append(conns, maps.Values(connections)...) 59 } 60 } 61 return conns 62 } 63 64 func (m *adsConnections) Connect(conn connection) { 65 m.Lock() 66 defer m.Unlock() 67 k := makeProxyKey(conn.Proxy()) 68 69 connections := m.byProxy[k] 70 if connections == nil { 71 connections = make(map[string]connection) 72 m.byProxy[k] = connections 73 } 74 connections[conn.ID()] = conn 75 } 76 77 // Disconnect tracks disconnect events of ads clients. 78 // Returns false once there are no more connections for the given proxy. 79 func (m *adsConnections) Disconnect(conn connection) bool { 80 m.Lock() 81 defer m.Unlock() 82 83 k := makeProxyKey(conn.Proxy()) 84 connections := m.byProxy[k] 85 if connections == nil { 86 return false 87 } 88 89 id := conn.ID() 90 delete(connections, id) 91 if len(connections) == 0 { 92 delete(m.byProxy, k) 93 return false 94 } 95 96 return true 97 } 98 99 // keys required to uniquely ID a single proxy 100 type proxyKey struct { 101 Network string 102 IP string 103 GroupName string 104 Namespace string 105 } 106 107 func makeProxyKey(proxy *model.Proxy) proxyKey { 108 return proxyKey{ 109 Network: string(proxy.Metadata.Network), 110 IP: proxy.IPAddresses[0], 111 GroupName: proxy.Metadata.AutoRegisterGroup, 112 Namespace: proxy.Metadata.Namespace, 113 } 114 }