WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit 878cec5

Browse files
committed
fix: aggregate xRoute/xPolicy statuses across GWCs in gateway-api runner
Signed-off-by: y-rabie <[email protected]>
1 parent 0fa26d7 commit 878cec5

File tree

3 files changed

+293
-99
lines changed

3 files changed

+293
-99
lines changed

internal/gatewayapi/extensionserverpolicy.go

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ func (t *Translator) ProcessExtensionServerPolicies(policies []unstructured.Unst
8181
}
8282
if accepted {
8383
res = append(res, *policy)
84-
policy.Object["status"] = policyStatusToUnstructured(policyStatus)
84+
policy.Object["status"] = PolicyStatusToUnstructured(policyStatus)
8585
}
8686
}
8787

@@ -108,14 +108,6 @@ func extractTargetRefs(policy *unstructured.Unstructured, gateways []*GatewayCon
108108
return ret, nil
109109
}
110110

111-
func policyStatusToUnstructured(policyStatus gwapiv1.PolicyStatus) map[string]any {
112-
ret := map[string]any{}
113-
// No need to check the marshal/unmarshal error here
114-
d, _ := json.Marshal(policyStatus)
115-
_ = json.Unmarshal(d, &ret)
116-
return ret
117-
}
118-
119111
func resolveExtServerPolicyGatewayTargetRef(policy *unstructured.Unstructured, target gwapiv1.LocalPolicyTargetReferenceWithSectionName, gateways map[types.NamespacedName]*policyGatewayTargetContext) *GatewayContext {
120112
// Check if the gateway exists
121113
key := types.NamespacedName{
@@ -132,6 +124,29 @@ func resolveExtServerPolicyGatewayTargetRef(policy *unstructured.Unstructured, t
132124
return gateway.GatewayContext
133125
}
134126

127+
func PolicyStatusToUnstructured(policyStatus gwapiv1.PolicyStatus) map[string]any {
128+
ret := map[string]any{}
129+
// No need to check the marshal/unmarshal error here
130+
d, _ := json.Marshal(policyStatus)
131+
_ = json.Unmarshal(d, &ret)
132+
return ret
133+
}
134+
135+
func ExtServerPolicyStatusAsPolicyStatus(policy *unstructured.Unstructured) gwapiv1.PolicyStatus {
136+
statusObj := policy.Object["status"]
137+
status := gwapiv1.PolicyStatus{}
138+
if _, ok := statusObj.(map[string]any); ok {
139+
// No need to check the json marshal/unmarshal error, the policyStatus was
140+
// created via a typed object so the marshalling/unmarshalling will always
141+
// work
142+
d, _ := json.Marshal(statusObj)
143+
_ = json.Unmarshal(d, &status)
144+
} else if _, ok := statusObj.(gwapiv1.PolicyStatus); ok {
145+
status = statusObj.(gwapiv1.PolicyStatus)
146+
}
147+
return status
148+
}
149+
135150
func (t *Translator) translateExtServerPolicyForGateway(
136151
policy *unstructured.Unstructured,
137152
gateway *GatewayContext,
@@ -173,3 +188,11 @@ func (t *Translator) translateExtServerPolicyForGateway(
173188
}
174189
return found
175190
}
191+
192+
// Appends status ancestors from newPolicy into aggregatedPolicy's list of ancestors.
193+
func MergeAncestorsForExtensionServerPolicies(aggregatedPolicy, newPolicy *unstructured.Unstructured) {
194+
aggStatus := ExtServerPolicyStatusAsPolicyStatus(aggregatedPolicy)
195+
newStatus := ExtServerPolicyStatusAsPolicyStatus(newPolicy)
196+
aggStatus.Ancestors = append(aggStatus.Ancestors, newStatus.Ancestors...)
197+
aggregatedPolicy.Object["status"] = PolicyStatusToUnstructured(aggStatus)
198+
}

internal/gatewayapi/extensionserverpolicy_test.go

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,115 @@ func TestExtractTargetRefs(t *testing.T) {
123123
})
124124
}
125125
}
126+
127+
func TestMergeAncestorsForExtensionServerPolicies(t *testing.T) {
128+
tests := []struct {
129+
aggStatus *gwapiv1.PolicyStatus
130+
newStatus *gwapiv1.PolicyStatus
131+
noStatus bool
132+
}{
133+
{
134+
aggStatus: &gwapiv1.PolicyStatus{
135+
Ancestors: []gwapiv1.PolicyAncestorStatus{
136+
{
137+
AncestorRef: gwapiv1.ParentReference{
138+
Name: "gateway-1",
139+
},
140+
},
141+
},
142+
},
143+
newStatus: &gwapiv1.PolicyStatus{
144+
Ancestors: []gwapiv1.PolicyAncestorStatus{
145+
{
146+
AncestorRef: gwapiv1.ParentReference{
147+
Name: "gateway-2",
148+
},
149+
},
150+
},
151+
},
152+
},
153+
{
154+
aggStatus: &gwapiv1.PolicyStatus{},
155+
newStatus: &gwapiv1.PolicyStatus{
156+
Ancestors: []gwapiv1.PolicyAncestorStatus{
157+
{
158+
AncestorRef: gwapiv1.ParentReference{
159+
Name: "gateway-2",
160+
},
161+
},
162+
},
163+
},
164+
},
165+
{
166+
aggStatus: &gwapiv1.PolicyStatus{
167+
Ancestors: []gwapiv1.PolicyAncestorStatus{
168+
{
169+
AncestorRef: gwapiv1.ParentReference{
170+
Name: "gateway-1",
171+
},
172+
},
173+
},
174+
},
175+
newStatus: &gwapiv1.PolicyStatus{},
176+
},
177+
{
178+
aggStatus: &gwapiv1.PolicyStatus{},
179+
newStatus: &gwapiv1.PolicyStatus{},
180+
},
181+
{
182+
aggStatus: nil,
183+
newStatus: &gwapiv1.PolicyStatus{
184+
Ancestors: []gwapiv1.PolicyAncestorStatus{
185+
{
186+
AncestorRef: gwapiv1.ParentReference{
187+
Name: "gateway-1",
188+
},
189+
},
190+
},
191+
},
192+
},
193+
{
194+
aggStatus: &gwapiv1.PolicyStatus{
195+
Ancestors: []gwapiv1.PolicyAncestorStatus{
196+
{
197+
AncestorRef: gwapiv1.ParentReference{
198+
Name: "gateway-1",
199+
},
200+
},
201+
},
202+
},
203+
newStatus: nil,
204+
},
205+
{
206+
aggStatus: nil,
207+
newStatus: nil,
208+
},
209+
}
210+
211+
for _, test := range tests {
212+
aggPolicy := unstructured.Unstructured{Object: make(map[string]interface{})}
213+
newPolicy := unstructured.Unstructured{Object: make(map[string]interface{})}
214+
desiredMergedStatus := gwapiv1.PolicyStatus{}
215+
216+
// aggStatus == nil, means simulate not setting status at all within the policy.
217+
if test.aggStatus != nil {
218+
aggPolicy.Object["status"] = PolicyStatusToUnstructured(*test.aggStatus)
219+
desiredMergedStatus.Ancestors = append(desiredMergedStatus.Ancestors, test.aggStatus.Ancestors...)
220+
}
221+
222+
// newStatus == nil, means simulate not setting status at all within the policy.
223+
if test.newStatus != nil {
224+
newPolicy.Object["status"] = PolicyStatusToUnstructured(*test.newStatus)
225+
desiredMergedStatus.Ancestors = append(desiredMergedStatus.Ancestors, test.newStatus.Ancestors...)
226+
}
227+
228+
MergeAncestorsForExtensionServerPolicies(&aggPolicy, &newPolicy)
229+
230+
// The product object will always have an existing `status`, even if with 0 ancestors.
231+
newAggPolicy := ExtServerPolicyStatusAsPolicyStatus(&aggPolicy)
232+
require.Len(t, newAggPolicy.Ancestors, len(desiredMergedStatus.Ancestors))
233+
for i := range newAggPolicy.Ancestors {
234+
require.Equal(t, desiredMergedStatus.Ancestors[i].AncestorRef.Name, newAggPolicy.Ancestors[i].AncestorRef.Name)
235+
}
236+
}
237+
}

0 commit comments

Comments
 (0)