github.com/looshlee/beatles@v0.0.0-20220727174639-742810ab631c/pkg/identity/identitymanager/manager.go (about) 1 // Copyright 2019 Authors of Cilium 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 identitymanager 16 17 import ( 18 "github.com/cilium/cilium/api/v1/models" 19 "github.com/cilium/cilium/pkg/identity" 20 "github.com/cilium/cilium/pkg/lock" 21 "github.com/cilium/cilium/pkg/logging/logfields" 22 23 "github.com/sirupsen/logrus" 24 ) 25 26 var ( 27 // GlobalIdentityManager is a singleton instance of an IdentityManager, used 28 // for easy updating / tracking lifecycles of identities on the local node 29 // without having to pass around a specific instance of an IdentityManager 30 // throughout Cilium. 31 GlobalIdentityManager = NewIdentityManager() 32 ) 33 34 // IdentityManager caches information about a set of identities, currently a 35 // reference count of how many users there are for each identity. 36 type IdentityManager struct { 37 mutex lock.RWMutex 38 identities map[identity.NumericIdentity]*identityMetadata 39 observers map[Observer]struct{} 40 } 41 42 type identityMetadata struct { 43 identity *identity.Identity 44 refCount uint 45 } 46 47 // NewIdentityManager returns an initialized IdentityManager. 48 func NewIdentityManager() *IdentityManager { 49 return &IdentityManager{ 50 identities: make(map[identity.NumericIdentity]*identityMetadata), 51 observers: make(map[Observer]struct{}), 52 } 53 } 54 55 // Add inserts the identity into the GlobalIdentityManager. 56 func Add(identity *identity.Identity) { 57 GlobalIdentityManager.Add(identity) 58 } 59 60 // Remove deletes the identity from the GlobalIdentityManager. 61 func Remove(identity *identity.Identity) { 62 GlobalIdentityManager.Remove(identity) 63 } 64 65 // Add inserts the identity into the identity manager. If the identity is 66 // already in the identity manager, the reference count for the identity is 67 // incremented. 68 func (idm *IdentityManager) Add(identity *identity.Identity) { 69 log.WithFields(logrus.Fields{ 70 logfields.Identity: identity, 71 }).Debug("Adding identity to the identity manager") 72 73 idm.mutex.Lock() 74 defer idm.mutex.Unlock() 75 idm.add(identity) 76 } 77 78 func (idm *IdentityManager) add(identity *identity.Identity) { 79 80 if identity == nil { 81 return 82 } 83 84 idMeta, exists := idm.identities[identity.ID] 85 if !exists { 86 idm.identities[identity.ID] = &identityMetadata{ 87 identity: identity, 88 refCount: 1, 89 } 90 for o := range idm.observers { 91 o.LocalEndpointIdentityAdded(identity) 92 } 93 } else { 94 idMeta.refCount++ 95 } 96 } 97 98 // RemoveOldAddNew removes old from the identity manager and inserts new 99 // into the IdentityManager. 100 // Caller must have previously added the old identity with Add(). 101 // This is a no-op if both identities have the same numeric ID. 102 func (idm *IdentityManager) RemoveOldAddNew(old, new *identity.Identity) { 103 idm.mutex.Lock() 104 defer idm.mutex.Unlock() 105 106 if old == nil && new == nil { 107 return 108 } 109 if old != nil && new != nil && old.ID == new.ID { 110 return 111 } 112 113 log.WithFields(logrus.Fields{ 114 "old": old, 115 "new": new, 116 }).Debug("removing old and adding new identity") 117 118 idm.remove(old) 119 idm.add(new) 120 } 121 122 // RemoveOldAddNew removes old from and inserts new into the 123 // GlobalIdentityManager. 124 func RemoveOldAddNew(old, new *identity.Identity) { 125 GlobalIdentityManager.RemoveOldAddNew(old, new) 126 } 127 128 // Remove deletes the identity from the identity manager. If the identity is 129 // already in the identity manager, the reference count for the identity is 130 // decremented. If the identity is not in the cache, this is a no-op. If the 131 // ref count becomes zero, the identity is removed from the cache. 132 func (idm *IdentityManager) Remove(identity *identity.Identity) { 133 log.WithFields(logrus.Fields{ 134 logfields.Identity: identity, 135 }).Debug("Removing identity from the identity manager") 136 137 idm.mutex.Lock() 138 defer idm.mutex.Unlock() 139 idm.remove(identity) 140 } 141 142 func (idm *IdentityManager) remove(identity *identity.Identity) { 143 144 if identity == nil { 145 return 146 } 147 148 idMeta, exists := idm.identities[identity.ID] 149 if !exists { 150 log.WithFields(logrus.Fields{ 151 logfields.Identity: identity, 152 }).Error("removing identity not added to the identity manager!") 153 return 154 } 155 idMeta.refCount-- 156 if idMeta.refCount == 0 { 157 delete(idm.identities, identity.ID) 158 for o := range idm.observers { 159 o.LocalEndpointIdentityRemoved(identity) 160 } 161 } 162 163 } 164 165 // GetIdentityModels returns the API representation of the IdentityManager. 166 func (idm *IdentityManager) GetIdentityModels() []*models.IdentityEndpoints { 167 idm.mutex.RLock() 168 defer idm.mutex.RUnlock() 169 170 identities := make([]*models.IdentityEndpoints, 0, len(idm.identities)) 171 172 for _, v := range idm.identities { 173 identities = append(identities, &models.IdentityEndpoints{ 174 Identity: v.identity.GetModel(), 175 RefCount: int64(v.refCount), 176 }) 177 } 178 179 return identities 180 } 181 182 func (idm *IdentityManager) subscribe(o Observer) { 183 idm.mutex.Lock() 184 defer idm.mutex.Unlock() 185 idm.observers[o] = struct{}{} 186 } 187 188 // GetIdentityModels returns the API model of all identities in the 189 // GlobalIdentityManager. 190 func GetIdentityModels() []*models.IdentityEndpoints { 191 return GlobalIdentityManager.GetIdentityModels() 192 } 193 194 // IdentitiesModel is a wrapper so that we can implement the sort.Interface 195 // to sort the slice by ID 196 type IdentitiesModel []*models.IdentityEndpoints 197 198 // Less returns true if the element in index `i` is lower than the element 199 // in index `j` 200 func (s IdentitiesModel) Less(i, j int) bool { 201 return s[i].Identity.ID < s[j].Identity.ID 202 } 203 204 // Subscribe adds the specified Observer to the global identity manager, to be 205 // notified upon changes to local identity usage. 206 func Subscribe(o Observer) { 207 GlobalIdentityManager.subscribe(o) 208 }