github.com/noironetworks/cilium-net@v1.6.12/pkg/endpoint/endpoint_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 endpoint
    18  
    19  import (
    20  	"context"
    21  	"reflect"
    22  	"testing"
    23  	"time"
    24  
    25  	"github.com/cilium/cilium/common/addressing"
    26  	"github.com/cilium/cilium/pkg/completion"
    27  	"github.com/cilium/cilium/pkg/datapath"
    28  	"github.com/cilium/cilium/pkg/endpoint/regeneration"
    29  	"github.com/cilium/cilium/pkg/identity"
    30  	"github.com/cilium/cilium/pkg/identity/cache"
    31  	ciliumio "github.com/cilium/cilium/pkg/k8s/apis/cilium.io"
    32  	"github.com/cilium/cilium/pkg/kvstore"
    33  	pkgLabels "github.com/cilium/cilium/pkg/labels"
    34  	"github.com/cilium/cilium/pkg/lock"
    35  	"github.com/cilium/cilium/pkg/metrics"
    36  	monitorAPI "github.com/cilium/cilium/pkg/monitor/api"
    37  	"github.com/cilium/cilium/pkg/policy"
    38  	"github.com/cilium/cilium/pkg/policy/api"
    39  	"github.com/cilium/cilium/pkg/revert"
    40  
    41  	"github.com/prometheus/client_golang/prometheus"
    42  	. "gopkg.in/check.v1"
    43  )
    44  
    45  var (
    46  	IPv6Addr, _ = addressing.NewCiliumIPv6("beef:beef:beef:beef:aaaa:aaaa:1111:1112")
    47  	IPv4Addr, _ = addressing.NewCiliumIPv4("10.11.12.13")
    48  )
    49  
    50  // Hook up gocheck into the "go test" runner.
    51  func Test(t *testing.T) { TestingT(t) }
    52  
    53  type EndpointSuite struct {
    54  	repo *policy.Repository
    55  
    56  	// Metrics
    57  	collectors []prometheus.Collector
    58  }
    59  
    60  // suite can be used by testing.T benchmarks or tests as a mock regeneration.Owner
    61  var suite = EndpointSuite{repo: policy.NewPolicyRepository()}
    62  var _ = Suite(&suite)
    63  
    64  func (s *EndpointSuite) SetUpSuite(c *C) {
    65  	s.repo = policy.NewPolicyRepository()
    66  
    67  	// Register metrics once before running the suite
    68  	_, s.collectors = metrics.CreateConfiguration([]string{"cilium_endpoint_state"})
    69  	metrics.MustRegister(s.collectors...)
    70  }
    71  
    72  func (s *EndpointSuite) TearDownSuite(c *C) {
    73  	// Unregister the metrics after the suite has finished
    74  	for _, c := range s.collectors {
    75  		metrics.Unregister(c)
    76  	}
    77  }
    78  
    79  func (s *EndpointSuite) GetPolicyRepository() *policy.Repository {
    80  	return s.repo
    81  }
    82  
    83  func (s *EndpointSuite) UpdateProxyRedirect(e regeneration.EndpointUpdater, l4 *policy.L4Filter, wg *completion.WaitGroup) (uint16, error, revert.FinalizeFunc, revert.RevertFunc) {
    84  	return 0, nil, nil, nil
    85  }
    86  
    87  func (s *EndpointSuite) RemoveProxyRedirect(e regeneration.EndpointInfoSource, id string, wg *completion.WaitGroup) (error, revert.FinalizeFunc, revert.RevertFunc) {
    88  	return nil, nil, nil
    89  }
    90  
    91  func (s *EndpointSuite) UpdateNetworkPolicy(e regeneration.EndpointUpdater, policy *policy.L4Policy,
    92  	proxyWaitGroup *completion.WaitGroup) (error, revert.RevertFunc) {
    93  	return nil, nil
    94  }
    95  
    96  func (s *EndpointSuite) RemoveNetworkPolicy(e regeneration.EndpointInfoSource) {}
    97  
    98  func (s *EndpointSuite) QueueEndpointBuild(ctx context.Context, epID uint64) (func(), error) {
    99  	return nil, nil
   100  }
   101  
   102  func (s *EndpointSuite) RemoveFromEndpointQueue(epID uint64) {}
   103  
   104  func (s *EndpointSuite) GetCompilationLock() *lock.RWMutex {
   105  	return nil
   106  }
   107  
   108  func (s *EndpointSuite) SendNotification(typ monitorAPI.AgentNotification, text string) error {
   109  	return nil
   110  }
   111  
   112  func (s *EndpointSuite) Datapath() datapath.Datapath {
   113  	return nil
   114  }
   115  
   116  func (s *EndpointSuite) GetNodeSuffix() string {
   117  	return ""
   118  }
   119  
   120  func (s *EndpointSuite) UpdateIdentities(added, deleted cache.IdentityCache) {}
   121  
   122  type testIdentityAllocator struct{}
   123  
   124  func (t *testIdentityAllocator) UpdateIdentities(added, deleted cache.IdentityCache) {}
   125  
   126  func (t *testIdentityAllocator) GetNodeSuffix() string { return "foo" }
   127  
   128  func (s *EndpointSuite) SetUpTest(c *C) {
   129  	/* Required to test endpoint CEP policy model */
   130  	kvstore.SetupDummy("etcd")
   131  	identity.InitWellKnownIdentities()
   132  	// The nils are only used by k8s CRD identities. We default to kvstore.
   133  	<-cache.InitIdentityAllocator(&testIdentityAllocator{}, nil, nil)
   134  }
   135  
   136  func (s *EndpointSuite) TearDownTest(c *C) {
   137  	cache.Close()
   138  	kvstore.Client().Close()
   139  }
   140  
   141  func (s *EndpointSuite) TestEndpointStatus(c *C) {
   142  	eps := NewEndpointStatus()
   143  
   144  	c.Assert(eps.String(), Equals, "OK")
   145  
   146  	sts := &statusLogMsg{
   147  		Status: Status{
   148  			Code: OK,
   149  			Msg:  "BPF Program compiled",
   150  			Type: BPF,
   151  		},
   152  		Timestamp: time.Now(),
   153  	}
   154  	eps.addStatusLog(sts)
   155  	c.Assert(eps.String(), Equals, "OK")
   156  
   157  	sts = &statusLogMsg{
   158  		Status: Status{
   159  			Code: Failure,
   160  			Msg:  "BPF Program failed to compile",
   161  			Type: BPF,
   162  		},
   163  		Timestamp: time.Now(),
   164  	}
   165  	eps.addStatusLog(sts)
   166  	c.Assert(eps.String(), Equals, "Failure")
   167  
   168  	sts = &statusLogMsg{
   169  		Status: Status{
   170  			Code: OK,
   171  			Msg:  "Policy compiled",
   172  			Type: Policy,
   173  		},
   174  		Timestamp: time.Now(),
   175  	}
   176  	eps.addStatusLog(sts)
   177  	c.Assert(eps.String(), Equals, "Failure")
   178  
   179  	// An OK message with priority Other can't hide a High Failure message.
   180  	for i := 0; i <= maxLogs; i++ {
   181  		st := &statusLogMsg{
   182  			Status: Status{
   183  				Code: OK,
   184  				Msg:  "Other thing compiled",
   185  				Type: Other,
   186  			},
   187  			Timestamp: time.Now(),
   188  		}
   189  		eps.addStatusLog(st)
   190  	}
   191  	eps.addStatusLog(sts)
   192  	c.Assert(eps.String(), Equals, "Failure")
   193  
   194  	sts = &statusLogMsg{
   195  		Status: Status{
   196  			Code: Failure,
   197  			Msg:  "Policy failed",
   198  			Type: Policy,
   199  		},
   200  		Timestamp: time.Now(),
   201  	}
   202  	eps.addStatusLog(sts)
   203  	c.Assert(eps.String(), Equals, "Failure")
   204  
   205  	sts = &statusLogMsg{
   206  		Status: Status{
   207  			Code: OK,
   208  			Msg:  "BPF Program compiled",
   209  			Type: BPF,
   210  		},
   211  		Timestamp: time.Now(),
   212  	}
   213  	eps.addStatusLog(sts)
   214  	// BPF might be ok but the policy is still in fail mode.
   215  	c.Assert(eps.String(), Equals, "Failure")
   216  
   217  	sts = &statusLogMsg{
   218  		Status: Status{
   219  			Code: Failure,
   220  			Msg:  "Policy failed",
   221  			Type: Policy,
   222  		},
   223  		Timestamp: time.Now(),
   224  	}
   225  	eps.addStatusLog(sts)
   226  	c.Assert(eps.String(), Equals, "Failure")
   227  
   228  	sts = &statusLogMsg{
   229  		Status: Status{
   230  			Code: OK,
   231  			Msg:  "Policy compiled",
   232  			Type: Policy,
   233  		},
   234  		Timestamp: time.Now(),
   235  	}
   236  	eps.addStatusLog(sts)
   237  	c.Assert(eps.String(), Equals, "OK")
   238  }
   239  
   240  func (s *EndpointSuite) TestEndpointUpdateLabels(c *C) {
   241  	e := NewEndpointWithState(s, 100, StateCreating)
   242  
   243  	// Test that inserting identity labels works
   244  	rev := e.replaceIdentityLabels(pkgLabels.Map2Labels(map[string]string{"foo": "bar", "zip": "zop"}, "cilium"))
   245  	c.Assert(rev, Not(Equals), 0)
   246  	c.Assert(string(e.OpLabels.OrchestrationIdentity.SortedList()), Equals, "cilium:foo=bar;cilium:zip=zop;")
   247  	// Test that nothing changes
   248  	rev = e.replaceIdentityLabels(pkgLabels.Map2Labels(map[string]string{"foo": "bar", "zip": "zop"}, "cilium"))
   249  	c.Assert(rev, Equals, 0)
   250  	c.Assert(string(e.OpLabels.OrchestrationIdentity.SortedList()), Equals, "cilium:foo=bar;cilium:zip=zop;")
   251  	// Remove one label, change the source and value of the other.
   252  	rev = e.replaceIdentityLabels(pkgLabels.Map2Labels(map[string]string{"foo": "zop"}, "nginx"))
   253  	c.Assert(rev, Not(Equals), 0)
   254  	c.Assert(string(e.OpLabels.OrchestrationIdentity.SortedList()), Equals, "nginx:foo=zop;")
   255  
   256  	// Test that inserting information labels works
   257  	e.replaceInformationLabels(pkgLabels.Map2Labels(map[string]string{"foo": "bar", "zip": "zop"}, "cilium"))
   258  	c.Assert(string(e.OpLabels.OrchestrationInfo.SortedList()), Equals, "cilium:foo=bar;cilium:zip=zop;")
   259  	// Remove one label, change the source and value of the other.
   260  	e.replaceInformationLabels(pkgLabels.Map2Labels(map[string]string{"foo": "zop"}, "nginx"))
   261  	c.Assert(string(e.OpLabels.OrchestrationInfo.SortedList()), Equals, "nginx:foo=zop;")
   262  }
   263  
   264  func (s *EndpointSuite) TestEndpointState(c *C) {
   265  	e := NewEndpointWithState(s, 100, StateCreating)
   266  	e.UnconditionalLock()
   267  	defer e.Unlock()
   268  
   269  	assertStateTransition(c, e, e.SetStateLocked, StateCreating, StateCreating, false)
   270  	assertStateTransition(c, e, e.SetStateLocked, StateCreating, StateWaitingForIdentity, true)
   271  	assertStateTransition(c, e, e.SetStateLocked, StateCreating, StateReady, false)
   272  	assertStateTransition(c, e, e.SetStateLocked, StateCreating, StateWaitingToRegenerate, false)
   273  	assertStateTransition(c, e, e.SetStateLocked, StateCreating, StateRegenerating, false)
   274  	assertStateTransition(c, e, e.SetStateLocked, StateCreating, StateDisconnecting, true)
   275  	assertStateTransition(c, e, e.SetStateLocked, StateCreating, StateDisconnected, false)
   276  
   277  	assertStateTransition(c, e, e.SetStateLocked, StateWaitingForIdentity, StateCreating, false)
   278  	assertStateTransition(c, e, e.SetStateLocked, StateWaitingForIdentity, StateWaitingForIdentity, false)
   279  
   280  	assertStateTransition(c, e, e.SetStateLocked, StateWaitingForIdentity, StateReady, true)
   281  
   282  	assertStateTransition(c, e, e.SetStateLocked, StateWaitingForIdentity, StateWaitingToRegenerate, false)
   283  	assertStateTransition(c, e, e.SetStateLocked, StateWaitingToRegenerate, StateRegenerating, false)
   284  	assertStateTransition(c, e, e.SetStateLocked, StateRegenerating, StateDisconnecting, true)
   285  
   286  	assertStateTransition(c, e, e.SetStateLocked, StateWaitingForIdentity, StateDisconnected, false)
   287  
   288  	assertStateTransition(c, e, e.SetStateLocked, StateReady, StateCreating, false)
   289  	assertStateTransition(c, e, e.SetStateLocked, StateReady, StateWaitingForIdentity, true)
   290  	assertStateTransition(c, e, e.SetStateLocked, StateReady, StateReady, false)
   291  	assertStateTransition(c, e, e.SetStateLocked, StateReady, StateWaitingToRegenerate, true)
   292  	assertStateTransition(c, e, e.SetStateLocked, StateReady, StateRegenerating, false)
   293  	assertStateTransition(c, e, e.SetStateLocked, StateReady, StateDisconnecting, true)
   294  	assertStateTransition(c, e, e.SetStateLocked, StateReady, StateDisconnected, false)
   295  
   296  	assertStateTransition(c, e, e.SetStateLocked, StateWaitingToRegenerate, StateCreating, false)
   297  	assertStateTransition(c, e, e.SetStateLocked, StateWaitingToRegenerate, StateWaitingForIdentity, true)
   298  	assertStateTransition(c, e, e.SetStateLocked, StateWaitingToRegenerate, StateReady, false)
   299  	assertStateTransition(c, e, e.SetStateLocked, StateWaitingToRegenerate, StateWaitingToRegenerate, false)
   300  	assertStateTransition(c, e, e.SetStateLocked, StateWaitingToRegenerate, StateRegenerating, false)
   301  	assertStateTransition(c, e, e.SetStateLocked, StateWaitingToRegenerate, StateDisconnecting, true)
   302  	assertStateTransition(c, e, e.SetStateLocked, StateWaitingToRegenerate, StateDisconnected, false)
   303  
   304  	assertStateTransition(c, e, e.SetStateLocked, StateRegenerating, StateCreating, false)
   305  	assertStateTransition(c, e, e.SetStateLocked, StateRegenerating, StateWaitingForIdentity, true)
   306  	assertStateTransition(c, e, e.SetStateLocked, StateRegenerating, StateReady, false)
   307  	assertStateTransition(c, e, e.SetStateLocked, StateRegenerating, StateWaitingToRegenerate, true)
   308  	assertStateTransition(c, e, e.SetStateLocked, StateRegenerating, StateRegenerating, false)
   309  	assertStateTransition(c, e, e.SetStateLocked, StateRegenerating, StateDisconnecting, true)
   310  	assertStateTransition(c, e, e.SetStateLocked, StateRegenerating, StateDisconnected, false)
   311  
   312  	assertStateTransition(c, e, e.SetStateLocked, StateDisconnecting, StateCreating, false)
   313  	assertStateTransition(c, e, e.SetStateLocked, StateDisconnecting, StateWaitingForIdentity, false)
   314  	assertStateTransition(c, e, e.SetStateLocked, StateDisconnecting, StateReady, false)
   315  	assertStateTransition(c, e, e.SetStateLocked, StateDisconnecting, StateWaitingToRegenerate, false)
   316  	assertStateTransition(c, e, e.SetStateLocked, StateDisconnecting, StateRegenerating, false)
   317  	assertStateTransition(c, e, e.SetStateLocked, StateDisconnecting, StateDisconnecting, false)
   318  	assertStateTransition(c, e, e.SetStateLocked, StateDisconnecting, StateDisconnected, true)
   319  
   320  	assertStateTransition(c, e, e.SetStateLocked, StateDisconnected, StateCreating, false)
   321  	assertStateTransition(c, e, e.SetStateLocked, StateDisconnected, StateWaitingForIdentity, false)
   322  	assertStateTransition(c, e, e.SetStateLocked, StateDisconnected, StateReady, false)
   323  	assertStateTransition(c, e, e.SetStateLocked, StateDisconnected, StateWaitingToRegenerate, false)
   324  	assertStateTransition(c, e, e.SetStateLocked, StateDisconnected, StateRegenerating, false)
   325  	assertStateTransition(c, e, e.SetStateLocked, StateDisconnected, StateDisconnecting, false)
   326  	assertStateTransition(c, e, e.SetStateLocked, StateDisconnected, StateDisconnected, false)
   327  
   328  	// State transitions involving the "Invalid" state
   329  	assertStateTransition(c, e, e.SetStateLocked, "", StateInvalid, false)
   330  	assertStateTransition(c, e, e.SetStateLocked, StateWaitingForIdentity, StateInvalid, true)
   331  	assertStateTransition(c, e, e.SetStateLocked, StateInvalid, StateInvalid, false)
   332  
   333  	// Builder-specific transitions
   334  
   335  	// Builder can't transition to ready from waiting-to-regenerate
   336  	// as (another) build is pending
   337  	assertStateTransition(c, e, e.BuilderSetStateLocked, StateWaitingToRegenerate, StateReady, false)
   338  	// Only builder knows when bpf regeneration starts
   339  	assertStateTransition(c, e, e.SetStateLocked, StateWaitingToRegenerate, StateRegenerating, false)
   340  	assertStateTransition(c, e, e.BuilderSetStateLocked, StateWaitingToRegenerate, StateRegenerating, true)
   341  
   342  	// Builder does not trigger the need for regeneration
   343  	assertStateTransition(c, e, e.BuilderSetStateLocked, StateRegenerating, StateWaitingToRegenerate, false)
   344  	// Builder transitions to ready state after build is done
   345  	assertStateTransition(c, e, e.BuilderSetStateLocked, StateRegenerating, StateReady, true)
   346  
   347  	// Check that direct transition from restoring --> regenerating is valid.
   348  	assertStateTransition(c, e, e.BuilderSetStateLocked, StateRestoring, StateRegenerating, true)
   349  
   350  	// Typical lifecycle
   351  	assertStateTransition(c, e, e.SetStateLocked, StateCreating, StateWaitingForIdentity, true)
   352  	assertStateTransition(c, e, e.SetStateLocked, "", StateWaitingForIdentity, true)
   353  	// Initial build does not change the state
   354  	assertStateTransition(c, e, e.BuilderSetStateLocked, StateWaitingForIdentity, StateRegenerating, false)
   355  	assertStateTransition(c, e, e.BuilderSetStateLocked, StateWaitingForIdentity, StateReady, false)
   356  	// identity arrives
   357  	assertStateTransition(c, e, e.SetStateLocked, StateWaitingForIdentity, StateReady, true)
   358  	// a build is triggered after the identity is set
   359  	assertStateTransition(c, e, e.SetStateLocked, StateReady, StateWaitingToRegenerate, true)
   360  	// build starts
   361  	assertStateTransition(c, e, e.BuilderSetStateLocked, StateWaitingToRegenerate, StateRegenerating, true)
   362  	// another change arrives while building
   363  	assertStateTransition(c, e, e.SetStateLocked, StateRegenerating, StateWaitingToRegenerate, true)
   364  	// Builder's transition to ready fails due to the queued build
   365  	assertStateTransition(c, e, e.BuilderSetStateLocked, StateWaitingToRegenerate, StateReady, false)
   366  	// second build starts
   367  	assertStateTransition(c, e, e.BuilderSetStateLocked, StateWaitingToRegenerate, StateRegenerating, true)
   368  	// second build finishes
   369  	assertStateTransition(c, e, e.BuilderSetStateLocked, StateRegenerating, StateReady, true)
   370  	// endpoint is being deleted
   371  	assertStateTransition(c, e, e.SetStateLocked, StateReady, StateDisconnecting, true)
   372  	// parallel disconnect fails
   373  	assertStateTransition(c, e, e.SetStateLocked, StateDisconnecting, StateDisconnecting, false)
   374  	assertStateTransition(c, e, e.SetStateLocked, StateDisconnecting, StateDisconnected, true)
   375  
   376  	// Restoring state
   377  	assertStateTransition(c, e, e.SetStateLocked, StateRestoring, StateWaitingToRegenerate, false)
   378  	assertStateTransition(c, e, e.SetStateLocked, StateRestoring, StateDisconnecting, true)
   379  
   380  	assertStateTransition(c, e, e.SetStateLocked, StateRestoring, StateRestoring, true)
   381  
   382  	// Invalid state
   383  	assertStateTransition(c, e, e.BuilderSetStateLocked, StateInvalid, StateReady, false)
   384  	assertStateTransition(c, e, e.BuilderSetStateLocked, StateWaitingToRegenerate, StateInvalid, false)
   385  }
   386  
   387  func assertStateTransition(c *C,
   388  	e *Endpoint, stateSetter func(string, string) bool,
   389  	from, to string,
   390  	success bool) {
   391  
   392  	e.state = from
   393  
   394  	currStateOldMetric := getMetricValue(e.state)
   395  	newStateOldMetric := getMetricValue(to)
   396  	got := stateSetter(to, "test")
   397  	currStateNewMetric := getMetricValue(from)
   398  	newStateNewMetric := getMetricValue(e.state)
   399  
   400  	c.Assert(got, Equals, success)
   401  
   402  	// Do not assert on metrics if the endpoint is not expected to transition.
   403  	if !success {
   404  		return
   405  	}
   406  
   407  	// If the state transition moves from itself to itself, we expect the
   408  	// metrics to be unchanged.
   409  	if from == to {
   410  		c.Assert(currStateOldMetric, Equals, currStateNewMetric)
   411  		c.Assert(newStateOldMetric, Equals, newStateNewMetric)
   412  	} else {
   413  		// Blank states don't have metrics so we skip over that; metric should
   414  		// be unchanged.
   415  		if from != "" {
   416  			c.Assert(currStateOldMetric-1, Equals, currStateNewMetric)
   417  		} else {
   418  			c.Assert(currStateOldMetric, Equals, currStateNewMetric)
   419  		}
   420  
   421  		// Don't assert on state transition that ends up in a final state, as
   422  		// the metric is not incremented in this case; metric should be
   423  		// unchanged.
   424  		if !isFinalState(to) {
   425  			c.Assert(newStateOldMetric+1, Equals, newStateNewMetric)
   426  		} else {
   427  			c.Assert(newStateOldMetric, Equals, newStateNewMetric)
   428  		}
   429  	}
   430  }
   431  
   432  func isFinalState(state string) bool {
   433  	return (state == StateDisconnected || state == StateInvalid)
   434  }
   435  
   436  func getMetricValue(state string) int64 {
   437  	return int64(metrics.GetGaugeValue(metrics.EndpointStateCount.WithLabelValues(state)))
   438  }
   439  
   440  func (s *EndpointSuite) TestWaitForPolicyRevision(c *C) {
   441  	e := &Endpoint{policyRevision: 0}
   442  
   443  	ctx, cancel := context.WithTimeout(context.Background(), time.Duration(1*time.Second))
   444  
   445  	cbRan := false
   446  	<-e.WaitForPolicyRevision(ctx, 0, func(time.Time) { cbRan = true })
   447  	// shouldn't get a timeout when waiting for policy revision already reached
   448  	c.Assert(ctx.Err(), IsNil)
   449  	// Should see a callback when waiting for a policy revision already reached
   450  	c.Assert(cbRan, Equals, true)
   451  
   452  	cancel()
   453  
   454  	e.policyRevision = 1
   455  
   456  	ctx, cancel = context.WithTimeout(context.Background(), time.Duration(1*time.Second))
   457  	cbRan = false
   458  
   459  	<-e.WaitForPolicyRevision(ctx, 0, func(time.Time) { cbRan = true })
   460  	// shouldn't get a timeout when waiting for policy revision already reached
   461  	c.Assert(ctx.Err(), IsNil)
   462  	// Should see a callback because the channel returned
   463  	c.Assert(cbRan, Equals, true)
   464  
   465  	cancel()
   466  
   467  	e.policyRevision = 1
   468  
   469  	ctx, cancel = context.WithCancel(context.Background())
   470  	cbRan = false
   471  
   472  	ch := e.WaitForPolicyRevision(ctx, 2, func(time.Time) { cbRan = true })
   473  	cancel()
   474  	// context was prematurely closed on purpose the error should be nil
   475  	c.Assert(ctx.Err(), Equals, context.Canceled)
   476  	// Should not see a callback when we don't close the channel
   477  	c.Assert(cbRan, Equals, false)
   478  
   479  	e.setPolicyRevision(3)
   480  
   481  	select {
   482  	case <-ch:
   483  	default:
   484  		c.Fatalf("channel should have been closed since the wanted policy revision was reached")
   485  	}
   486  
   487  	// Number of policy revision signals should be 0
   488  	c.Assert(len(e.policyRevisionSignals), Equals, 0)
   489  
   490  	e.state = StateDisconnected
   491  
   492  	ctx, cancel = context.WithCancel(context.Background())
   493  	cbRan = false
   494  	ch = e.WaitForPolicyRevision(ctx, 99, func(time.Time) { cbRan = true })
   495  	cancel()
   496  	select {
   497  	case <-ch:
   498  	default:
   499  		c.Fatalf("channel should have been closed since the endpoint is in disconnected state")
   500  	}
   501  	// Should see a callback because the channel was closed
   502  	c.Assert(cbRan, Equals, true)
   503  
   504  	// Number of policy revision signals should be 0
   505  	c.Assert(len(e.policyRevisionSignals), Equals, 0)
   506  
   507  	e.state = StateCreating
   508  	ctx, cancel = context.WithCancel(context.Background())
   509  	ch = e.WaitForPolicyRevision(ctx, 99, func(time.Time) { cbRan = true })
   510  
   511  	e.cleanPolicySignals()
   512  
   513  	select {
   514  	case <-ch:
   515  	default:
   516  		c.Fatalf("channel should have been closed since all policy signals were closed")
   517  	}
   518  	// Should see a callback because the channel was closed
   519  	c.Assert(cbRan, Equals, true)
   520  	cancel()
   521  
   522  	// Number of policy revision signals should be 0
   523  	c.Assert(len(e.policyRevisionSignals), Equals, 0)
   524  }
   525  
   526  func (s *EndpointSuite) TestProxyID(c *C) {
   527  	e := &Endpoint{ID: 123, policyRevision: 0}
   528  
   529  	id := e.ProxyID(&policy.L4Filter{Port: 8080, Protocol: api.ProtoTCP, Ingress: true})
   530  	endpointID, ingress, protocol, port, err := policy.ParseProxyID(id)
   531  	c.Assert(endpointID, Equals, uint16(123))
   532  	c.Assert(ingress, Equals, true)
   533  	c.Assert(protocol, Equals, "TCP")
   534  	c.Assert(port, Equals, uint16(8080))
   535  	c.Assert(err, IsNil)
   536  }
   537  
   538  func TestEndpoint_GetK8sPodLabels(t *testing.T) {
   539  	type fields struct {
   540  		OpLabels pkgLabels.OpLabels
   541  	}
   542  	tests := []struct {
   543  		name   string
   544  		fields fields
   545  		want   pkgLabels.Labels
   546  	}{
   547  		{
   548  			name: "has all k8s labels",
   549  			fields: fields{
   550  				OpLabels: pkgLabels.OpLabels{
   551  					OrchestrationInfo: pkgLabels.Map2Labels(map[string]string{"foo": "bar"}, pkgLabels.LabelSourceK8s),
   552  				},
   553  			},
   554  			want: pkgLabels.Map2Labels(map[string]string{"foo": "bar"}, pkgLabels.LabelSourceK8s),
   555  		},
   556  		{
   557  			name: "the namespace labels, service account and namespace should be ignored as they don't belong to pod labels",
   558  			fields: fields{
   559  				OpLabels: pkgLabels.OpLabels{
   560  					OrchestrationInfo: pkgLabels.Map2Labels(map[string]string{
   561  						"foo":                                    "bar",
   562  						ciliumio.PodNamespaceMetaLabels + ".env": "prod",
   563  						ciliumio.PolicyLabelServiceAccount:       "default",
   564  						ciliumio.PodNamespaceLabel:               "default",
   565  					}, pkgLabels.LabelSourceK8s),
   566  				},
   567  			},
   568  			want: pkgLabels.Map2Labels(map[string]string{"foo": "bar"}, pkgLabels.LabelSourceK8s),
   569  		},
   570  		{
   571  			name: "labels with other source than k8s should also be ignored",
   572  			fields: fields{
   573  				OpLabels: pkgLabels.OpLabels{
   574  					OrchestrationInfo: pkgLabels.Map2Labels(map[string]string{
   575  						"foo":                                    "bar",
   576  						ciliumio.PodNamespaceMetaLabels + ".env": "prod",
   577  					}, pkgLabels.LabelSourceK8s),
   578  					OrchestrationIdentity: pkgLabels.Map2Labels(map[string]string{
   579  						"foo2":                                   "bar",
   580  						ciliumio.PodNamespaceMetaLabels + ".env": "prod2",
   581  					}, pkgLabels.LabelSourceAny),
   582  				},
   583  			},
   584  			want: pkgLabels.Map2Labels(map[string]string{"foo": "bar"}, pkgLabels.LabelSourceK8s),
   585  		},
   586  	}
   587  	for _, tt := range tests {
   588  		t.Run(tt.name, func(t *testing.T) {
   589  			e := &Endpoint{
   590  				mutex:    lock.RWMutex{},
   591  				OpLabels: tt.fields.OpLabels,
   592  			}
   593  			if got := e.GetK8sPodLabels(); !reflect.DeepEqual(got, tt.want) {
   594  				t.Errorf("Endpoint.GetK8sPodLabels() = %v, want %v", got, tt.want)
   595  			}
   596  		})
   597  	}
   598  }
   599  
   600  func (s *EndpointSuite) TestK8sPodNameIsSet(c *C) {
   601  	e := Endpoint{}
   602  	c.Assert(e.K8sNamespaceAndPodNameIsSet(), Equals, false)
   603  	e.K8sPodName = "foo"
   604  	e.K8sNamespace = "default"
   605  	c.Assert(e.K8sNamespaceAndPodNameIsSet(), Equals, true)
   606  }