Merge pull request #1791 from steved/main

fix: gateway router should wait for accepted condition
This commit is contained in:
Stefan Prodan
2025-10-16 12:51:36 +03:00
committed by GitHub
3 changed files with 125 additions and 1 deletions

2
go.mod
View File

@@ -29,6 +29,7 @@ require (
k8s.io/client-go v0.34.1
k8s.io/code-generator v0.34.1
k8s.io/klog/v2 v2.130.1
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397
knative.dev/serving v0.46.6
)
@@ -99,7 +100,6 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/gengo/v2 v2.0.0-20250604051438-85fd79dbfd9f // indirect
k8s.io/kube-openapi v0.0.0-20250710124328-f3f2b991d03b // indirect
k8s.io/utils v0.0.0-20250604170112-4c0f3b243397 // indirect
knative.dev/networking v0.0.0-20250902160145-7dad473f6351 // indirect
knative.dev/pkg v0.0.0-20250909011231-077dcf0d00e8 // indirect
sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect

View File

@@ -273,6 +273,26 @@ func (gwr *GatewayAPIRouter) GetRoutes(canary *flaggerv1.Canary) (
err = fmt.Errorf("HTTPRoute %s.%s get error: %w", apexSvcName, hrNamespace, err)
return
}
currentGeneration := httpRoute.GetGeneration()
for _, parentRef := range httpRoute.Spec.CommonRouteSpec.ParentRefs {
for _, parentStatus := range httpRoute.Status.Parents {
if !reflect.DeepEqual(parentStatus.ParentRef, parentRef) {
continue
}
for _, condition := range parentStatus.Conditions {
if condition.Type == string(v1.RouteConditionAccepted) && (condition.Status != metav1.ConditionTrue || condition.ObservedGeneration < currentGeneration) {
err = fmt.Errorf(
"HTTPRoute %s.%s parent %s is not ready (status: %s, observed generation: %d, current generation: %d)",
apexSvcName, hrNamespace, parentRef.Name, string(condition.Status), condition.ObservedGeneration, currentGeneration,
)
return 0, 0, false, err
}
}
}
}
var weightedRule *v1.HTTPRouteRule
for _, rule := range httpRoute.Spec.Rules {
// If session affinity is enabled, then we are only interested in the rule

View File

@@ -28,6 +28,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/ptr"
flaggerv1 "github.com/fluxcd/flagger/pkg/apis/flagger/v1beta1"
v1 "github.com/fluxcd/flagger/pkg/apis/gatewayapi/v1"
@@ -603,3 +604,106 @@ func TestGatewayAPIRouter_makeFilters_CORS(t *testing.T) {
// Assert MaxAge (24h = 86400 seconds)
assert.Equal(t, int32(86400), corsFilter.CORS.MaxAge)
}
func TestGatewayAPIRouter_GetRoutes(t *testing.T) {
canary := newTestGatewayAPICanary()
mocks := newFixture(canary)
router := &GatewayAPIRouter{
gatewayAPIClient: mocks.meshClient,
kubeClient: mocks.kubeClient,
logger: mocks.logger,
}
httpRoute := &v1.HTTPRoute{
ObjectMeta: metav1.ObjectMeta{
Name: "podinfo",
Generation: 1,
},
Spec: v1.HTTPRouteSpec{
Rules: []v1.HTTPRouteRule{
{
BackendRefs: []v1.HTTPBackendRef{
{
BackendRef: v1.BackendRef{
BackendObjectReference: v1.BackendObjectReference{
Name: "podinfo-canary",
},
Weight: ptr.To(int32(10)),
},
},
{
BackendRef: v1.BackendRef{
BackendObjectReference: v1.BackendObjectReference{
Name: "podinfo-primary",
},
Weight: ptr.To(int32(90)),
},
},
},
},
},
CommonRouteSpec: v1.CommonRouteSpec{
ParentRefs: []v1.ParentReference{
{
Name: "podinfo",
},
},
},
},
}
httpRoute, err := router.gatewayAPIClient.GatewayapiV1().HTTPRoutes("default").Create(context.TODO(), httpRoute, metav1.CreateOptions{})
require.NoError(t, err)
t.Run("httproute generation", func(t *testing.T) {
httpRoute.ObjectMeta.Generation = 5
httpRoute.Status.Parents = []v1.RouteParentStatus{
{
ParentRef: v1.ParentReference{
Name: "podinfo",
SectionName: ptr.To(v1.SectionName("https")),
},
Conditions: []metav1.Condition{
{
Type: string(v1.RouteConditionAccepted),
Status: metav1.ConditionTrue,
ObservedGeneration: 1,
},
},
},
{
ParentRef: v1.ParentReference{
Name: "podinfo",
},
Conditions: []metav1.Condition{
{
Type: string(v1.RouteConditionAccepted),
Status: metav1.ConditionFalse,
ObservedGeneration: 4,
},
},
},
}
httpRoute, err := router.gatewayAPIClient.GatewayapiV1().HTTPRoutes("default").Update(context.TODO(), httpRoute, metav1.UpdateOptions{})
require.NoError(t, err)
_, _, _, err = router.GetRoutes(canary)
require.Error(t, err)
httpRoute.Status.Parents[1].Conditions[0].ObservedGeneration = 5
_, err = router.gatewayAPIClient.GatewayapiV1().HTTPRoutes("default").Update(context.TODO(), httpRoute, metav1.UpdateOptions{})
require.NoError(t, err)
_, _, _, err = router.GetRoutes(canary)
require.Error(t, err)
httpRoute.Status.Parents[1].Conditions[0].Status = metav1.ConditionTrue
_, err = router.gatewayAPIClient.GatewayapiV1().HTTPRoutes("default").Update(context.TODO(), httpRoute, metav1.UpdateOptions{})
require.NoError(t, err)
primaryWeight, canaryWeight, mirrored, err := router.GetRoutes(canary)
require.NoError(t, err)
assert.Equal(t, 90, primaryWeight)
assert.Equal(t, 10, canaryWeight)
assert.False(t, mirrored)
})
}