Skip to content

Commit

Permalink
fix route status
Browse files Browse the repository at this point in the history
Signed-off-by: Huabing Zhao <[email protected]>
  • Loading branch information
zhaohuabing committed Oct 31, 2024
1 parent 82ce107 commit 0991e3f
Show file tree
Hide file tree
Showing 4 changed files with 321 additions and 12 deletions.
44 changes: 33 additions & 11 deletions internal/provider/kubernetes/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context, ext
panic(err)
}
hCopy := h.DeepCopy()
hCopy.Status.Parents = val.Parents
hCopy.Status.Parents = mergeRouteParentStatus(h.Status.Parents, val.Parents)
return hCopy
}),
})
Expand All @@ -97,15 +97,15 @@ func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context, ext
NamespacedName: key,
Resource: new(gwapiv1.GRPCRoute),
Mutator: MutatorFunc(func(obj client.Object) client.Object {
h, ok := obj.(*gwapiv1.GRPCRoute)
g, ok := obj.(*gwapiv1.GRPCRoute)
if !ok {
err := fmt.Errorf("unsupported object type %T", obj)
errChan <- err
panic(err)
}
hCopy := h.DeepCopy()
hCopy.Status.Parents = val.Parents
return hCopy
gCopy := g.DeepCopy()
gCopy.Status.Parents = mergeRouteParentStatus(g.Status.Parents, val.Parents)
return gCopy
}),
})
},
Expand Down Expand Up @@ -136,7 +136,7 @@ func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context, ext
panic(err)
}
tCopy := t.DeepCopy()
tCopy.Status.Parents = val.Parents
tCopy.Status.Parents = mergeRouteParentStatus(t.Status.Parents, val.Parents)
return tCopy
}),
})
Expand Down Expand Up @@ -168,7 +168,7 @@ func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context, ext
panic(err)
}
tCopy := t.DeepCopy()
tCopy.Status.Parents = val.Parents
tCopy.Status.Parents = mergeRouteParentStatus(t.Status.Parents, val.Parents)
return tCopy
}),
})
Expand All @@ -193,15 +193,15 @@ func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context, ext
NamespacedName: key,
Resource: new(gwapiv1a2.UDPRoute),
Mutator: MutatorFunc(func(obj client.Object) client.Object {
t, ok := obj.(*gwapiv1a2.UDPRoute)
u, ok := obj.(*gwapiv1a2.UDPRoute)
if !ok {
err := fmt.Errorf("unsupported object type %T", obj)
errChan <- err
panic(err)
}
tCopy := t.DeepCopy()
tCopy.Status.Parents = val.Parents
return tCopy
uCopy := u.DeepCopy()
uCopy.Status.Parents = mergeRouteParentStatus(u.Status.Parents, val.Parents)
return uCopy
}),
})
},
Expand Down Expand Up @@ -469,6 +469,28 @@ func (r *gatewayAPIReconciler) subscribeAndUpdateStatus(ctx context.Context, ext
}
}

// mergeRouteParentStatus merges the old and new RouteParentStatus.
// This is needed because the RouteParentStatus doesn't support strategic merge patch yet.
func mergeRouteParentStatus(old, new []gwapiv1.RouteParentStatus) []gwapiv1.RouteParentStatus {
merged := make([]gwapiv1.RouteParentStatus, len(old))
_ = copy(merged, old)
for _, parent := range new {
found := -1
for i, existing := range old {
if parent.ParentRef.Name == existing.ParentRef.Name {
found = i
break
}
}
if found >= 0 {
merged[found] = parent
} else {
merged = append(merged, parent)
}
}
return merged
}

