github.com/looshlee/beatles@v0.0.0-20220727174639-742810ab631c/pkg/fqdn/name_manager_test.go (about)

     1  // Copyright 2018 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 fqdn
    18  
    19  import (
    20  	"context"
    21  	"net"
    22  	"sync"
    23  	"time"
    24  
    25  	"github.com/cilium/cilium/pkg/policy/api"
    26  	"github.com/miekg/dns"
    27  
    28  	. "gopkg.in/check.v1"
    29  )
    30  
    31  // force a fail if something calls this function
    32  func lookupFail(c *C, dnsNames []string) (DNSIPs map[string]*DNSIPRecords, errorDNSNames map[string]error) {
    33  	c.Error("Lookup function called when it should not")
    34  	return nil, nil
    35  }
    36  
    37  // TestNameManagerCIDRGeneration tests rule generation output:
    38  // add a rule, get correct IP4/6 in ToCIDRSet
    39  // add a rule, lookup twice, get correct IP4/6 in TOCIDRSet after change
    40  // add a rule w/ToCIDRSet, get correct IP4/6 and old rules
    41  // add a rule, get same UUID label on repeat generations
    42  func (ds *FQDNTestSuite) TestNameManagerCIDRGeneration(c *C) {
    43  	var (
    44  		selIPMap map[api.FQDNSelector][]net.IP
    45  
    46  		nameManager = NewNameManager(Config{
    47  			MinTTL: 1,
    48  			Cache:  NewDNSCache(0),
    49  
    50  			LookupDNSNames: func(dnsNames []string) (DNSIPs map[string]*DNSIPRecords, errorDNSNames map[string]error) {
    51  				return lookupFail(c, dnsNames)
    52  			},
    53  
    54  			UpdateSelectors: func(ctx context.Context, selectorIPMapping map[api.FQDNSelector][]net.IP, selectorsWithoutIPs []api.FQDNSelector) (*sync.WaitGroup, error) {
    55  				for k, v := range selectorIPMapping {
    56  					selIPMap[k] = v
    57  				}
    58  				return &sync.WaitGroup{}, nil
    59  			},
    60  		})
    61  	)
    62  
    63  	// add rules
    64  	nameManager.Lock()
    65  	ids := nameManager.RegisterForIdentityUpdatesLocked(ciliumIOSel)
    66  	nameManager.Unlock()
    67  	c.Assert(len(ids), Equals, 0)
    68  	c.Assert(ids, Not(IsNil))
    69  
    70  	// poll DNS once, check that we only generate 1 rule (for 1 IP) and that we
    71  	// still have 1 ToFQDN rule, and that the IP is correct
    72  	selIPMap = make(map[api.FQDNSelector][]net.IP)
    73  	_, err := nameManager.UpdateGenerateDNS(context.Background(), time.Now(), map[string]*DNSIPRecords{dns.Fqdn("cilium.io"): {TTL: 60, IPs: []net.IP{net.ParseIP("1.1.1.1")}}})
    74  	c.Assert(err, IsNil, Commentf("Error mapping selectors to IPs"))
    75  	c.Assert(len(selIPMap), Equals, 1, Commentf("Incorrect length for testCase with single ToFQDNs entry"))
    76  
    77  	expectedIPs := []net.IP{net.ParseIP("1.1.1.1")}
    78  	ips, _ := selIPMap[ciliumIOSel]
    79  	c.Assert(ips[0].Equal(expectedIPs[0]), Equals, true)
    80  
    81  	// poll DNS once, check that we only generate 1 rule (for 2 IPs that we
    82  	// inserted) and that we still have 1 ToFQDN rule, and that the IP, now
    83  	// different, is correct
    84  	selIPMap = make(map[api.FQDNSelector][]net.IP)
    85  	_, err = nameManager.UpdateGenerateDNS(context.Background(), time.Now(), map[string]*DNSIPRecords{dns.Fqdn("cilium.io"): {TTL: 60, IPs: []net.IP{net.ParseIP("2.2.2.2")}}})
    86  	c.Assert(err, IsNil, Commentf("Error generating IP CIDR rules"))
    87  	c.Assert(len(selIPMap), Equals, 1, Commentf("Only one entry per FQDNSelector should be present"))
    88  	expectedIPs = []net.IP{net.ParseIP("1.1.1.1"), net.ParseIP("2.2.2.2")}
    89  	c.Assert(selIPMap[ciliumIOSel][0].Equal(expectedIPs[0]), Equals, true)
    90  	c.Assert(selIPMap[ciliumIOSel][1].Equal(expectedIPs[1]), Equals, true)
    91  }
    92  
    93  // Test that all IPs are updated when one is
    94  func (ds *FQDNTestSuite) TestNameManagerMultiIPUpdate(c *C) {
    95  	var (
    96  		selIPMap map[api.FQDNSelector][]net.IP
    97  
    98  		nameManager = NewNameManager(Config{
    99  			MinTTL: 1,
   100  			Cache:  NewDNSCache(0),
   101  
   102  			LookupDNSNames: func(dnsNames []string) (DNSIPs map[string]*DNSIPRecords, errorDNSNames map[string]error) {
   103  				return lookupFail(c, dnsNames)
   104  			},
   105  
   106  			UpdateSelectors: func(ctx context.Context, selectorIPMapping map[api.FQDNSelector][]net.IP, selectorsWithoutIPs []api.FQDNSelector) (*sync.WaitGroup, error) {
   107  				for k, v := range selectorIPMapping {
   108  					selIPMap[k] = v
   109  				}
   110  				return &sync.WaitGroup{}, nil
   111  			},
   112  		})
   113  	)
   114  
   115  	// add rules
   116  	selectorsToAdd := api.FQDNSelectorSlice{ciliumIOSel, githubSel}
   117  	nameManager.Lock()
   118  	for _, sel := range selectorsToAdd {
   119  		ids := nameManager.RegisterForIdentityUpdatesLocked(sel)
   120  		c.Assert(ids, Not(IsNil))
   121  	}
   122  	nameManager.Unlock()
   123  
   124  	// poll DNS once, check that we only generate 1 IP for cilium.io
   125  	selIPMap = make(map[api.FQDNSelector][]net.IP)
   126  	_, err := nameManager.UpdateGenerateDNS(context.Background(), time.Now(), map[string]*DNSIPRecords{dns.Fqdn("cilium.io"): {TTL: 60, IPs: []net.IP{net.ParseIP("1.1.1.1")}}})
   127  	c.Assert(err, IsNil, Commentf("Error mapping selectors to IPs"))
   128  	c.Assert(len(selIPMap), Equals, 1, Commentf("Incorrect number of plumbed FQDN selectors"))
   129  	c.Assert(selIPMap[ciliumIOSel][0].Equal(net.ParseIP("1.1.1.1")), Equals, true)
   130  
   131  	// poll DNS once, check that we only generate 3 IPs, 2 cached from before and 1 new one for github.com
   132  	selIPMap = make(map[api.FQDNSelector][]net.IP)
   133  	_, err = nameManager.UpdateGenerateDNS(context.Background(), time.Now(), map[string]*DNSIPRecords{
   134  		dns.Fqdn("cilium.io"):  {TTL: 60, IPs: []net.IP{net.ParseIP("2.2.2.2")}},
   135  		dns.Fqdn("github.com"): {TTL: 60, IPs: []net.IP{net.ParseIP("3.3.3.3")}}})
   136  	c.Assert(err, IsNil, Commentf("Error mapping selectors to IPs"))
   137  	c.Assert(len(selIPMap), Equals, 2, Commentf("More than 2 FQDN selectors while only 2 were added"))
   138  	c.Assert(len(selIPMap[ciliumIOSel]), Equals, 2, Commentf("Incorrect number of IPs for cilium.io selector"))
   139  	c.Assert(len(selIPMap[githubSel]), Equals, 1, Commentf("Incorrect number of IPs for github.com selector"))
   140  	c.Assert(selIPMap[ciliumIOSel][0].Equal(net.ParseIP("1.1.1.1")), Equals, true, Commentf("Incorrect IP mapping to FQDN"))
   141  	c.Assert(selIPMap[ciliumIOSel][1].Equal(net.ParseIP("2.2.2.2")), Equals, true, Commentf("Incorrect IP mapping to FQDN"))
   142  	c.Assert(selIPMap[githubSel][0].Equal(net.ParseIP("3.3.3.3")), Equals, true, Commentf("Incorrect IP mapping to FQDN"))
   143  
   144  	// poll DNS once, check that we only generate 4 IPs, 2 cilium.io cached IPs, 1 cached github.com IP, 1 new github.com IP
   145  	selIPMap = make(map[api.FQDNSelector][]net.IP)
   146  	_, err = nameManager.UpdateGenerateDNS(context.Background(), time.Now(), map[string]*DNSIPRecords{
   147  		dns.Fqdn("cilium.io"):  {TTL: 60, IPs: []net.IP{net.ParseIP("2.2.2.2")}},
   148  		dns.Fqdn("github.com"): {TTL: 60, IPs: []net.IP{net.ParseIP("4.4.4.4")}}})
   149  	c.Assert(err, IsNil, Commentf("Error mapping selectors to IPs"))
   150  	c.Assert(len(selIPMap[ciliumIOSel]), Equals, 2, Commentf("Incorrect number of IPs for cilium.io selector"))
   151  	c.Assert(len(selIPMap[githubSel]), Equals, 2, Commentf("Incorrect number of IPs for github.com selector"))
   152  	c.Assert(selIPMap[ciliumIOSel][0].Equal(net.ParseIP("1.1.1.1")), Equals, true, Commentf("Incorrect IP mapping to FQDN"))
   153  	c.Assert(selIPMap[ciliumIOSel][1].Equal(net.ParseIP("2.2.2.2")), Equals, true, Commentf("Incorrect IP mapping to FQDN"))
   154  	c.Assert(selIPMap[githubSel][0].Equal(net.ParseIP("3.3.3.3")), Equals, true, Commentf("Incorrect IP mapping to FQDN"))
   155  	c.Assert(selIPMap[githubSel][1].Equal(net.ParseIP("4.4.4.4")), Equals, true, Commentf("Incorrect IP mapping to FQDN"))
   156  
   157  	// Second registration fails because IdenitityAllocator is not initialized
   158  	nameManager.Lock()
   159  	ids := nameManager.RegisterForIdentityUpdatesLocked(githubSel)
   160  	c.Assert(ids, IsNil)
   161  
   162  	nameManager.UnregisterForIdentityUpdatesLocked(githubSel)
   163  	_, exists := nameManager.allSelectors[githubSel]
   164  	c.Assert(exists, Equals, false)
   165  
   166  	nameManager.UnregisterForIdentityUpdatesLocked(ciliumIOSel)
   167  	_, exists = nameManager.allSelectors[ciliumIOSel]
   168  	c.Assert(exists, Equals, false)
   169  	nameManager.Unlock()
   170  
   171  }