github.com/cilium/cilium@v1.16.2/pkg/bgpv1/test/fixtures.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package test
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  	"os"
    10  	"testing"
    11  
    12  	"github.com/cilium/hive/cell"
    13  	"github.com/cilium/hive/hivetest"
    14  	"github.com/sirupsen/logrus"
    15  	meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    16  	"k8s.io/utils/ptr"
    17  
    18  	daemon_k8s "github.com/cilium/cilium/daemon/k8s"
    19  	"github.com/cilium/cilium/pkg/annotation"
    20  	"github.com/cilium/cilium/pkg/bgpv1"
    21  	"github.com/cilium/cilium/pkg/bgpv1/agent"
    22  	"github.com/cilium/cilium/pkg/hive"
    23  	ipamOption "github.com/cilium/cilium/pkg/ipam/option"
    24  	k8sPkg "github.com/cilium/cilium/pkg/k8s"
    25  	cilium_api_v2 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2"
    26  	cilium_api_v2alpha1 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1"
    27  	k8sClient "github.com/cilium/cilium/pkg/k8s/client"
    28  	"github.com/cilium/cilium/pkg/k8s/client/clientset/versioned/typed/cilium.io/v2alpha1"
    29  	"github.com/cilium/cilium/pkg/k8s/resource"
    30  	slim_core_v1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/api/core/v1"
    31  	slim_meta_v1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/meta/v1"
    32  	clientset_core_v1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/client/clientset/versioned/typed/core/v1"
    33  	"github.com/cilium/cilium/pkg/k8s/utils"
    34  	"github.com/cilium/cilium/pkg/metrics"
    35  	"github.com/cilium/cilium/pkg/option"
    36  )
    37  
    38  var (
    39  	// log is used in the test as well as passed to gobgp instances.
    40  	log = &logrus.Logger{
    41  		Out:   os.Stdout,
    42  		Hooks: make(logrus.LevelHooks),
    43  		Formatter: &logrus.TextFormatter{
    44  			DisableTimestamp: false,
    45  			DisableColors:    false,
    46  		},
    47  		Level: logrus.DebugLevel,
    48  	}
    49  )
    50  
    51  // cilium BGP config
    52  var (
    53  	ciliumASN        = uint32(65001)
    54  	ciliumListenPort = uint32(1790)
    55  )
    56  
    57  // kubernetes policies
    58  var (
    59  	// base node spec
    60  	nodeAnnotationKey    = fmt.Sprintf("%s%d", annotation.BGPVRouterAnnoPrefix, ciliumASN)
    61  	nodeAnnotationValues = fmt.Sprintf("router-id=%s,local-port=%d",
    62  		dummies[ciliumLink].ipv4.Addr().String(), ciliumListenPort)
    63  
    64  	labels = map[string]string{
    65  		"rack": "rack0",
    66  	}
    67  
    68  	baseNode = ciliumNodeConfig{
    69  		name:        "test",
    70  		labels:      labels,
    71  		annotations: map[string]string{nodeAnnotationKey: nodeAnnotationValues},
    72  	}
    73  
    74  	baseBGPPolicy = policyConfig{
    75  		nodeSelector: labels,
    76  		virtualRouters: []cilium_api_v2alpha1.CiliumBGPVirtualRouter{
    77  			{
    78  				LocalASN: int64(ciliumASN),
    79  			},
    80  		},
    81  	}
    82  )
    83  
    84  // fixture is test harness
    85  type fixture struct {
    86  	config        fixtureConfig
    87  	fakeClientSet *k8sClient.FakeClientset
    88  	policyClient  v2alpha1.CiliumBGPPeeringPolicyInterface
    89  	secretClient  clientset_core_v1.SecretInterface
    90  	hive          *hive.Hive
    91  	cells         []cell.Cell
    92  	bgp           *agent.Controller
    93  	ciliumNode    daemon_k8s.LocalCiliumNodeResource
    94  }
    95  
    96  type fixtureConfig struct {
    97  	node      cilium_api_v2.CiliumNode
    98  	policy    cilium_api_v2alpha1.CiliumBGPPeeringPolicy
    99  	secret    slim_core_v1.Secret
   100  	ipam      string
   101  	bgpEnable bool
   102  }
   103  
   104  func newFixtureConf() fixtureConfig {
   105  	policyCfg := policyConfig{
   106  		nodeSelector: baseBGPPolicy.nodeSelector,
   107  	}
   108  	secret := slim_core_v1.Secret{
   109  		ObjectMeta: slim_meta_v1.ObjectMeta{
   110  			Namespace: "bgp-secrets",
   111  			Name:      "a-secret",
   112  		},
   113  		Data: map[string]slim_core_v1.Bytes{"password": slim_core_v1.Bytes("testing-123")},
   114  	}
   115  
   116  	// deepcopy the VirtualRouters as the tests modify them
   117  	for _, vr := range baseBGPPolicy.virtualRouters {
   118  		policyCfg.virtualRouters = append(policyCfg.virtualRouters, *vr.DeepCopy())
   119  	}
   120  	return fixtureConfig{
   121  		node:      newCiliumNode(baseNode),
   122  		policy:    newPolicyObj(policyCfg),
   123  		ipam:      ipamOption.IPAMKubernetes,
   124  		secret:    secret,
   125  		bgpEnable: true,
   126  	}
   127  }
   128  
   129  func newFixture(conf fixtureConfig) *fixture {
   130  	f := &fixture{
   131  		config: conf,
   132  	}
   133  
   134  	f.fakeClientSet, _ = k8sClient.NewFakeClientset()
   135  	f.policyClient = f.fakeClientSet.CiliumFakeClientset.CiliumV2alpha1().CiliumBGPPeeringPolicies()
   136  	f.secretClient = f.fakeClientSet.SlimFakeClientset.CoreV1().Secrets("bgp-secrets")
   137  
   138  	// create initial cilium node
   139  	f.fakeClientSet.CiliumFakeClientset.Tracker().Add(&conf.node)
   140  
   141  	// create initial bgp policy
   142  	f.fakeClientSet.CiliumFakeClientset.Tracker().Add(&conf.policy)
   143  	f.fakeClientSet.SlimFakeClientset.Tracker().Add(&conf.secret)
   144  
   145  	// Construct a new Hive with mocked out dependency cells.
   146  	f.cells = []cell.Cell{
   147  		cell.Config(k8sPkg.DefaultConfig),
   148  
   149  		// service
   150  		cell.Provide(k8sPkg.ServiceResource),
   151  
   152  		// endpoints
   153  		cell.Provide(k8sPkg.EndpointsResource),
   154  
   155  		// CiliumLoadBalancerIPPool
   156  		cell.Provide(k8sPkg.LBIPPoolsResource),
   157  
   158  		// cilium node
   159  		cell.Provide(func(lc cell.Lifecycle, c k8sClient.Clientset) daemon_k8s.LocalCiliumNodeResource {
   160  			store := resource.New[*cilium_api_v2.CiliumNode](
   161  				lc, utils.ListerWatcherFromTyped[*cilium_api_v2.CiliumNodeList](
   162  					c.CiliumV2().CiliumNodes(),
   163  				),
   164  			)
   165  			f.ciliumNode = store
   166  			return store
   167  		}),
   168  
   169  		// Provide the mocked client cells directly
   170  		cell.Provide(func() k8sClient.Clientset {
   171  			return f.fakeClientSet
   172  		}),
   173  
   174  		// daemon config
   175  		cell.Provide(func() *option.DaemonConfig {
   176  			return &option.DaemonConfig{
   177  				EnableBGPControlPlane: conf.bgpEnable,
   178  				BGPSecretsNamespace:   "bgp-secrets",
   179  				IPAM:                  conf.ipam,
   180  			}
   181  		}),
   182  
   183  		// local bgp state for inspection
   184  		cell.Invoke(func(bgp *agent.Controller) {
   185  			f.bgp = bgp
   186  		}),
   187  
   188  		metrics.Cell,
   189  		bgpv1.Cell,
   190  	}
   191  	f.hive = hive.New(f.cells...)
   192  
   193  	return f
   194  }
   195  
   196  func setupSingleNeighbor(ctx context.Context, f *fixture, peerASN uint32) error {
   197  	f.config.policy.Spec.VirtualRouters[0] = cilium_api_v2alpha1.CiliumBGPVirtualRouter{
   198  		LocalASN:      int64(ciliumASN),
   199  		ExportPodCIDR: ptr.To[bool](true),
   200  		Neighbors: []cilium_api_v2alpha1.CiliumBGPNeighbor{
   201  			{
   202  				PeerAddress: dummies[instance1Link].ipv4.String(),
   203  				PeerASN:     int64(peerASN),
   204  			},
   205  		},
   206  	}
   207  
   208  	_, err := f.policyClient.Update(ctx, &f.config.policy, meta_v1.UpdateOptions{})
   209  	return err
   210  }
   211  
   212  // setup configures the test environment based on provided gobgp and fixture config.
   213  func setup(ctx context.Context, t testing.TB, peerConfigs []gobgpConfig, fixConfig fixtureConfig) (peers []*goBGP, f *fixture, cleanup func(), err error) {
   214  	f = newFixture(fixConfig)
   215  	peers, cleanup, err = start(ctx, t, peerConfigs, f)
   216  	return
   217  }
   218  
   219  // start configures dummy links, starts gobgp and cilium bgp cell.
   220  func start(ctx context.Context, t testing.TB, peerConfigs []gobgpConfig, f *fixture) (peers []*goBGP, cleanup func(), err error) {
   221  	// cleanup old dummy links if they are hanging around
   222  	_ = teardownLinks()
   223  
   224  	err = setupLinks()
   225  	if err != nil {
   226  		return
   227  	}
   228  
   229  	err = setupLinkIPs()
   230  	if err != nil {
   231  		return
   232  	}
   233  
   234  	// start goBGP
   235  	for _, pConf := range peerConfigs {
   236  		var peer *goBGP
   237  		peer, err = startGoBGP(ctx, pConf)
   238  		if err != nil {
   239  			return
   240  		}
   241  		peers = append(peers, peer)
   242  	}
   243  
   244  	// start cilium
   245  	tlog := hivetest.Logger(t)
   246  	err = f.hive.Start(tlog, ctx)
   247  	if err != nil {
   248  		return
   249  	}
   250  
   251  	cleanup = func() {
   252  		for _, peer := range peers {
   253  			peer.stopGoBGP()
   254  		}
   255  
   256  		f.bgp.BGPMgr.Stop()
   257  
   258  		f.hive.Stop(tlog, ctx)
   259  		teardownLinks()
   260  	}
   261  
   262  	return
   263  }