Backport of [API Gateway] Fix infinite loop in controller and binding non-accepted routes and gateways into release/1.15.x #16378
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Backport
This PR is auto-generated from #16377 to be assessed for backporting due to the inclusion of the label backport/1.15.
The below text is copied from the body of the original PR.
Description
We were allowing gateways to bind routes that were in a "non-accepted" state in our gateway reconciliation path and not allowing them in the route reconciliation path. Because of the fact that a TCP route being added to a gateway and forcing the gateway into a "conflicted" state causes a status update to the gateway and a status update to the route, we could trigger an infinite loop where the route status was being written as "bound" and the gateway status as "conflicted" when the gateway was reconciled, and then it would trigger a route reconciliation marking the route as "unbound" and the gateway no longer as "conflicted". The mutual status setting would cause reconciliation to be triggered indefinitely.
The fix is to add a check inside of our binding logic that makes sure a route and gateway are both marked as "accepted" prior to binding them. This does mean that on their first pass through the reconciler neither gateways, nor routes will actually bind anything because they aren't considered "accepted" until the end of the reconciliation loop. This is ok, because a second reconciliation run will be triggered when the status gets updated and routes will bind on the second pass.
Testing & Reproduction steps
Created the config entries in the following order:
Service one defaults - tcp protocol:
Service two defaults - http protocol:
TCPRoute one (should be valid):
TCPRoute two (should be invalid due to mismatched protocol on the service):
Gateway:
The final write for the gateway kicks off the death loop. It binds both TCPRoutes and sets itself in a "conflicted" state because it was ignoring whether or not the route was actually valid. Binding the routes triggers their reconciliation loops since we write to the route bound status. The route reconciliation would then unbind, taking the gateway out of conflicted, and triggering the gateway reconciliation -- this continued on mutually triggering re-reconciliation infinitely.
PR Checklist
Overview of commits