func (r *gatewayAPIReconciler) updateStatusForGateway(ctx context.Context, gtw *gwapiv1.Gateway) {
// nil check for unit tests.
if r.statusUpdater == nil {
Expand Down
286 changes: 286 additions & 0 deletions internal/provider/kubernetes/status_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,286 @@
// Copyright Envoy Gateway Authors
// SPDX-License-Identifier: Apache-2.0
// The full text of the Apache license is available in the LICENSE file at
// the root of the repo.

package kubernetes

import (
"reflect"
"testing"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
gwapiv1 "sigs.k8s.io/gateway-api/apis/v1"
)

func Test_mergeRouteParentStatus(t *testing.T) {
type args struct {
old []gwapiv1.RouteParentStatus
new []gwapiv1.RouteParentStatus
}
tests := []struct {
name string
args args
want []gwapiv1.RouteParentStatus
}{
{
name: "merge old and new",
args: args{
old: []gwapiv1.RouteParentStatus{
{
ControllerName: "gateway.envoyproxy.io/gatewayclass-controller",
ParentRef: gwapiv1.ParentReference{
Name: "gateway1",
},
Conditions: []metav1.Condition{
{
Type: string(gwapiv1.RouteConditionAccepted),
Status: metav1.ConditionTrue,
Reason: "Accepted",
},
{
Type: string(gwapiv1.RouteConditionResolvedRefs),
Status: metav1.ConditionTrue,
Reason: "ResolvedRefs",
},
},
},
},
new: []gwapiv1.RouteParentStatus{
{
ControllerName: "gateway.envoyproxy.io/gatewayclass-controller",
ParentRef: gwapiv1.ParentReference{
Name: "gateway2",
},
Conditions: []metav1.Condition{
{
Type: string(gwapiv1.RouteConditionAccepted),
Status: metav1.ConditionFalse,
Reason: "SomeReason",
},
},
},
},
},
want: []gwapiv1.RouteParentStatus{
{
ControllerName: "gateway.envoyproxy.io/gatewayclass-controller",
ParentRef: gwapiv1.ParentReference{
Name: "gateway1",
},
Conditions: []metav1.Condition{
{
Type: string(gwapiv1.RouteConditionAccepted),
Status: metav1.ConditionTrue,
Reason: "Accepted",
},
{
Type: string(gwapiv1.RouteConditionResolvedRefs),
Status: metav1.ConditionTrue,
Reason: "ResolvedRefs",
},
},
},
{
ControllerName: "gateway.envoyproxy.io/gatewayclass-controller",
ParentRef: gwapiv1.ParentReference{
Name: "gateway2",
},
Conditions: []metav1.Condition{
{
Type: string(gwapiv1.RouteConditionAccepted),
Status: metav1.ConditionFalse,
Reason: "SomeReason",
},
},
},
},
},

{
name: "override an existing parent",
args: args{
old: []gwapiv1.RouteParentStatus{
{
ControllerName: "gateway.envoyproxy.io/gatewayclass-controller",
ParentRef: gwapiv1.ParentReference{
Name: "gateway1",
},
Conditions: []metav1.Condition{
{
Type: string(gwapiv1.RouteConditionAccepted),
Status: metav1.ConditionTrue,
Reason: "Accepted",
},
{
Type: string(gwapiv1.RouteConditionResolvedRefs),
Status: metav1.ConditionTrue,
Reason: "ResolvedRefs",
},
},
},
{
ControllerName: "gateway.envoyproxy.io/gatewayclass-controller",
ParentRef: gwapiv1.ParentReference{
Name: "gateway2",
},
Conditions: []metav1.Condition{
{
Type: string(gwapiv1.RouteConditionAccepted),
Status: metav1.ConditionTrue,
Reason: "Accepted",
},
{
Type: string(gwapiv1.RouteConditionResolvedRefs),
Status: metav1.ConditionTrue,
Reason: "ResolvedRefs",
},
},
},
},
new: []gwapiv1.RouteParentStatus{
{
ControllerName: "gateway.envoyproxy.io/gatewayclass-controller",
ParentRef: gwapiv1.ParentReference{
Name: "gateway2",
},
Conditions: []metav1.Condition{
{
Type: string(gwapiv1.RouteConditionAccepted),
Status: metav1.ConditionFalse,
Reason: "SomeReason",
},
},
},
},
},
want: []gwapiv1.RouteParentStatus{
{
ControllerName: "gateway.envoyproxy.io/gatewayclass-controller",
ParentRef: gwapiv1.ParentReference{
Name: "gateway1",
},
Conditions: []metav1.Condition{
{
Type: string(gwapiv1.RouteConditionAccepted),
Status: metav1.ConditionTrue,
Reason: "Accepted",
},
{
Type: string(gwapiv1.RouteConditionResolvedRefs),
Status: metav1.ConditionTrue,
Reason: "ResolvedRefs",
},
},
},
{
ControllerName: "gateway.envoyproxy.io/gatewayclass-controller",
ParentRef: gwapiv1.ParentReference{
Name: "gateway2",
},
Conditions: []metav1.Condition{
{
Type: string(gwapiv1.RouteConditionAccepted),
Status: metav1.ConditionFalse,
Reason: "SomeReason",
},
},
},
},
},

{
name: "nothing changed",
args: args{
old: []gwapiv1.RouteParentStatus{
{
ControllerName: "gateway.envoyproxy.io/gatewayclass-controller",
ParentRef: gwapiv1.ParentReference{
Name: "gateway1",
},
Conditions: []metav1.Condition{
{
Type: string(gwapiv1.RouteConditionAccepted),
Status: metav1.ConditionTrue,
Reason: "Accepted",
},
{
Type: string(gwapiv1.RouteConditionResolvedRefs),
Status: metav1.ConditionTrue,
Reason: "ResolvedRefs",
},
},
},
{
ControllerName: "gateway.envoyproxy.io/gatewayclass-controller",
ParentRef: gwapiv1.ParentReference{
Name: "gateway2",
},
Conditions: []metav1.Condition{
{
Type: string(gwapiv1.RouteConditionAccepted),
Status: metav1.ConditionFalse,
Reason: "SomeReason",
},
},
},
},
new: []gwapiv1.RouteParentStatus{
{
ControllerName: "gateway.envoyproxy.io/gatewayclass-controller",
ParentRef: gwapiv1.ParentReference{
Name: "gateway2",
},
Conditions: []metav1.Condition{
{
Type: string(gwapiv1.RouteConditionAccepted),
Status: metav1.ConditionFalse,
Reason: "SomeReason",
},
},
},
},
},
want: []gwapiv1.RouteParentStatus{
{
ControllerName: "gateway.envoyproxy.io/gatewayclass-controller",
ParentRef: gwapiv1.ParentReference{
Name: "gateway1",
},
Conditions: []metav1.Condition{
{
Type: string(gwapiv1.RouteConditionAccepted),
Status: metav1.ConditionTrue,
Reason: "Accepted",
},
{
Type: string(gwapiv1.RouteConditionResolvedRefs),
Status: metav1.ConditionTrue,
Reason: "ResolvedRefs",
},
},
},
{
ControllerName: "gateway.envoyproxy.io/gatewayclass-controller",
ParentRef: gwapiv1.ParentReference{
Name: "gateway2",
},
Conditions: []metav1.Condition{
{
Type: string(gwapiv1.RouteConditionAccepted),
Status: metav1.ConditionFalse,
Reason: "SomeReason",
},
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := mergeRouteParentStatus(tt.args.old, tt.args.new); !reflect.DeepEqual(got, tt.want) {
t.Errorf("mergeRouteParentStatus() = %v, want %v", got, tt.want)
}
})
}
}
2 changes: 1 addition & 1 deletion internal/provider/kubernetes/status_updater.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func (u *UpdateHandler) apply(update Update) {
}

newObj.SetUID(obj.GetUID())

return u.client.Status().Update(context.Background(), newObj)
}); err != nil {
u.log.Error(err, "unable to update status", "name", update.NamespacedName.Name,
Expand Down
1 change: 1 addition & 0 deletions release-notes/current.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ new features: |
bug fixes: |
Only log endpoint configuration in verbose logging mode (`-v 4` or higher)
The xDS translation failed when wasm http code source configured without a sha
HTTPRoute status only shows one parent when targeting multiple Gateways from different GatewayClasses
# Enhancements that improve performance.
performance improvements: |
Expand Down

0 comments on commit 0991e3f

Please sign in to comment.