From 282f2b36f05af04435c7465fcffacb37d373ac92 Mon Sep 17 00:00:00 2001 From: Stefan Prodan Date: Mon, 16 Dec 2024 16:29:55 +0200 Subject: [PATCH 1/2] Preserve HTTPRoute annotations injected by AWS Gateway API Signed-off-by: Stefan Prodan --- pkg/router/gateway_api.go | 25 ++++++++++++++++++------- pkg/router/gateway_api_v1beta1.go | 23 +++++++++++++++++------ 2 files changed, 35 insertions(+), 13 deletions(-) diff --git a/pkg/router/gateway_api.go b/pkg/router/gateway_api.go index bc398afda..65a322893 100644 --- a/pkg/router/gateway_api.go +++ b/pkg/router/gateway_api.go @@ -23,11 +23,6 @@ import ( "slices" "strings" - flaggerv1 "github.com/fluxcd/flagger/pkg/apis/flagger/v1beta1" - v1 "github.com/fluxcd/flagger/pkg/apis/gatewayapi/v1" - "github.com/fluxcd/flagger/pkg/apis/gatewayapi/v1beta1" - istiov1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1" - clientset "github.com/fluxcd/flagger/pkg/client/clientset/versioned" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "go.uber.org/zap" @@ -35,6 +30,12 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/kubernetes" + + flaggerv1 "github.com/fluxcd/flagger/pkg/apis/flagger/v1beta1" + v1 "github.com/fluxcd/flagger/pkg/apis/gatewayapi/v1" + "github.com/fluxcd/flagger/pkg/apis/gatewayapi/v1beta1" + istiov1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1" + clientset "github.com/fluxcd/flagger/pkg/client/clientset/versioned" ) var ( @@ -218,16 +219,26 @@ func (gwr *GatewayAPIRouter) Reconcile(canary *flaggerv1.Canary) error { } if httpRoute != nil { + // Preserve the existing annotations added by other controllers such as AWS Gateway API Controller. + mergedAnnotations := newMetadata.Annotations + for key, val := range httpRoute.Annotations { + if _, ok := mergedAnnotations[key]; !ok { + mergedAnnotations[key] = val + } + } + + // Compare the existing HTTPRoute spec and metadata with the desired state. + // If there are differences, update the HTTPRoute object. specDiff := cmp.Diff( httpRoute.Spec, httpRouteSpec, ignoreCmpOptions..., ) labelsDiff := cmp.Diff(newMetadata.Labels, httpRoute.Labels, cmpopts.EquateEmpty()) - annotationsDiff := cmp.Diff(newMetadata.Annotations, httpRoute.Annotations, cmpopts.EquateEmpty()) + annotationsDiff := cmp.Diff(mergedAnnotations, httpRoute.Annotations, cmpopts.EquateEmpty()) if (specDiff != "" && httpRoute.Name != "") || labelsDiff != "" || annotationsDiff != "" { hrClone := httpRoute.DeepCopy() hrClone.Spec = httpRouteSpec - hrClone.ObjectMeta.Annotations = newMetadata.Annotations + hrClone.ObjectMeta.Annotations = mergedAnnotations hrClone.ObjectMeta.Labels = newMetadata.Labels _, err := gwr.gatewayAPIClient.GatewayapiV1().HTTPRoutes(hrNamespace). Update(context.TODO(), hrClone, metav1.UpdateOptions{}) diff --git a/pkg/router/gateway_api_v1beta1.go b/pkg/router/gateway_api_v1beta1.go index b9d8e40e1..da65e359c 100644 --- a/pkg/router/gateway_api_v1beta1.go +++ b/pkg/router/gateway_api_v1beta1.go @@ -23,10 +23,6 @@ import ( "slices" "strings" - flaggerv1 "github.com/fluxcd/flagger/pkg/apis/flagger/v1beta1" - "github.com/fluxcd/flagger/pkg/apis/gatewayapi/v1beta1" - istiov1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1" - clientset "github.com/fluxcd/flagger/pkg/client/clientset/versioned" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "go.uber.org/zap" @@ -34,6 +30,11 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/client-go/kubernetes" + + flaggerv1 "github.com/fluxcd/flagger/pkg/apis/flagger/v1beta1" + "github.com/fluxcd/flagger/pkg/apis/gatewayapi/v1beta1" + istiov1beta1 "github.com/fluxcd/flagger/pkg/apis/istio/v1beta1" + clientset "github.com/fluxcd/flagger/pkg/client/clientset/versioned" ) var ( @@ -200,16 +201,26 @@ func (gwr *GatewayAPIV1Beta1Router) Reconcile(canary *flaggerv1.Canary) error { } if httpRoute != nil { + // Preserve the existing annotations added by other controllers such as AWS Gateway API Controller. + mergedAnnotations := newMetadata.Annotations + for key, val := range httpRoute.Annotations { + if _, ok := mergedAnnotations[key]; !ok { + mergedAnnotations[key] = val + } + } + + // Compare the existing HTTPRoute spec and metadata with the desired state. + // If there are differences, update the HTTPRoute object. specDiff := cmp.Diff( httpRoute.Spec, httpRouteSpec, ignoreCmpOptions..., ) labelsDiff := cmp.Diff(newMetadata.Labels, httpRoute.Labels, cmpopts.EquateEmpty()) - annotationsDiff := cmp.Diff(newMetadata.Annotations, httpRoute.Annotations, cmpopts.EquateEmpty()) + annotationsDiff := cmp.Diff(mergedAnnotations, httpRoute.Annotations, cmpopts.EquateEmpty()) if (specDiff != "" && httpRoute.Name != "") || labelsDiff != "" || annotationsDiff != "" { hrClone := httpRoute.DeepCopy() hrClone.Spec = httpRouteSpec - hrClone.ObjectMeta.Annotations = newMetadata.Annotations + hrClone.ObjectMeta.Annotations = mergedAnnotations hrClone.ObjectMeta.Labels = newMetadata.Labels _, err := gwr.gatewayAPIClient.GatewayapiV1beta1().HTTPRoutes(hrNamespace). Update(context.TODO(), hrClone, metav1.UpdateOptions{}) From 3b6b550d6471a0d3affdfb068e987e2297c64d90 Mon Sep 17 00:00:00 2001 From: Sanskar Jaiswal Date: Mon, 16 Dec 2024 22:16:05 +0530 Subject: [PATCH 2/2] Add tests for annotations preservation in Gateway API router Signed-off-by: Sanskar Jaiswal --- pkg/router/gateway_api_test.go | 11 +++++++++++ pkg/router/gateway_api_v1beta1_test.go | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/pkg/router/gateway_api_test.go b/pkg/router/gateway_api_test.go index a7d6b6d89..f00ea5549 100644 --- a/pkg/router/gateway_api_test.go +++ b/pkg/router/gateway_api_test.go @@ -57,6 +57,17 @@ func TestGatewayAPIRouter_Reconcile(t *testing.T) { timeout := routeRules[0].Timeouts assert.Equal(t, string(*timeout.Request), canary.Spec.Service.Timeout) + + // assert that http route annotations injected by the networking controller is preserved. + httpRoute.Annotations["foo"] = "bar" + _, err = router.gatewayAPIClient.GatewayapiV1().HTTPRoutes("default").Update(context.TODO(), httpRoute, metav1.UpdateOptions{}) + require.NoError(t, err) + err = router.Reconcile(canary) + require.NoError(t, err) + + httpRoute, err = router.gatewayAPIClient.GatewayapiV1().HTTPRoutes("default").Get(context.TODO(), "podinfo", metav1.GetOptions{}) + require.NoError(t, err) + assert.Equal(t, httpRoute.Annotations["foo"], "bar") } func TestGatewayAPIRouter_Routes(t *testing.T) { diff --git a/pkg/router/gateway_api_v1beta1_test.go b/pkg/router/gateway_api_v1beta1_test.go index 8652aae7c..9ffeda416 100644 --- a/pkg/router/gateway_api_v1beta1_test.go +++ b/pkg/router/gateway_api_v1beta1_test.go @@ -55,6 +55,17 @@ func TestGatewayAPIV1Beta1Router_Reconcile(t *testing.T) { require.Equal(t, len(backendRefs), 2) assert.Equal(t, int32(100), *backendRefs[0].Weight) assert.Equal(t, int32(0), *backendRefs[1].Weight) + + // assert that http route annotations injected by the networking controller is preserved. + httpRoute.Annotations["foo"] = "bar" + _, err = router.gatewayAPIClient.GatewayapiV1beta1().HTTPRoutes("default").Update(context.TODO(), httpRoute, metav1.UpdateOptions{}) + require.NoError(t, err) + err = router.Reconcile(canary) + require.NoError(t, err) + + httpRoute, err = router.gatewayAPIClient.GatewayapiV1beta1().HTTPRoutes("default").Get(context.TODO(), "podinfo", metav1.GetOptions{}) + require.NoError(t, err) + assert.Equal(t, httpRoute.Annotations["foo"], "bar") } func TestGatewayAPIV1Beta1Router_Routes(t *testing.T) {