mirror of
https://github.com/fluxcd/flagger.git
synced 2026-04-15 06:57:34 +00:00
fix: gateway router should wait for accepted condition
It can take some time for changes to propagate for cloud load balancers, so flagger should ensure the route changes are current before proceeding with any more. Signed-off-by: Steven Davidovitz <sdavidovitz@groq.com>
This commit is contained in:
2
go.mod
2
go.mod
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user