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:
@@ -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