github.com/looshlee/cilium@v1.6.12/daemon/daemon_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 main
    18  
    19  import (
    20  	"context"
    21  	"io/ioutil"
    22  	"os"
    23  	"path/filepath"
    24  	"runtime"
    25  	"sync"
    26  	"testing"
    27  	"time"
    28  
    29  	"github.com/cilium/cilium/api/v1/models"
    30  	"github.com/cilium/cilium/common"
    31  	"github.com/cilium/cilium/pkg/completion"
    32  	"github.com/cilium/cilium/pkg/datapath"
    33  	fakedatapath "github.com/cilium/cilium/pkg/datapath/fake"
    34  	"github.com/cilium/cilium/pkg/endpoint/regeneration"
    35  	"github.com/cilium/cilium/pkg/endpointmanager"
    36  	"github.com/cilium/cilium/pkg/identity"
    37  	"github.com/cilium/cilium/pkg/identity/cache"
    38  	"github.com/cilium/cilium/pkg/kvstore"
    39  	"github.com/cilium/cilium/pkg/labels"
    40  	"github.com/cilium/cilium/pkg/lock"
    41  	"github.com/cilium/cilium/pkg/metrics"
    42  	monitorAPI "github.com/cilium/cilium/pkg/monitor/api"
    43  	"github.com/cilium/cilium/pkg/option"
    44  	"github.com/cilium/cilium/pkg/policy"
    45  	"github.com/cilium/cilium/pkg/proxy/accesslog"
    46  	"github.com/cilium/cilium/pkg/revert"
    47  
    48  	"github.com/prometheus/client_golang/prometheus"
    49  	. "gopkg.in/check.v1"
    50  )
    51  
    52  // Hook up gocheck into the "go test" runner.
    53  func Test(t *testing.T) { TestingT(t) }
    54  
    55  type DaemonSuite struct {
    56  	d *Daemon
    57  
    58  	// oldPolicyEnabled is the policy enforcement mode that was set before the test,
    59  	// as returned by policy.GetPolicyEnabled().
    60  	oldPolicyEnabled string
    61  
    62  	kvstoreInit bool
    63  
    64  	// Owners interface mock
    65  	OnTracingEnabled          func() bool
    66  	OnAlwaysAllowLocalhost    func() bool
    67  	OnGetCachedLabelList      func(id identity.NumericIdentity) (labels.LabelArray, error)
    68  	OnGetPolicyRepository     func() *policy.Repository
    69  	OnUpdateProxyRedirect     func(e regeneration.EndpointUpdater, l4 *policy.L4Filter, proxyWaitGroup *completion.WaitGroup) (uint16, error, revert.FinalizeFunc, revert.RevertFunc)
    70  	OnRemoveProxyRedirect     func(e regeneration.EndpointInfoSource, id string, proxyWaitGroup *completion.WaitGroup) (error, revert.FinalizeFunc, revert.RevertFunc)
    71  	OnUpdateNetworkPolicy     func(e regeneration.EndpointUpdater, policy *policy.L4Policy, proxyWaitGroup *completion.WaitGroup) (error, revert.RevertFunc)
    72  	OnRemoveNetworkPolicy     func(e regeneration.EndpointInfoSource)
    73  	OnQueueEndpointBuild      func(ctx context.Context, epID uint64) (func(), error)
    74  	OnRemoveFromEndpointQueue func(epID uint64)
    75  	OnDebugEnabled            func() bool
    76  	OnGetCompilationLock      func() *lock.RWMutex
    77  	OnSendNotification        func(typ monitorAPI.AgentNotification, text string) error
    78  	OnNewProxyLogRecord       func(l *accesslog.LogRecord) error
    79  	OnClearPolicyConsumers    func(id uint16) *sync.WaitGroup
    80  
    81  	// Metrics
    82  	collectors []prometheus.Collector
    83  }
    84  
    85  func setupTestDirectories() {
    86  	tempRunDir, err := ioutil.TempDir("", "cilium-test-run")
    87  	if err != nil {
    88  		panic("TempDir() failed.")
    89  	}
    90  
    91  	err = os.Mkdir(filepath.Join(tempRunDir, "globals"), 0777)
    92  	if err != nil {
    93  		panic("Mkdir failed")
    94  	}
    95  
    96  	option.Config.Device = "undefined"
    97  	option.Config.RunDir = tempRunDir
    98  	option.Config.StateDir = tempRunDir
    99  	option.Config.AccessLog = filepath.Join(tempRunDir, "cilium-access.log")
   100  }
   101  
   102  func TestMain(m *testing.M) {
   103  	// Set up all configuration options which are global to the entire test
   104  	// run.
   105  	option.Config.Populate()
   106  	option.Config.IdentityAllocationMode = option.IdentityAllocationModeKVstore
   107  	option.Config.DryMode = true
   108  	option.Config.Opts = option.NewIntOptions(&option.DaemonMutableOptionLibrary)
   109  	// GetConfig the default labels prefix filter
   110  	err := labels.ParseLabelPrefixCfg(nil, "")
   111  	if err != nil {
   112  		panic("ParseLabelPrefixCfg() failed")
   113  	}
   114  	option.Config.Opts.SetBool(option.DropNotify, true)
   115  	option.Config.Opts.SetBool(option.TraceNotify, true)
   116  
   117  	// Disable restore of host IPs for unit tests. There can be arbitrary
   118  	// state left on disk.
   119  	option.Config.EnableHostIPRestore = false
   120  
   121  	time.Local = time.UTC
   122  	os.Exit(m.Run())
   123  }
   124  
   125  func (ds *DaemonSuite) SetUpSuite(c *C) {
   126  	// Register metrics once before running the suite
   127  	_, ds.collectors = metrics.CreateConfiguration([]string{"cilium_endpoint_state"})
   128  	metrics.MustRegister(ds.collectors...)
   129  }
   130  
   131  func (ds *DaemonSuite) TearDownSuite(c *C) {
   132  	// Unregister the metrics after the suite has finished
   133  	for _, c := range ds.collectors {
   134  		metrics.Unregister(c)
   135  	}
   136  }
   137  
   138  func (ds *DaemonSuite) SetUpTest(c *C) {
   139  
   140  	setupTestDirectories()
   141  
   142  	ds.oldPolicyEnabled = policy.GetPolicyEnabled()
   143  	policy.SetPolicyEnabled(option.DefaultEnforcement)
   144  
   145  	d, _, err := NewDaemon(fakedatapath.NewDatapath(), nil)
   146  	c.Assert(err, IsNil)
   147  	ds.d = d
   148  
   149  	kvstore.Client().DeletePrefix(common.OperationalPath)
   150  	kvstore.Client().DeletePrefix(kvstore.BaseKeyPrefix)
   151  
   152  	ds.OnTracingEnabled = nil
   153  	ds.OnAlwaysAllowLocalhost = nil
   154  	ds.OnGetCachedLabelList = nil
   155  	ds.OnGetPolicyRepository = nil
   156  	ds.OnUpdateProxyRedirect = nil
   157  	ds.OnRemoveProxyRedirect = nil
   158  	ds.OnUpdateNetworkPolicy = nil
   159  	ds.OnRemoveNetworkPolicy = nil
   160  	ds.OnQueueEndpointBuild = nil
   161  	ds.OnRemoveFromEndpointQueue = nil
   162  	ds.OnDebugEnabled = nil
   163  	ds.OnGetCompilationLock = nil
   164  	ds.OnSendNotification = nil
   165  	ds.OnNewProxyLogRecord = nil
   166  	ds.OnClearPolicyConsumers = nil
   167  
   168  	// Reset the most common endpoint states before each test.
   169  	for _, s := range []string{
   170  		string(models.EndpointStateReady),
   171  		string(models.EndpointStateWaitingForIdentity),
   172  		string(models.EndpointStateWaitingToRegenerate)} {
   173  		metrics.EndpointStateCount.WithLabelValues(s).Set(0.0)
   174  	}
   175  }
   176  
   177  func (ds *DaemonSuite) TearDownTest(c *C) {
   178  	endpointmanager.RemoveAll()
   179  
   180  	// It's helpful to keep the directories around if a test failed; only delete
   181  	// them if tests succeed.
   182  	if !c.Failed() {
   183  		os.RemoveAll(option.Config.RunDir)
   184  	}
   185  
   186  	if ds.kvstoreInit {
   187  		kvstore.Client().DeletePrefix(common.OperationalPath)
   188  		kvstore.Client().DeletePrefix(kvstore.BaseKeyPrefix)
   189  	}
   190  
   191  	// Restore the policy enforcement mode.
   192  	policy.SetPolicyEnabled(ds.oldPolicyEnabled)
   193  
   194  	// Release the identity allocator reference created by NewDaemon. This
   195  	// is done manually here as we have no Close() function daemon
   196  	cache.Close()
   197  
   198  	ds.d.Close()
   199  }
   200  
   201  type DaemonEtcdSuite struct {
   202  	DaemonSuite
   203  }
   204  
   205  var _ = Suite(&DaemonEtcdSuite{})
   206  
   207  func (e *DaemonEtcdSuite) SetUpSuite(c *C) {
   208  	kvstore.SetupDummy("etcd")
   209  	e.DaemonSuite.kvstoreInit = true
   210  }
   211  
   212  func (e *DaemonEtcdSuite) SetUpTest(c *C) {
   213  	e.DaemonSuite.SetUpTest(c)
   214  }
   215  
   216  func (e *DaemonEtcdSuite) TearDownTest(c *C) {
   217  	e.DaemonSuite.TearDownTest(c)
   218  }
   219  
   220  type DaemonConsulSuite struct {
   221  	DaemonSuite
   222  }
   223  
   224  var _ = Suite(&DaemonConsulSuite{})
   225  
   226  func (e *DaemonConsulSuite) SetUpSuite(c *C) {
   227  	kvstore.SetupDummy("consul")
   228  	e.DaemonSuite.kvstoreInit = true
   229  }
   230  
   231  func (e *DaemonConsulSuite) SetUpTest(c *C) {
   232  	e.DaemonSuite.SetUpTest(c)
   233  }
   234  
   235  func (e *DaemonConsulSuite) TearDownTest(c *C) {
   236  	e.DaemonSuite.TearDownTest(c)
   237  }
   238  
   239  func (ds *DaemonSuite) TestMinimumWorkerThreadsIsSet(c *C) {
   240  	c.Assert(numWorkerThreads() >= 2, Equals, true)
   241  	c.Assert(numWorkerThreads() >= runtime.NumCPU(), Equals, true)
   242  }
   243  
   244  func (ds *DaemonSuite) AlwaysAllowLocalhost() bool {
   245  	if ds.OnAlwaysAllowLocalhost != nil {
   246  		return ds.OnAlwaysAllowLocalhost()
   247  	}
   248  	panic("AlwaysAllowLocalhost should not have been called")
   249  }
   250  
   251  func (ds *DaemonSuite) GetCachedLabelList(id identity.NumericIdentity) (labels.LabelArray, error) {
   252  	if ds.OnGetCachedLabelList != nil {
   253  		return ds.OnGetCachedLabelList(id)
   254  	}
   255  	panic("GetCachedLabelList should not have been called")
   256  }
   257  
   258  func (ds *DaemonSuite) GetPolicyRepository() *policy.Repository {
   259  	if ds.OnGetPolicyRepository != nil {
   260  		return ds.OnGetPolicyRepository()
   261  	}
   262  	panic("GetPolicyRepository should not have been called")
   263  }
   264  
   265  func (ds *DaemonSuite) UpdateProxyRedirect(e regeneration.EndpointUpdater, l4 *policy.L4Filter, proxyWaitGroup *completion.WaitGroup) (uint16, error, revert.FinalizeFunc, revert.RevertFunc) {
   266  	if ds.OnUpdateProxyRedirect != nil {
   267  		return ds.OnUpdateProxyRedirect(e, l4, proxyWaitGroup)
   268  	}
   269  	panic("UpdateProxyRedirect should not have been called")
   270  }
   271  
   272  func (ds *DaemonSuite) RemoveProxyRedirect(e regeneration.EndpointInfoSource, id string, proxyWaitGroup *completion.WaitGroup) (error, revert.FinalizeFunc, revert.RevertFunc) {
   273  	if ds.OnRemoveProxyRedirect != nil {
   274  		return ds.OnRemoveProxyRedirect(e, id, proxyWaitGroup)
   275  	}
   276  	panic("RemoveProxyRedirect should not have been called")
   277  }
   278  
   279  func (ds *DaemonSuite) UpdateNetworkPolicy(e regeneration.EndpointUpdater, policy *policy.L4Policy,
   280  	proxyWaitGroup *completion.WaitGroup) (error, revert.RevertFunc) {
   281  	if ds.OnUpdateNetworkPolicy != nil {
   282  		return ds.OnUpdateNetworkPolicy(e, policy, proxyWaitGroup)
   283  	}
   284  	panic("UpdateNetworkPolicy should not have been called")
   285  }
   286  
   287  func (ds *DaemonSuite) RemoveNetworkPolicy(e regeneration.EndpointInfoSource) {
   288  	if ds.OnRemoveNetworkPolicy != nil {
   289  		ds.OnRemoveNetworkPolicy(e)
   290  	}
   291  	panic("RemoveNetworkPolicy should not have been called")
   292  }
   293  
   294  func (ds *DaemonSuite) QueueEndpointBuild(ctx context.Context, epID uint64) (func(), error) {
   295  	if ds.OnQueueEndpointBuild != nil {
   296  		return ds.OnQueueEndpointBuild(ctx, epID)
   297  	}
   298  	panic("QueueEndpointBuild should not have been called")
   299  }
   300  
   301  func (ds *DaemonSuite) RemoveFromEndpointQueue(epID uint64) {
   302  	if ds.OnRemoveFromEndpointQueue != nil {
   303  		ds.OnRemoveFromEndpointQueue(epID)
   304  		return
   305  	}
   306  	panic("RemoveFromEndpointQueue should not have been called")
   307  }
   308  
   309  func (ds *DaemonSuite) DebugEnabled() bool {
   310  	if ds.OnDebugEnabled != nil {
   311  		return ds.OnDebugEnabled()
   312  	}
   313  	panic("DebugEnabled should not have been called")
   314  }
   315  
   316  func (ds *DaemonSuite) GetCompilationLock() *lock.RWMutex {
   317  	if ds.OnGetCompilationLock != nil {
   318  		return ds.OnGetCompilationLock()
   319  	}
   320  	panic("GetCompilationLock should not have been called")
   321  }
   322  
   323  func (ds *DaemonSuite) SendNotification(typ monitorAPI.AgentNotification, text string) error {
   324  	if ds.OnSendNotification != nil {
   325  		return ds.OnSendNotification(typ, text)
   326  	}
   327  	panic("SendNotification should not have been called")
   328  }
   329  
   330  func (ds *DaemonSuite) NewProxyLogRecord(l *accesslog.LogRecord) error {
   331  	if ds.OnNewProxyLogRecord != nil {
   332  		return ds.OnNewProxyLogRecord(l)
   333  	}
   334  	panic("NewProxyLogRecord should not have been called")
   335  }
   336  
   337  func (ds *DaemonSuite) Datapath() datapath.Datapath {
   338  	return ds.d.datapath
   339  }
   340  
   341  func (ds *DaemonSuite) ClearPolicyConsumers(id uint16) *sync.WaitGroup {
   342  	if ds.OnClearPolicyConsumers != nil {
   343  		return ds.OnClearPolicyConsumers(id)
   344  	}
   345  	panic("ClearPolicyConsumers should not have been called")
   346  }
   347  
   348  func (ds *DaemonSuite) GetNodeSuffix() string {
   349  	return ds.d.GetNodeSuffix()
   350  }
   351  
   352  func (ds *DaemonSuite) UpdateIdentities(added, deleted cache.IdentityCache) {
   353  	ds.d.UpdateIdentities(added, deleted)
   354  }