@@ -23,8 +23,11 @@ import (
2323 "time"
2424
2525 corev1 "k8s.io/api/core/v1"
26+ apierrs "k8s.io/apimachinery/pkg/api/errors"
2627 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28+ "k8s.io/apimachinery/pkg/labels"
2729 "k8s.io/apimachinery/pkg/runtime"
30+ "k8s.io/apimachinery/pkg/runtime/schema"
2831 "k8s.io/apimachinery/pkg/types"
2932 clientgotesting "k8s.io/client-go/testing"
3033 "k8s.io/utils/ptr"
@@ -47,6 +50,7 @@ import (
4750
4851 gatewayapi "sigs.k8s.io/gateway-api/apis/v1"
4952 gatewayapiv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1"
53+ gatewaylisters "sigs.k8s.io/gateway-api/pkg/client/listers/apis/v1"
5054
5155 . "knative.dev/net-gateway-api/pkg/reconciler/testing"
5256 . "knative.dev/pkg/reconciler/testing"
@@ -196,6 +200,103 @@ func TestReconcile(t *testing.T) {
196200 httpRoute (t , ing (withBasicSpec , withGatewayAPIclass ), httpRouteReady ),
197201 }, servicesAndEndpoints ... ),
198202 // no extra update
203+ }, {
204+ Name : "prune stale HTTPRoute when rule removed" ,
205+ Key : "ns/name" ,
206+ Objects : append ([]runtime.Object {
207+ ing (withBasicSpec , withGatewayAPIclass , withFinalizer , makeItReady ),
208+ httpRoute (t , ing (withBasicSpec , withGatewayAPIclass ), httpRouteReady ),
209+ HTTPRoute {
210+ Name : "stale.example.com" ,
211+ Namespace : "ns" ,
212+ Hostname : "stale.example.com" ,
213+ }.Build (),
214+ }, servicesAndEndpoints ... ),
215+ WantDeletes : []clientgotesting.DeleteActionImpl {
216+ clientgotesting .NewDeleteAction (
217+ schema.GroupVersionResource {
218+ Group : "gateway.networking.k8s.io" ,
219+ Version : "v1" ,
220+ Resource : "httproutes" ,
221+ },
222+ "ns" ,
223+ "stale.example.com" ,
224+ ),
225+ },
226+ }, {
227+ Name : "prune skips non-owned HTTPRoute" ,
228+ Key : "ns/name" ,
229+ Objects : append (func () []runtime.Object {
230+ route := HTTPRoute {
231+ Name : "stale.example.com" ,
232+ Namespace : "ns" ,
233+ Hostname : "stale.example.com" ,
234+ }.Build ()
235+ // Remove owner so it is not controlled by this Ingress
236+ route .OwnerReferences = nil
237+ return []runtime.Object {
238+ ing (withBasicSpec , withGatewayAPIclass , withFinalizer , makeItReady ),
239+ httpRoute (t , ing (withBasicSpec , withGatewayAPIclass ), httpRouteReady ),
240+ route ,
241+ }
242+ }(), servicesAndEndpoints ... ),
243+ // No deletes expected
244+ WantDeletes : []clientgotesting.DeleteActionImpl {},
245+ }, {
246+ Name : "prune list error bubbles up" ,
247+ Key : "ns/name" ,
248+ Ctx : withHTTPRouteListError (),
249+ Objects : append ([]runtime.Object {
250+ ing (withBasicSpec , withGatewayAPIclass , withFinalizer , makeItReady ),
251+ }, servicesAndEndpoints ... ),
252+ WantCreates : []runtime.Object {
253+ httpRoute (t , ing (withBasicSpec , withGatewayAPIclass )),
254+ },
255+ WantStatusUpdates : []clientgotesting.UpdateActionImpl {{
256+ Object : ing (withBasicSpec , withGatewayAPIclass , withFinalizer , makeItReady , func (i * v1alpha1.Ingress ) {
257+ i .Status .MarkIngressNotReady ("ReconcileIngressFailed" , "Ingress reconciliation failed" )
258+ }),
259+ }},
260+ WantEvents : []string {
261+ Eventf (corev1 .EventTypeNormal , "Created" , "Created HTTPRoute \" example.com\" " ),
262+ Eventf (corev1 .EventTypeWarning , "InternalError" , `failed to list HTTPRoutes: forced list error` ),
263+ },
264+ WantErr : true ,
265+ }, {
266+ Name : "prune delete NotFound tolerated" ,
267+ Key : "ns/name" ,
268+ WithReactors : []clientgotesting.ReactionFunc {
269+ func (a clientgotesting.Action ) (bool , runtime.Object , error ) {
270+ if a .GetVerb () == "delete" && a .GetResource ().Resource == "httproutes" {
271+ name := a .(clientgotesting.DeleteActionImpl ).Name
272+ return true , nil , apierrs .NewNotFound (
273+ schema.GroupResource {Group : "gateway.networking.k8s.io" , Resource : "httproutes" },
274+ name ,
275+ )
276+ }
277+ return false , nil , nil
278+ },
279+ },
280+ Objects : append ([]runtime.Object {
281+ ing (withBasicSpec , withGatewayAPIclass , withFinalizer , makeItReady ),
282+ httpRoute (t , ing (withBasicSpec , withGatewayAPIclass ), httpRouteReady ),
283+ HTTPRoute {
284+ Name : "stale.example.com" ,
285+ Namespace : "ns" ,
286+ Hostname : "stale.example.com" ,
287+ }.Build (),
288+ }, servicesAndEndpoints ... ),
289+ WantDeletes : []clientgotesting.DeleteActionImpl {
290+ clientgotesting .NewDeleteAction (
291+ schema.GroupVersionResource {
292+ Group : "gateway.networking.k8s.io" ,
293+ Version : "v1" ,
294+ Resource : "httproutes" ,
295+ },
296+ "ns" ,
297+ "stale.example.com" ,
298+ ),
299+ },
199300 }}
200301
201302 table .Test (t , MakeFactory (func (ctx context.Context , listers * Listers , cmw configmap.Watcher ) controller.Reconciler {
@@ -214,6 +315,11 @@ func TestReconcile(t *testing.T) {
214315 },
215316 }
216317
318+ // Force HTTPRoute List error when test context requests it.
319+ if ctx .Value (httpRouteListErrorKey {}) == true {
320+ r .httprouteLister = errorWrapHTTPRouteLister {inner : listers .GetHTTPRouteLister ()}
321+ }
322+
217323 ingr := ingressreconciler .NewReconciler (ctx , logging .FromContext (ctx ), fakeingressclient .Get (ctx ),
218324 listers .GetIngressLister (), controller .GetEventRecorder (ctx ), r , gatewayAPIIngressClassName ,
219325 controller.Options {
@@ -226,6 +332,38 @@ func TestReconcile(t *testing.T) {
226332 }))
227333}
228334
335+ // --- helpers for forcing lister errors in specific tests ---
336+
337+ type httpRouteListErrorKey struct {}
338+
339+ func withHTTPRouteListError () context.Context {
340+ return context .WithValue (context .Background (), httpRouteListErrorKey {}, true )
341+ }
342+
343+ type errorWrapHTTPRouteNamespaceLister struct {
344+ inner gatewaylisters.HTTPRouteNamespaceLister
345+ }
346+
347+ func (e errorWrapHTTPRouteNamespaceLister ) List (selector labels.Selector ) ([]* gatewayapi.HTTPRoute , error ) {
348+ return nil , fmt .Errorf ("forced list error" )
349+ }
350+
351+ func (e errorWrapHTTPRouteNamespaceLister ) Get (name string ) (* gatewayapi.HTTPRoute , error ) {
352+ return e .inner .Get (name )
353+ }
354+
355+ type errorWrapHTTPRouteLister struct {
356+ inner gatewaylisters.HTTPRouteLister
357+ }
358+
359+ func (e errorWrapHTTPRouteLister ) List (selector labels.Selector ) ([]* gatewayapi.HTTPRoute , error ) {
360+ return e .inner .List (selector )
361+ }
362+
363+ func (e errorWrapHTTPRouteLister ) HTTPRoutes (namespace string ) gatewaylisters.HTTPRouteNamespaceLister {
364+ return errorWrapHTTPRouteNamespaceLister {inner : e .inner .HTTPRoutes (namespace )}
365+ }
366+
229367func TestReconcileTLS (t * testing.T ) {
230368 // The gateway API annoyingly has a number of
231369 secretName := "name-WE-STICK-A-LONG-UID-HERE"
0 commit comments