github.com/cilium/cilium@v1.16.2/pkg/egressgateway/helpers_test.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package egressgateway 5 6 import ( 7 "context" 8 "errors" 9 "net/netip" 10 "testing" 11 12 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 13 "k8s.io/apimachinery/pkg/runtime" 14 "k8s.io/apimachinery/pkg/types" 15 16 v2 "github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2" 17 "github.com/cilium/cilium/pkg/k8s/resource" 18 slimv1 "github.com/cilium/cilium/pkg/k8s/slim/k8s/apis/meta/v1" 19 k8sTypes "github.com/cilium/cilium/pkg/k8s/types" 20 "github.com/cilium/cilium/pkg/policy/api" 21 ) 22 23 type fakeResource[T runtime.Object] chan resource.Event[T] 24 25 func (fr fakeResource[T]) sync(tb testing.TB) { 26 var sync resource.Event[T] 27 sync.Kind = resource.Sync 28 fr.process(tb, sync) 29 } 30 31 func (fr fakeResource[T]) process(tb testing.TB, ev resource.Event[T]) { 32 tb.Helper() 33 if err := fr.processWithError(ev); err != nil { 34 tb.Fatal("Failed to process event:", err) 35 } 36 } 37 38 func (fr fakeResource[T]) processWithError(ev resource.Event[T]) error { 39 errs := make(chan error) 40 ev.Done = func(err error) { 41 errs <- err 42 } 43 fr <- ev 44 return <-errs 45 } 46 47 func (fr fakeResource[T]) Observe(ctx context.Context, next func(event resource.Event[T]), complete func(error)) { 48 complete(errors.New("not implemented")) 49 } 50 51 func (fr fakeResource[T]) Events(ctx context.Context, opts ...resource.EventsOpt) <-chan resource.Event[T] { 52 if len(opts) > 1 { 53 // Ideally we'd only ignore resource.WithRateLimit here, but that 54 // isn't possible. 55 panic("more than one option is not supported") 56 } 57 return fr 58 } 59 60 func (fr fakeResource[T]) Store(context.Context) (resource.Store[T], error) { 61 return nil, errors.New("not implemented") 62 } 63 64 func addPolicy(tb testing.TB, policies fakeResource[*Policy], params *policyParams) { 65 tb.Helper() 66 67 policy, _ := newCEGP(params) 68 policies.process(tb, resource.Event[*Policy]{ 69 Kind: resource.Upsert, 70 Object: policy, 71 }) 72 } 73 74 type policyParams struct { 75 name string 76 endpointLabels map[string]string 77 destinationCIDR string 78 excludedCIDRs []string 79 nodeLabels map[string]string 80 iface string 81 egressIP string 82 } 83 84 func newCEGP(params *policyParams) (*v2.CiliumEgressGatewayPolicy, *PolicyConfig) { 85 parsedDestinationCIDR, _ := netip.ParsePrefix(params.destinationCIDR) 86 87 parsedExcludedCIDRs := make([]netip.Prefix, 0, len(params.excludedCIDRs)) 88 for _, excludedCIDR := range params.excludedCIDRs { 89 parsedExcludedCIDR, _ := netip.ParsePrefix(excludedCIDR) 90 parsedExcludedCIDRs = append(parsedExcludedCIDRs, parsedExcludedCIDR) 91 } 92 93 addr, _ := netip.ParseAddr(params.egressIP) 94 policy := &PolicyConfig{ 95 id: types.NamespacedName{ 96 Name: params.name, 97 }, 98 dstCIDRs: []netip.Prefix{parsedDestinationCIDR}, 99 excludedCIDRs: parsedExcludedCIDRs, 100 endpointSelectors: []api.EndpointSelector{ 101 { 102 LabelSelector: &slimv1.LabelSelector{ 103 MatchLabels: params.endpointLabels, 104 }, 105 }, 106 }, 107 policyGwConfig: &policyGatewayConfig{ 108 iface: params.iface, 109 egressIP: addr, 110 }, 111 } 112 113 if len(params.endpointLabels) != 0 { 114 policy.endpointSelectors = []api.EndpointSelector{ 115 { 116 LabelSelector: &slimv1.LabelSelector{ 117 MatchLabels: params.endpointLabels, 118 }, 119 }, 120 } 121 } 122 123 if len(params.nodeLabels) != 0 { 124 policy.policyGwConfig.nodeSelector = api.EndpointSelector{ 125 LabelSelector: &slimv1.LabelSelector{ 126 MatchLabels: params.nodeLabels, 127 }, 128 } 129 } 130 131 excludedCIDRs := []v2.IPv4CIDR{} 132 for _, excludedCIDR := range params.excludedCIDRs { 133 excludedCIDRs = append(excludedCIDRs, v2.IPv4CIDR(excludedCIDR)) 134 } 135 136 cegp := &v2.CiliumEgressGatewayPolicy{ 137 ObjectMeta: metav1.ObjectMeta{ 138 Name: params.name, 139 }, 140 Spec: v2.CiliumEgressGatewayPolicySpec{ 141 Selectors: []v2.EgressRule{ 142 { 143 PodSelector: &slimv1.LabelSelector{ 144 MatchLabels: params.endpointLabels, 145 }, 146 }, 147 }, 148 DestinationCIDRs: []v2.IPv4CIDR{ 149 v2.IPv4CIDR(params.destinationCIDR), 150 }, 151 ExcludedCIDRs: excludedCIDRs, 152 EgressGateway: &v2.EgressGateway{ 153 NodeSelector: &slimv1.LabelSelector{ 154 MatchLabels: params.nodeLabels, 155 }, 156 Interface: params.iface, 157 EgressIP: params.egressIP, 158 }, 159 }, 160 } 161 162 return cegp, policy 163 } 164 165 func addEndpoint(tb testing.TB, endpoints fakeResource[*k8sTypes.CiliumEndpoint], ep *k8sTypes.CiliumEndpoint) { 166 endpoints.process(tb, resource.Event[*k8sTypes.CiliumEndpoint]{ 167 Kind: resource.Upsert, 168 Object: ep, 169 }) 170 } 171 172 func deleteEndpoint(tb testing.TB, endpoints fakeResource[*k8sTypes.CiliumEndpoint], ep *k8sTypes.CiliumEndpoint) { 173 endpoints.process(tb, resource.Event[*k8sTypes.CiliumEndpoint]{ 174 Kind: resource.Delete, 175 Object: ep, 176 }) 177 }