github.phpd.cn/cilium/cilium@v1.6.12/pkg/identity/cache/allocation_test.go (about) 1 // Copyright 2016-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 // +build !privileged_tests 16 17 package cache 18 19 import ( 20 "context" 21 "time" 22 23 "github.com/cilium/cilium/pkg/allocator" 24 "github.com/cilium/cilium/pkg/checker" 25 "github.com/cilium/cilium/pkg/identity" 26 "github.com/cilium/cilium/pkg/idpool" 27 "github.com/cilium/cilium/pkg/kvstore" 28 "github.com/cilium/cilium/pkg/labels" 29 "github.com/cilium/cilium/pkg/lock" 30 31 . "gopkg.in/check.v1" 32 ) 33 34 func (s *IdentityCacheTestSuite) TestAllocateIdentityReserved(c *C) { 35 var ( 36 lbls labels.Labels 37 i *identity.Identity 38 isNew bool 39 err error 40 ) 41 42 lbls = labels.Labels{ 43 labels.IDNameHost: labels.NewLabel(labels.IDNameHost, "", labels.LabelSourceReserved), 44 } 45 c.Assert(IdentityAllocationIsLocal(lbls), Equals, true) 46 i, isNew, err = AllocateIdentity(context.Background(), nil, lbls) 47 c.Assert(err, IsNil) 48 c.Assert(i.ID, Equals, identity.ReservedIdentityHost) 49 c.Assert(isNew, Equals, false) 50 51 lbls = labels.Labels{ 52 labels.IDNameWorld: labels.NewLabel(labels.IDNameWorld, "", labels.LabelSourceReserved), 53 } 54 c.Assert(IdentityAllocationIsLocal(lbls), Equals, true) 55 i, isNew, err = AllocateIdentity(context.Background(), nil, lbls) 56 c.Assert(err, IsNil) 57 c.Assert(i.ID, Equals, identity.ReservedIdentityWorld) 58 c.Assert(isNew, Equals, false) 59 60 c.Assert(IdentityAllocationIsLocal(labels.LabelHealth), Equals, true) 61 i, isNew, err = AllocateIdentity(context.Background(), nil, labels.LabelHealth) 62 c.Assert(err, IsNil) 63 c.Assert(i.ID, Equals, identity.ReservedIdentityHealth) 64 c.Assert(isNew, Equals, false) 65 66 lbls = labels.Labels{ 67 labels.IDNameInit: labels.NewLabel(labels.IDNameInit, "", labels.LabelSourceReserved), 68 } 69 c.Assert(IdentityAllocationIsLocal(lbls), Equals, true) 70 i, isNew, err = AllocateIdentity(context.Background(), nil, lbls) 71 c.Assert(err, IsNil) 72 c.Assert(i.ID, Equals, identity.ReservedIdentityInit) 73 c.Assert(isNew, Equals, false) 74 75 lbls = labels.Labels{ 76 labels.IDNameUnmanaged: labels.NewLabel(labels.IDNameUnmanaged, "", labels.LabelSourceReserved), 77 } 78 c.Assert(IdentityAllocationIsLocal(lbls), Equals, true) 79 i, isNew, err = AllocateIdentity(context.Background(), nil, lbls) 80 c.Assert(err, IsNil) 81 c.Assert(i.ID, Equals, identity.ReservedIdentityUnmanaged) 82 c.Assert(isNew, Equals, false) 83 } 84 85 type IdentityAllocatorSuite struct{} 86 87 type IdentityAllocatorEtcdSuite struct { 88 IdentityAllocatorSuite 89 } 90 91 var _ = Suite(&IdentityAllocatorEtcdSuite{}) 92 93 func (e *IdentityAllocatorEtcdSuite) SetUpTest(c *C) { 94 kvstore.SetupDummy("etcd") 95 } 96 97 type IdentityAllocatorConsulSuite struct { 98 IdentityAllocatorSuite 99 } 100 101 var _ = Suite(&IdentityAllocatorConsulSuite{}) 102 103 func (e *IdentityAllocatorConsulSuite) SetUpTest(c *C) { 104 kvstore.SetupDummy("consul") 105 } 106 107 type dummyOwner struct { 108 updated chan identity.NumericIdentity 109 mutex lock.Mutex 110 cache IdentityCache 111 } 112 113 func newDummyOwner() *dummyOwner { 114 return &dummyOwner{ 115 cache: IdentityCache{}, 116 updated: make(chan identity.NumericIdentity, 1024), 117 } 118 } 119 120 func (d *dummyOwner) UpdateIdentities(added, deleted IdentityCache) { 121 d.mutex.Lock() 122 log.Debugf("Dummy UpdateIdentities(added: %v, deleted: %v)", added, deleted) 123 for id, lbls := range added { 124 d.cache[id] = lbls 125 d.updated <- id 126 } 127 for id := range deleted { 128 delete(d.cache, id) 129 d.updated <- id 130 } 131 d.mutex.Unlock() 132 } 133 134 func (d *dummyOwner) GetIdentity(id identity.NumericIdentity) labels.LabelArray { 135 d.mutex.Lock() 136 defer d.mutex.Unlock() 137 return d.cache[id] 138 } 139 140 func (d *dummyOwner) GetNodeSuffix() string { 141 return "foo" 142 } 143 144 // WaitUntilID waits until an update event is received for the 145 // 'target' identity and returns the number of events processed to get 146 // there. Returns 0 in case of 'd.updated' channel is closed or 147 // nothing is received from that channel in 60 seconds. 148 func (d *dummyOwner) WaitUntilID(target identity.NumericIdentity) int { 149 rounds := 0 150 for { 151 select { 152 case nid, ok := <-d.updated: 153 if !ok { 154 // updates channel closed 155 return 0 156 } 157 rounds++ 158 if nid == target { 159 return rounds 160 } 161 case <-time.After(60 * time.Second): 162 // Timed out waiting for KV-store events 163 return 0 164 } 165 } 166 } 167 168 func (ias *IdentityAllocatorSuite) TestEventWatcherBatching(c *C) { 169 owner := newDummyOwner() 170 events := make(allocator.AllocatorEventChan, 1024) 171 var watcher identityWatcher 172 173 watcher.watch(owner, events) 174 defer close(watcher.stopChan) 175 176 lbls := labels.NewLabelsFromSortedList("id=foo") 177 key := GlobalIdentity{lbls.LabelArray()} 178 179 for i := 1024; i < 1034; i++ { 180 events <- allocator.AllocatorEvent{ 181 Typ: kvstore.EventTypeCreate, 182 ID: idpool.ID(i), 183 Key: key, 184 } 185 } 186 c.Assert(owner.WaitUntilID(1033), Not(Equals), 0) 187 c.Assert(owner.GetIdentity(identity.NumericIdentity(1033)), checker.DeepEquals, lbls.LabelArray()) 188 for i := 1024; i < 1034; i++ { 189 events <- allocator.AllocatorEvent{ 190 Typ: kvstore.EventTypeDelete, 191 ID: idpool.ID(i), 192 } 193 } 194 c.Assert(owner.WaitUntilID(1033), Not(Equals), 0) 195 for i := 2048; i < 2058; i++ { 196 events <- allocator.AllocatorEvent{ 197 Typ: kvstore.EventTypeCreate, 198 ID: idpool.ID(i), 199 Key: key, 200 } 201 } 202 for i := 2048; i < 2053; i++ { 203 events <- allocator.AllocatorEvent{ 204 Typ: kvstore.EventTypeDelete, 205 ID: idpool.ID(i), 206 } 207 } 208 c.Assert(owner.WaitUntilID(2052), Not(Equals), 0) 209 c.Assert(owner.GetIdentity(identity.NumericIdentity(2052)), IsNil) // Pooling removed the add 210 211 for i := 2053; i < 2058; i++ { 212 events <- allocator.AllocatorEvent{ 213 Typ: kvstore.EventTypeDelete, 214 ID: idpool.ID(i), 215 } 216 } 217 c.Assert(owner.WaitUntilID(2057), Not(Equals), 0) 218 } 219 220 func (ias *IdentityAllocatorSuite) TestGetIdentityCache(c *C) { 221 identity.InitWellKnownIdentities() 222 // The nils are only used by k8s CRD identities. We default to kvstore. 223 <-InitIdentityAllocator(newDummyOwner(), nil, nil) 224 defer Close() 225 defer IdentityAllocator.DeleteAllKeys() 226 227 cache := GetIdentityCache() 228 _, ok := cache[identity.ReservedCiliumKVStore] 229 c.Assert(ok, Equals, true) 230 } 231 232 func (ias *IdentityAllocatorSuite) TestAllocator(c *C) { 233 lbls1 := labels.NewLabelsFromSortedList("blah=%%//!!;id=foo;user=anna") 234 lbls2 := labels.NewLabelsFromSortedList("id=bar;user=anna") 235 lbls3 := labels.NewLabelsFromSortedList("id=bar;user=susan") 236 237 owner := newDummyOwner() 238 identity.InitWellKnownIdentities() 239 // The nils are only used by k8s CRD identities. We default to kvstore. 240 <-InitIdentityAllocator(owner, nil, nil) 241 defer Close() 242 defer IdentityAllocator.DeleteAllKeys() 243 244 id1a, isNew, err := AllocateIdentity(context.Background(), nil, lbls1) 245 c.Assert(id1a, Not(IsNil)) 246 c.Assert(err, IsNil) 247 c.Assert(isNew, Equals, true) 248 // Wait for the update event from the KV-store 249 c.Assert(owner.WaitUntilID(id1a.ID), Not(Equals), 0) 250 c.Assert(owner.GetIdentity(id1a.ID), checker.DeepEquals, lbls1.LabelArray()) 251 252 // reuse the same identity 253 id1b, isNew, err := AllocateIdentity(context.Background(), nil, lbls1) 254 c.Assert(id1b, Not(IsNil)) 255 c.Assert(isNew, Equals, false) 256 c.Assert(err, IsNil) 257 c.Assert(id1a.ID, Equals, id1b.ID) 258 259 released, err := Release(context.Background(), nil, id1a) 260 c.Assert(err, IsNil) 261 c.Assert(released, Equals, false) 262 released, err = Release(context.Background(), nil, id1b) 263 c.Assert(err, IsNil) 264 c.Assert(released, Equals, true) 265 // KV-store still keeps the ID even when a single node has released it. 266 // This also means that we should have not received an event from the 267 // KV-store for the deletion of the identity, so it should still be in 268 // owner's cache. 269 c.Assert(owner.GetIdentity(id1a.ID), checker.DeepEquals, lbls1.LabelArray()) 270 271 id1b, isNew, err = AllocateIdentity(context.Background(), nil, lbls1) 272 c.Assert(id1b, Not(IsNil)) 273 c.Assert(err, IsNil) 274 // the value key should not have been removed so the same ID should be 275 // assigned again and it should not be marked as new 276 c.Assert(isNew, Equals, false) 277 c.Assert(id1a.ID, Equals, id1b.ID) 278 // Should still be cached, no new events should have been received. 279 c.Assert(owner.GetIdentity(id1a.ID), checker.DeepEquals, lbls1.LabelArray()) 280 281 identity := LookupIdentityByID(id1b.ID) 282 c.Assert(identity, Not(IsNil)) 283 c.Assert(lbls1, checker.DeepEquals, identity.Labels) 284 285 id2, isNew, err := AllocateIdentity(context.Background(), nil, lbls2) 286 c.Assert(id2, Not(IsNil)) 287 c.Assert(isNew, Equals, true) 288 c.Assert(err, IsNil) 289 c.Assert(id1a.ID, Not(Equals), id2.ID) 290 // Wait for the update event from the KV-store 291 c.Assert(owner.WaitUntilID(id2.ID), Not(Equals), 0) 292 c.Assert(owner.GetIdentity(id2.ID), checker.DeepEquals, lbls2.LabelArray()) 293 294 id3, isNew, err := AllocateIdentity(context.Background(), nil, lbls3) 295 c.Assert(id3, Not(IsNil)) 296 c.Assert(isNew, Equals, true) 297 c.Assert(err, IsNil) 298 c.Assert(id1a.ID, Not(Equals), id3.ID) 299 c.Assert(id2.ID, Not(Equals), id3.ID) 300 // Wait for the update event from the KV-store 301 c.Assert(owner.WaitUntilID(id3.ID), Not(Equals), 0) 302 c.Assert(owner.GetIdentity(id3.ID), checker.DeepEquals, lbls3.LabelArray()) 303 304 released, err = Release(context.Background(), nil, id1b) 305 c.Assert(err, IsNil) 306 c.Assert(released, Equals, true) 307 released, err = Release(context.Background(), nil, id2) 308 c.Assert(err, IsNil) 309 c.Assert(released, Equals, true) 310 released, err = Release(context.Background(), nil, id3) 311 c.Assert(err, IsNil) 312 c.Assert(released, Equals, true) 313 314 IdentityAllocator.DeleteAllKeys() 315 c.Assert(owner.WaitUntilID(id3.ID), Not(Equals), 0) 316 } 317 318 func (ias *IdentityAllocatorSuite) TestLocalAllocation(c *C) { 319 lbls1 := labels.NewLabelsFromSortedList("cidr:192.0.2.3/32") 320 321 owner := newDummyOwner() 322 identity.InitWellKnownIdentities() 323 // The nils are only used by k8s CRD identities. We default to kvstore. 324 <-InitIdentityAllocator(owner, nil, nil) 325 defer Close() 326 defer IdentityAllocator.DeleteAllKeys() 327 328 id, isNew, err := AllocateIdentity(context.Background(), nil, lbls1) 329 c.Assert(id, Not(IsNil)) 330 c.Assert(err, IsNil) 331 c.Assert(isNew, Equals, true) 332 c.Assert(id.ID.HasLocalScope(), Equals, true) 333 // Wait for the update event from the KV-store 334 c.Assert(owner.WaitUntilID(id.ID), Not(Equals), 0) 335 c.Assert(owner.GetIdentity(id.ID), checker.DeepEquals, lbls1.LabelArray()) 336 337 // reuse the same identity 338 id, isNew, err = AllocateIdentity(context.Background(), nil, lbls1) 339 c.Assert(id, Not(IsNil)) 340 c.Assert(err, IsNil) 341 c.Assert(isNew, Equals, false) 342 343 cache := GetIdentityCache() 344 c.Assert(cache[id.ID], Not(IsNil)) 345 346 // 1st Release, not released 347 released, err := Release(context.Background(), nil, id) 348 c.Assert(err, IsNil) 349 c.Assert(released, Equals, false) 350 351 // Identity still exists 352 c.Assert(owner.GetIdentity(id.ID), checker.DeepEquals, lbls1.LabelArray()) 353 354 // 2nd Release, released 355 released, err = Release(context.Background(), nil, id) 356 c.Assert(err, IsNil) 357 c.Assert(released, Equals, true) 358 359 // Wait until the identity is released 360 c.Assert(owner.WaitUntilID(id.ID), Not(Equals), 0) 361 // Identity does not exist any more 362 c.Assert(owner.GetIdentity(id.ID), IsNil) 363 364 cache = GetIdentityCache() 365 c.Assert(cache[id.ID], IsNil) 366 367 id, isNew, err = AllocateIdentity(context.Background(), nil, lbls1) 368 c.Assert(id, Not(IsNil)) 369 c.Assert(err, IsNil) 370 c.Assert(isNew, Equals, true) 371 c.Assert(id.ID.HasLocalScope(), Equals, true) 372 373 released, err = Release(context.Background(), nil, id) 374 c.Assert(err, IsNil) 375 c.Assert(released, Equals, true) 376 377 IdentityAllocator.DeleteAllKeys() 378 c.Assert(owner.WaitUntilID(id.ID), Not(Equals), 0) 379 }