github.com/elfadel/cilium@v1.6.12/pkg/fqdn/dnspoller_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  
    24  	"github.com/cilium/cilium/pkg/policy/api"
    25  	"github.com/miekg/dns"
    26  
    27  	. "gopkg.in/check.v1"
    28  )
    29  
    30  var (
    31  	ciliumIOSel = api.FQDNSelector{
    32  		MatchName: "cilium.io",
    33  	}
    34  
    35  	githubSel = api.FQDNSelector{
    36  		MatchName: "github.com",
    37  	}
    38  
    39  	ciliumIOSelMatchPattern = api.FQDNSelector{
    40  		MatchPattern: "*cilium.io.",
    41  	}
    42  )
    43  
    44  func (ds *FQDNTestSuite) TestNameManagerSelectorHandling(c *C) {
    45  	var testCases = []struct {
    46  		desc                        string
    47  		selectorsToAdd              api.FQDNSelectorSlice
    48  		selectorsToDelete           api.FQDNSelectorSlice
    49  		lookupIterationsAfterAdd    int // # of times to call LookupUpdateDNS after add but before delete
    50  		lookupIterationsAfterDelete int // # of times to call LookupUpdateDNS after delete
    51  		checkFunc                   func(lookups map[string]int, nameManager *NameManager)
    52  	}{
    53  		{
    54  			desc:                        "Lookup a name when added in a rule",
    55  			lookupIterationsAfterAdd:    1,
    56  			lookupIterationsAfterDelete: 0,
    57  			checkFunc: func(lookups map[string]int, nameManager *NameManager) {
    58  				c.Assert(len(lookups), Equals, 1, Commentf("More than one DNS name was looked up for a rule with 1 DNS name"))
    59  				for _, name := range []string{dns.Fqdn("cilium.io")} {
    60  					c.Assert(lookups[name], Not(Equals), 0, Commentf("No lookups for DNS name %s in rule", name))
    61  					c.Assert(lookups[name], Equals, 1, Commentf("More than one DNS lookup was triggered for the same DNS name %s", name))
    62  				}
    63  			},
    64  			selectorsToAdd:    api.FQDNSelectorSlice{ciliumIOSel},
    65  			selectorsToDelete: nil,
    66  		},
    67  		{
    68  			desc:                        "Lookup each name once when 2 are added in a rule",
    69  			lookupIterationsAfterAdd:    1,
    70  			lookupIterationsAfterDelete: 0,
    71  			checkFunc: func(lookups map[string]int, nameManager *NameManager) {
    72  				c.Assert(len(lookups), Equals, 2, Commentf("More than two DNS names was looked up for a rule with 2 DNS name"))
    73  				for _, name := range []string{dns.Fqdn("cilium.io"), dns.Fqdn("github.com")} {
    74  					c.Assert(lookups[name], Not(Equals), 0, Commentf("No lookups for DNS name %s in rule", name))
    75  					c.Assert(lookups[name], Equals, 1, Commentf("More than one DNS lookup was triggered for the same DNS name %s", name))
    76  				}
    77  			},
    78  			selectorsToAdd:    api.FQDNSelectorSlice{ciliumIOSel, githubSel},
    79  			selectorsToDelete: nil,
    80  		},
    81  		{
    82  			desc:                        "Lookup name once when two rules refer to it",
    83  			lookupIterationsAfterAdd:    1,
    84  			lookupIterationsAfterDelete: 0,
    85  			checkFunc: func(lookups map[string]int, nameManager *NameManager) {
    86  				c.Assert(len(lookups), Equals, 1, Commentf("More than one DNS name was looked up for a rule with 1 DNS name"))
    87  				for _, name := range []string{dns.Fqdn("cilium.io")} {
    88  					c.Assert(lookups[name], Not(Equals), 0, Commentf("No lookups for DNS name %s in rule", name))
    89  					c.Assert(lookups[name], Equals, 1, Commentf("More than one DNS lookup was triggered for the same DNS name %s", name))
    90  				}
    91  			},
    92  			selectorsToAdd:    api.FQDNSelectorSlice{ciliumIOSel, ciliumIOSel},
    93  			selectorsToDelete: nil,
    94  		},
    95  		{
    96  			desc:                        "No lookups after removing all rules",
    97  			lookupIterationsAfterAdd:    0,
    98  			lookupIterationsAfterDelete: 1,
    99  			checkFunc: func(lookups map[string]int, nameManager *NameManager) {
   100  				c.Assert(len(lookups), Equals, 0, Commentf("DNS lookups occurred after removing all rules"))
   101  			},
   102  			selectorsToAdd:    api.FQDNSelectorSlice{ciliumIOSel},
   103  			selectorsToDelete: api.FQDNSelectorSlice{ciliumIOSel},
   104  		},
   105  		{
   106  			desc:                        "One lookup for a name after removing one of two referring FQDNSelectors",
   107  			lookupIterationsAfterAdd:    0,
   108  			lookupIterationsAfterDelete: 1,
   109  			checkFunc: func(lookups map[string]int, nameManager *NameManager) {
   110  				c.Assert(len(nameManager.GetDNSNames()), Equals, 0, Commentf("No more DNS names should be present since tracking of FQDNSelectors is done via set (adding two of the same selector is equivalent to adding one)"))
   111  				c.Assert(len(lookups), Equals, 0, Commentf("Incorrect number of lookups for single name with a single FQDNSelector"))
   112  			},
   113  			selectorsToAdd:    api.FQDNSelectorSlice{ciliumIOSel, ciliumIOSel},
   114  			selectorsToDelete: api.FQDNSelectorSlice{ciliumIOSel},
   115  		},
   116  		{
   117  			desc:                        "One lookup for a name after removing an unrelated rule",
   118  			lookupIterationsAfterAdd:    0,
   119  			lookupIterationsAfterDelete: 1,
   120  			checkFunc: func(lookups map[string]int, nameManager *NameManager) {
   121  				c.Assert(len(nameManager.GetDNSNames()), Equals, 1, Commentf("Incorrect number of DNS targets for single name with a single referring rule"))
   122  				c.Assert(len(lookups), Equals, 1, Commentf("Incorrect number of lookups for single name with a single referring rule"))
   123  				for _, name := range []string{dns.Fqdn("cilium.io")} {
   124  					c.Assert(lookups[name], Not(Equals), 0, Commentf("No lookups for DNS name %s in rule", name))
   125  					c.Assert(lookups[name], Equals, 1, Commentf("More than one DNS lookup was triggered for the same DNS name %s", name))
   126  				}
   127  			},
   128  			selectorsToAdd:    api.FQDNSelectorSlice{ciliumIOSel, githubSel},
   129  			selectorsToDelete: api.FQDNSelectorSlice{githubSel},
   130  		},
   131  	}
   132  
   133  	for _, testCase := range testCases {
   134  		c.Logf("Testcase: %s", testCase.desc)
   135  		var (
   136  			lookups = make(map[string]int)
   137  
   138  			cfg = Config{
   139  				MinTTL: 1,
   140  				Cache:  NewDNSCache(0),
   141  
   142  				LookupDNSNames: func(dnsNames []string) (DNSIPs map[string]*DNSIPRecords, errorDNSNames map[string]error) {
   143  					return lookupDNSNames(ipLookups, lookups, dnsNames), nil
   144  				},
   145  
   146  				UpdateSelectors: func(context.Context, map[api.FQDNSelector][]net.IP, []api.FQDNSelector) (*sync.WaitGroup, error) {
   147  					return &sync.WaitGroup{}, nil
   148  				},
   149  			}
   150  
   151  			nameManager = NewNameManager(cfg)
   152  			poller      = NewDNSPoller(cfg, nameManager)
   153  		)
   154  
   155  		nameManager.Lock()
   156  		for _, fqdnSel := range testCase.selectorsToAdd {
   157  			nameManager.RegisterForIdentityUpdatesLocked(fqdnSel)
   158  		}
   159  		nameManager.Unlock()
   160  		for i := testCase.lookupIterationsAfterAdd; i > 0; i-- {
   161  			err := poller.LookupUpdateDNS(context.Background())
   162  			c.Assert(err, IsNil, Commentf("Error running DNS lookups"))
   163  		}
   164  
   165  		// delete rules listed in the test case (note: we don't delete any unless
   166  		// they are listed)
   167  		nameManager.Lock()
   168  		for _, fqdnSel := range testCase.selectorsToDelete {
   169  			nameManager.UnregisterForIdentityUpdatesLocked(fqdnSel)
   170  		}
   171  		nameManager.Unlock()
   172  		for i := testCase.lookupIterationsAfterDelete; i > 0; i-- {
   173  			err := poller.LookupUpdateDNS(context.Background())
   174  			c.Assert(err, IsNil, Commentf("Error running DNS lookups"))
   175  		}
   176  
   177  		// call the testcase checkFunc, it will assert everything relevant to the test
   178  		testCase.checkFunc(lookups, nameManager)
   179  	}
   180  }