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  }