@@ -20,6 +20,7 @@ import (
2020 "sigs.k8s.io/controller-runtime/pkg/client/fake"
2121 gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
2222 gwapiv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
23+ gwapiv1b1 "sigs.k8s.io/gateway-api/apis/v1beta1"
2324
2425 aigv1a1 "github.com/envoyproxy/ai-gateway/api/v1alpha1"
2526)
@@ -266,6 +267,250 @@ func Test_getSecretNameAndNamespace(t *testing.T) {
266267 require .Equal (t , "mysecret.foo" , getSecretNameAndNamespace (secretRef , "foo" ))
267268}
268269
270+ func Test_referenceGrantToTargetKindIndexFunc (t * testing.T ) {
271+ tests := []struct {
272+ name string
273+ referenceGrant * gwapiv1b1.ReferenceGrant
274+ expectedKeys []string
275+ }{
276+ {
277+ name : "single target kind - AIServiceBackend" ,
278+ referenceGrant : & gwapiv1b1.ReferenceGrant {
279+ ObjectMeta : metav1.ObjectMeta {
280+ Name : "grant1" ,
281+ Namespace : "backend-ns" ,
282+ },
283+ Spec : gwapiv1b1.ReferenceGrantSpec {
284+ From : []gwapiv1b1.ReferenceGrantFrom {
285+ {
286+ Group : "aigateway.envoyproxy.io" ,
287+ Kind : "AIGatewayRoute" ,
288+ Namespace : "route-ns" ,
289+ },
290+ },
291+ To : []gwapiv1b1.ReferenceGrantTo {
292+ {
293+ Group : "aigateway.envoyproxy.io" ,
294+ Kind : "AIServiceBackend" ,
295+ },
296+ },
297+ },
298+ },
299+ expectedKeys : []string {"backend-ns.AIServiceBackend" },
300+ },
301+ {
302+ name : "multiple target kinds" ,
303+ referenceGrant : & gwapiv1b1.ReferenceGrant {
304+ ObjectMeta : metav1.ObjectMeta {
305+ Name : "grant2" ,
306+ Namespace : "backend-ns" ,
307+ },
308+ Spec : gwapiv1b1.ReferenceGrantSpec {
309+ From : []gwapiv1b1.ReferenceGrantFrom {
310+ {
311+ Group : "aigateway.envoyproxy.io" ,
312+ Kind : "AIGatewayRoute" ,
313+ Namespace : "route-ns" ,
314+ },
315+ },
316+ To : []gwapiv1b1.ReferenceGrantTo {
317+ {
318+ Group : "aigateway.envoyproxy.io" ,
319+ Kind : "AIServiceBackend" ,
320+ },
321+ {
322+ Group : "" ,
323+ Kind : "Secret" ,
324+ },
325+ },
326+ },
327+ },
328+ expectedKeys : []string {"backend-ns.AIServiceBackend" , "backend-ns.Secret" },
329+ },
330+ {
331+ name : "empty group for core resources" ,
332+ referenceGrant : & gwapiv1b1.ReferenceGrant {
333+ ObjectMeta : metav1.ObjectMeta {
334+ Name : "grant3" ,
335+ Namespace : "other-ns" ,
336+ },
337+ Spec : gwapiv1b1.ReferenceGrantSpec {
338+ From : []gwapiv1b1.ReferenceGrantFrom {
339+ {
340+ Group : "gateway.networking.k8s.io" ,
341+ Kind : "HTTPRoute" ,
342+ Namespace : "route-ns" ,
343+ },
344+ },
345+ To : []gwapiv1b1.ReferenceGrantTo {
346+ {
347+ Group : "" ,
348+ Kind : "Service" ,
349+ },
350+ },
351+ },
352+ },
353+ expectedKeys : []string {"other-ns.Service" },
354+ },
355+ {
356+ name : "no target kinds" ,
357+ referenceGrant : & gwapiv1b1.ReferenceGrant {
358+ ObjectMeta : metav1.ObjectMeta {
359+ Name : "grant4" ,
360+ Namespace : "backend-ns" ,
361+ },
362+ Spec : gwapiv1b1.ReferenceGrantSpec {
363+ From : []gwapiv1b1.ReferenceGrantFrom {
364+ {
365+ Group : "aigateway.envoyproxy.io" ,
366+ Kind : "AIGatewayRoute" ,
367+ Namespace : "route-ns" ,
368+ },
369+ },
370+ To : []gwapiv1b1.ReferenceGrantTo {},
371+ },
372+ },
373+ expectedKeys : nil , // nil is returned for empty To array
374+ },
375+ }
376+
377+ for _ , tt := range tests {
378+ t .Run (tt .name , func (t * testing.T ) {
379+ keys := referenceGrantToTargetKindIndexFunc (tt .referenceGrant )
380+ require .Equal (t , tt .expectedKeys , keys )
381+ })
382+ }
383+ }
384+
385+ func Test_referenceGrantIndexWithQuery (t * testing.T ) {
386+ // Create a fake client with the ReferenceGrant index
387+ c := fake .NewClientBuilder ().
388+ WithScheme (Scheme ).
389+ WithIndex (& gwapiv1b1.ReferenceGrant {}, k8sClientIndexReferenceGrantToTargetKind , referenceGrantToTargetKindIndexFunc ).
390+ Build ()
391+
392+ // Create multiple ReferenceGrants with different target kinds
393+ grant1 := & gwapiv1b1.ReferenceGrant {
394+ ObjectMeta : metav1.ObjectMeta {
395+ Name : "grant-aiservicebackend" ,
396+ Namespace : "backend-ns" ,
397+ },
398+ Spec : gwapiv1b1.ReferenceGrantSpec {
399+ From : []gwapiv1b1.ReferenceGrantFrom {
400+ {
401+ Group : "aigateway.envoyproxy.io" ,
402+ Kind : "AIGatewayRoute" ,
403+ Namespace : "route-ns" ,
404+ },
405+ },
406+ To : []gwapiv1b1.ReferenceGrantTo {
407+ {
408+ Group : "aigateway.envoyproxy.io" ,
409+ Kind : "AIServiceBackend" ,
410+ },
411+ },
412+ },
413+ }
414+
415+ grant2 := & gwapiv1b1.ReferenceGrant {
416+ ObjectMeta : metav1.ObjectMeta {
417+ Name : "grant-secret" ,
418+ Namespace : "backend-ns" ,
419+ },
420+ Spec : gwapiv1b1.ReferenceGrantSpec {
421+ From : []gwapiv1b1.ReferenceGrantFrom {
422+ {
423+ Group : "gateway.networking.k8s.io" ,
424+ Kind : "HTTPRoute" ,
425+ Namespace : "route-ns" ,
426+ },
427+ },
428+ To : []gwapiv1b1.ReferenceGrantTo {
429+ {
430+ Group : "" ,
431+ Kind : "Secret" ,
432+ },
433+ },
434+ },
435+ }
436+
437+ grant3 := & gwapiv1b1.ReferenceGrant {
438+ ObjectMeta : metav1.ObjectMeta {
439+ Name : "grant-multiple" ,
440+ Namespace : "backend-ns" ,
441+ },
442+ Spec : gwapiv1b1.ReferenceGrantSpec {
443+ From : []gwapiv1b1.ReferenceGrantFrom {
444+ {
445+ Group : "aigateway.envoyproxy.io" ,
446+ Kind : "AIGatewayRoute" ,
447+ Namespace : "route-ns" ,
448+ },
449+ },
450+ To : []gwapiv1b1.ReferenceGrantTo {
451+ {
452+ Group : "aigateway.envoyproxy.io" ,
453+ Kind : "AIServiceBackend" ,
454+ },
455+ {
456+ Group : "" ,
457+ Kind : "Secret" ,
458+ },
459+ },
460+ },
461+ }
462+
463+ require .NoError (t , c .Create (t .Context (), grant1 ))
464+ require .NoError (t , c .Create (t .Context (), grant2 ))
465+ require .NoError (t , c .Create (t .Context (), grant3 ))
466+
467+ t .Run ("query for AIServiceBackend grants in backend-ns" , func (t * testing.T ) {
468+ var grants gwapiv1b1.ReferenceGrantList
469+ err := c .List (t .Context (), & grants ,
470+ client.MatchingFields {k8sClientIndexReferenceGrantToTargetKind : "backend-ns.AIServiceBackend" })
471+ require .NoError (t , err )
472+
473+ // Should find grant1 and grant3 (both allow AIServiceBackend in backend-ns)
474+ require .Len (t , grants .Items , 2 )
475+ names := []string {grants .Items [0 ].Name , grants .Items [1 ].Name }
476+ require .Contains (t , names , "grant-aiservicebackend" )
477+ require .Contains (t , names , "grant-multiple" )
478+ })
479+
480+ t .Run ("query for Secret grants in backend-ns" , func (t * testing.T ) {
481+ var grants gwapiv1b1.ReferenceGrantList
482+ err := c .List (t .Context (), & grants ,
483+ client.MatchingFields {k8sClientIndexReferenceGrantToTargetKind : "backend-ns.Secret" })
484+ require .NoError (t , err )
485+
486+ // Should find grant2 and grant3 (both allow Secret in backend-ns)
487+ require .Len (t , grants .Items , 2 )
488+ names := []string {grants .Items [0 ].Name , grants .Items [1 ].Name }
489+ require .Contains (t , names , "grant-secret" )
490+ require .Contains (t , names , "grant-multiple" )
491+ })
492+
493+ t .Run ("query for non-existent kind" , func (t * testing.T ) {
494+ var grants gwapiv1b1.ReferenceGrantList
495+ err := c .List (t .Context (), & grants ,
496+ client.MatchingFields {k8sClientIndexReferenceGrantToTargetKind : "backend-ns.NonExistentKind" })
497+ require .NoError (t , err )
498+
499+ // Should find nothing
500+ require .Empty (t , grants .Items )
501+ })
502+
503+ t .Run ("query with wrong namespace" , func (t * testing.T ) {
504+ var grants gwapiv1b1.ReferenceGrantList
505+ err := c .List (t .Context (), & grants ,
506+ client.MatchingFields {k8sClientIndexReferenceGrantToTargetKind : "wrong-ns.AIServiceBackend" })
507+ require .NoError (t , err )
508+
509+ // Should find nothing (wrong namespace)
510+ require .Empty (t , grants .Items )
511+ })
512+ }
513+
269514func Test_handleFinalizer (t * testing.T ) {
270515 tests := []struct {
271516 name string
0 commit comments