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 }