Skip to content

Commit fce1781

Browse files
authored
Merge pull request #1791 from steved/main
fix: gateway router should wait for accepted condition
2 parents 461abc9 + bb7ad65 commit fce1781

File tree

3 files changed

+125
-1
lines changed

3 files changed

+125
-1
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ require (
2929
k8s.io/client-go v0.34.1
3030
k8s.io/code-generator v0.34.1
3131
k8s.io/klog/v2 v2.130.1
32+
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397
3233
knative.dev/serving v0.46.6
3334
)
3435

@@ -99,7 +100,6 @@ require (
99100
gopkg.in/yaml.v3 v3.0.1 // indirect
100101
k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f // indirect
101102
k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect
102-
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect
103103
knative.dev/networking v0.0.0-20250902160145-7dad473f6351 // indirect
104104
knative.dev/pkg v0.0.0-20250909011231-077dcf0d00e8 // indirect
105105
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect

pkg/router/gateway_api.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,26 @@ func (gwr *GatewayAPIRouter) GetRoutes(canary *flaggerv1.Canary) (
273273
err = fmt.Errorf("HTTPRoute %s.%s get error: %w", apexSvcName, hrNamespace, err)
274274
return
275275
}
276+
277+
currentGeneration := httpRoute.GetGeneration()
278+
for _, parentRef := range httpRoute.Spec.CommonRouteSpec.ParentRefs {
279+
for _, parentStatus := range httpRoute.Status.Parents {
280+
if !reflect.DeepEqual(parentStatus.ParentRef, parentRef) {
281+
continue
282+
}
283+
284+
for _, condition := range parentStatus.Conditions {
285+
if condition.Type == string(v1.RouteConditionAccepted) && (condition.Status != metav1.ConditionTrue || condition.ObservedGeneration < currentGeneration) {
286+
err = fmt.Errorf(
287+
"HTTPRoute %s.%s parent %s is not ready (status: %s, observed generation: %d, current generation: %d)",
288+
apexSvcName, hrNamespace, parentRef.Name, string(condition.Status), condition.ObservedGeneration, currentGeneration,
289+
)
290+
return 0, 0, false, err
291+
}
292+
}
293+
}
294+
}
295+
276296
var weightedRule *v1.HTTPRouteRule
277297
for _, rule := range httpRoute.Spec.Rules {
278298
// If session affinity is enabled, then we are only interested in the rule

pkg/router/gateway_api_test.go

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"github.com/stretchr/testify/assert"
2929
"github.com/stretchr/testify/require"
3030
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
31+
"k8s.io/utils/ptr"
3132

3233
flaggerv1 "github.com/fluxcd/flagger/pkg/apis/flagger/v1beta1"
3334
v1 "github.com/fluxcd/flagger/pkg/apis/gatewayapi/v1"
@@ -603,3 +604,106 @@ func TestGatewayAPIRouter_makeFilters_CORS(t *testing.T) {
603604
// Assert MaxAge (24h = 86400 seconds)
604605
assert.Equal(t, int32(86400), corsFilter.CORS.MaxAge)
605606
}
607+
608+
func TestGatewayAPIRouter_GetRoutes(t *testing.T) {
609+
canary := newTestGatewayAPICanary()
610+
mocks := newFixture(canary)
611+
router := &GatewayAPIRouter{
612+
gatewayAPIClient: mocks.meshClient,
613+
kubeClient: mocks.kubeClient,
614+
logger: mocks.logger,
615+
}
616+
617+
httpRoute := &v1.HTTPRoute{
618+
ObjectMeta: metav1.ObjectMeta{
619+
Name: "podinfo",
620+
Generation: 1,
621+
},
622+
Spec: v1.HTTPRouteSpec{
623+
Rules: []v1.HTTPRouteRule{
624+
{
625+
BackendRefs: []v1.HTTPBackendRef{
626+
{
627+
BackendRef: v1.BackendRef{
628+
BackendObjectReference: v1.BackendObjectReference{
629+
Name: "podinfo-canary",
630+
},
631+
Weight: ptr.To(int32(10)),
632+
},
633+
},
634+
{
635+
BackendRef: v1.BackendRef{
636+
BackendObjectReference: v1.BackendObjectReference{
637+
Name: "podinfo-primary",
638+
},
639+
Weight: ptr.To(int32(90)),
640+
},
641+
},
642+
},
643+
},
644+
},
645+
CommonRouteSpec: v1.CommonRouteSpec{
646+
ParentRefs: []v1.ParentReference{
647+
{
648+
Name: "podinfo",
649+
},
650+
},
651+
},
652+
},
653+
}
654+
httpRoute, err := router.gatewayAPIClient.GatewayapiV1().HTTPRoutes("default").Create(context.TODO(), httpRoute, metav1.CreateOptions{})
655+
require.NoError(t, err)
656+
657+
t.Run("httproute generation", func(t *testing.T) {
658+
httpRoute.ObjectMeta.Generation = 5
659+
httpRoute.Status.Parents = []v1.RouteParentStatus{
660+
{
661+
ParentRef: v1.ParentReference{
662+
Name: "podinfo",
663+
SectionName: ptr.To(v1.SectionName("https")),
664+
},
665+
Conditions: []metav1.Condition{
666+
{
667+
Type: string(v1.RouteConditionAccepted),
668+
Status: metav1.ConditionTrue,
669+
ObservedGeneration: 1,
670+
},
671+
},
672+
},
673+
{
674+
ParentRef: v1.ParentReference{
675+
Name: "podinfo",
676+
},
677+
Conditions: []metav1.Condition{
678+
{
679+
Type: string(v1.RouteConditionAccepted),
680+
Status: metav1.ConditionFalse,
681+
ObservedGeneration: 4,
682+
},
683+
},
684+
},
685+
}
686+
httpRoute, err := router.gatewayAPIClient.GatewayapiV1().HTTPRoutes("default").Update(context.TODO(), httpRoute, metav1.UpdateOptions{})
687+
require.NoError(t, err)
688+
689+
_, _, _, err = router.GetRoutes(canary)
690+
require.Error(t, err)
691+
692+
httpRoute.Status.Parents[1].Conditions[0].ObservedGeneration = 5
693+
_, err = router.gatewayAPIClient.GatewayapiV1().HTTPRoutes("default").Update(context.TODO(), httpRoute, metav1.UpdateOptions{})
694+
require.NoError(t, err)
695+
696+
_, _, _, err = router.GetRoutes(canary)
697+
require.Error(t, err)
698+
699+
httpRoute.Status.Parents[1].Conditions[0].Status = metav1.ConditionTrue
700+
_, err = router.gatewayAPIClient.GatewayapiV1().HTTPRoutes("default").Update(context.TODO(), httpRoute, metav1.UpdateOptions{})
701+
require.NoError(t, err)
702+
703+
primaryWeight, canaryWeight, mirrored, err := router.GetRoutes(canary)
704+
require.NoError(t, err)
705+
assert.Equal(t, 90, primaryWeight)
706+
assert.Equal(t, 10, canaryWeight)
707+
assert.False(t, mirrored)
708+
})
709+
}

0 commit comments

Comments
 (0)