diff --git a/internal/gatewayapi/status/conditions.go b/internal/gatewayapi/status/conditions.go index 576281cb3a..6de6f4a92f 100644 --- a/internal/gatewayapi/status/conditions.go +++ b/internal/gatewayapi/status/conditions.go @@ -14,9 +14,10 @@ package status import ( - "reflect" "unicode" + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -36,7 +37,7 @@ func MergeConditions(conditions []metav1.Condition, updates ...metav1.Condition) for j := range conditions { if conditions[j].Type == update.Type { add = false - if !reflect.DeepEqual(conditions[j], update) { + if conditionChanged(&conditions[j], &update) { conditions[j].Status = update.Status conditions[j].Reason = update.Reason conditions[j].Message = update.Message @@ -53,6 +54,11 @@ func MergeConditions(conditions []metav1.Condition, updates ...metav1.Condition) return conditions } +func conditionChanged(a, b *metav1.Condition) bool { + opts := cmpopts.IgnoreFields(metav1.Condition{}, "Type", "LastTransitionTime") + return !cmp.Equal(*a, *b, opts) +} + func newCondition(t string, status metav1.ConditionStatus, reason, msg string, og int64) metav1.Condition { return metav1.Condition{ Type: t, diff --git a/internal/gatewayapi/status/conditions_test.go b/internal/gatewayapi/status/conditions_test.go index b3ed1b2912..e43a7c7199 100644 --- a/internal/gatewayapi/status/conditions_test.go +++ b/internal/gatewayapi/status/conditions_test.go @@ -15,7 +15,6 @@ package status import ( "errors" - "reflect" "strings" "testing" @@ -41,6 +40,20 @@ func TestConditionChanged(t *testing.T) { a: metav1.Condition{}, b: metav1.Condition{}, }, + { + name: "condition LastTransitionTime should be ignored", + expected: false, + a: metav1.Condition{ + Type: string(gwapiv1.GatewayClassConditionStatusAccepted), + Status: metav1.ConditionTrue, + LastTransitionTime: metav1.Unix(0, 0), + }, + b: metav1.Condition{ + Type: string(gwapiv1.GatewayClassConditionStatusAccepted), + Status: metav1.ConditionTrue, + LastTransitionTime: metav1.Unix(1, 0), + }, + }, { name: "check condition reason differs", expected: true, @@ -70,7 +83,7 @@ func TestConditionChanged(t *testing.T) { } for _, tc := range testCases { - if got := !reflect.DeepEqual(tc.a, tc.b); got != tc.expected { + if got := conditionChanged(&tc.a, &tc.b); got != tc.expected { assert.Equal(t, tc.expected, got, tc.name) } } diff --git a/release-notes/current.yaml b/release-notes/current.yaml index a2a4673618..5c2c6edd30 100644 --- a/release-notes/current.yaml +++ b/release-notes/current.yaml @@ -15,6 +15,7 @@ bug fixes: | Fixed ListenerSet and its listeners incorrectly setting `Accepted: False` for InvalidCertificateRef and RefNotPermitted, inconsistent with Gateway behavior and the Gateway API spec. Fixed active HTTP health checks to use Backend endpoint hostnames before falling back to the effective Route hostname. Fixed HTTPS listeners with overlapping hostnames but disjoint certificate SANs to preserve HTTP/2 ALPN by default. + Fixed Gateway getting stuck at `Programmed=False` after its LoadBalancer Service IP was restored, by ignoring `LastTransitionTime` when comparing status conditions. # Enhancements that improve performance. performance improvements: |