diff --git a/internal/provider/kubernetes/controller.go b/internal/provider/kubernetes/controller.go index 492bef67b1..b1637bd63b 100644 --- a/internal/provider/kubernetes/controller.go +++ b/internal/provider/kubernetes/controller.go @@ -1267,7 +1267,7 @@ func (r *gatewayAPIReconciler) processBtpConfigMapRefs( ) error { for _, policy := range resourceTree.BackendTrafficPolicies { for _, ro := range policy.Spec.ResponseOverride { - if ro.Response.Body != nil && ro.Response.Body.ValueRef != nil && string(ro.Response.Body.ValueRef.Kind) == resource.KindConfigMap { + if ro.Response != nil && ro.Response.Body != nil && ro.Response.Body.ValueRef != nil && string(ro.Response.Body.ValueRef.Kind) == resource.KindConfigMap { configMap := new(corev1.ConfigMap) err := r.client.Get(ctx, types.NamespacedName{Namespace: policy.Namespace, Name: string(ro.Response.Body.ValueRef.Name)}, diff --git a/internal/provider/kubernetes/indexers.go b/internal/provider/kubernetes/indexers.go index 11418f63da..2b9b5efdb3 100644 --- a/internal/provider/kubernetes/indexers.go +++ b/internal/provider/kubernetes/indexers.go @@ -837,7 +837,7 @@ func configMapBtpIndexFunc(rawObj client.Object) []string { var configMapReferences []string for _, ro := range btp.Spec.ResponseOverride { - if ro.Response.Body != nil && ro.Response.Body.ValueRef != nil { + if ro.Response != nil && ro.Response.Body != nil && ro.Response.Body.ValueRef != nil { if string(ro.Response.Body.ValueRef.Kind) == resource.KindConfigMap { configMapReferences = append(configMapReferences, types.NamespacedName{ diff --git a/internal/provider/kubernetes/predicates_test.go b/internal/provider/kubernetes/predicates_test.go index 61125e80a4..7478febea0 100644 --- a/internal/provider/kubernetes/predicates_test.go +++ b/internal/provider/kubernetes/predicates_test.go @@ -286,6 +286,42 @@ func TestValidateConfigMapForReconcile(t *testing.T) { } } +// TestValidateBackendTrafficPolicyForReconcileWithRedirectResponseOverride tests the validateBackendTrafficPolicyForReconcile +// predicate function with a redirect response override. +func TestValidateBackendTrafficPolicyForReconcileWithRedirectResponseOverride(t *testing.T) { + btpWithRedirect := &egv1a1.BackendTrafficPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: "response-override", + Namespace: "envoy-gateway-system", + }, + Spec: egv1a1.BackendTrafficPolicySpec{ + ResponseOverride: []*egv1a1.ResponseOverride{ + { + Match: egv1a1.CustomResponseMatch{ + StatusCodes: []egv1a1.StatusCodeMatch{ + { + Type: &[]egv1a1.StatusCodeValueType{egv1a1.StatusCodeValueTypeRange}[0], + Range: &egv1a1.StatusCodeRange{ + Start: 500, + End: 511, + }, + }, + }, + }, + // Using redirect instead of response causes ro.Response to be nil + Redirect: &egv1a1.CustomRedirect{ + Hostname: &[]gwapiv1.PreciseHostname{"custom-errors.example.com"}[0], + StatusCode: &[]int{302}[0], + Scheme: &[]string{"https"}[0], + }, + }, + }, + }, + } + result := configMapBtpIndexFunc(btpWithRedirect) + require.Empty(t, result) +} + // TestValidateSecretForReconcile tests the validateSecretForReconcile // predicate function. func TestValidateSecretForReconcile(t *testing.T) { diff --git a/release-notes/current.yaml b/release-notes/current.yaml index 428d2defd6..5cc1b58fee 100644 --- a/release-notes/current.yaml +++ b/release-notes/current.yaml @@ -17,6 +17,7 @@ bug fixes: | Fixed log formatting of improper key-value pairs to avoid DPANIC in controller-runtime logger. Fixed handling of context-related transient errors to prevent incorrect state reconciliation and unintended behavior. Fixed the controller cannot read the EnvoyProxy attached gatewayclass only. + Fixed indexer and controller crashing when BackendTrafficPolicy has a redirect response override. # Enhancements that improve performance. performance improvements: |