feat: auto-refresh on new revisions during sync retries (Alpha) (#11494)#15603
feat: auto-refresh on new revisions during sync retries (Alpha) (#11494)#15603aslafy-z wants to merge 5 commits intoargoproj:masterfrom
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #15603 +/- ##
==========================================
- Coverage 44.93% 44.92% -0.02%
==========================================
Files 354 354
Lines 47742 47720 -22
==========================================
- Hits 21454 21437 -17
Misses 23485 23485
+ Partials 2803 2798 -5 ☔ View full report in Codecov by Sentry. |
3872209 to
0a95fd5
Compare
539d026 to
a363b85
Compare
0713719 to
3850169
Compare
controller/appcontroller.go
Outdated
| ctrl.requestAppRefresh(app.QualifiedName(), CompareWithLatest.Pointer(), &retryAfter) | ||
| return | ||
| } else { | ||
| if state.Phase == synccommon.OperationRunning && app.Spec.SyncPolicy.Retry.Refresh && app.Status.Sync.Revision != state.Operation.Sync.Revision { |
There was a problem hiding this comment.
This triggers when processing resources, not hooks. Are hooks processed somewhere else?
| logCtx.Infof("A new revision is available, refreshing and terminating app, was phase: %s, message: %s", state.Phase, state.Message) | ||
| ctrl.requestAppRefresh(app.QualifiedName(), CompareWithLatest.Pointer(), nil) | ||
| state.Phase = synccommon.OperationTerminating | ||
| state.Message = "Operation forced to terminate (new revision available)" |
There was a problem hiding this comment.
I could not find this message on the UI, is there a way to make it appear?
There was a problem hiding this comment.
I think we have to move setOperationState above the requestAppRefresh, since otherwise there can be a race condition by the refresh processor kicking in and message not being ready yet.
0d2a152 to
ca363b9
Compare
|
@alexec any inputs? |
|
@todaywasawesome I applied the required change. I also added the |
|
I will fix the tests asap |
864ce27 to
7129857
Compare
Signed-off-by: Zadkiel AHARONIAN <hello@zadkiel.fr>
Signed-off-by: Zadkiel AHARONIAN <hello@zadkiel.fr>
Signed-off-by: Zadkiel AHARONIAN <hello@zadkiel.fr>
e1ce49c to
a65cbd3
Compare
Signed-off-by: Zadkiel AHARONIAN <hello@zadkiel.fr>
|
@aslafy-z any news? |
|
hey @aslafy-z , are you going to work on it? |
|
Hi @pasha-codefresh, I couldn't reproduce the issue correctly in the end-to-end tests. I'm quite short on time these days. Please feel free to take over if needed, and any suggestions are welcome. |
I think your test case shouldnt wait for |
| PatchFile("guestbook-ui-deployment.yaml", `[{"op": "add", "path": "/spec/selector/matchLabels/foo", "value": "bar"}, {"op": "add", "path": "/spec/template/metadata/labels/foo", "value": "bar"}]`). | ||
| Refresh(RefreshTypeNormal). | ||
| Then(). | ||
| Expect(OperationPhaseIs(OperationFailed)). | ||
| When(). | ||
| // Trigger refresh again to make sure controller notices previously failed sync attempt before expectation timeout expires | ||
| Refresh(RefreshTypeNormal). | ||
| Then(). | ||
| Expect(SyncStatusIs(SyncStatusCodeOutOfSync)). | ||
| Expect(Condition(ApplicationConditionSyncError, "Failed sync attempt")). |
There was a problem hiding this comment.
| PatchFile("guestbook-ui-deployment.yaml", `[{"op": "add", "path": "/spec/selector/matchLabels/foo", "value": "bar"}, {"op": "add", "path": "/spec/template/metadata/labels/foo", "value": "bar"}]`). | |
| Refresh(RefreshTypeNormal). | |
| Then(). | |
| Expect(OperationPhaseIs(OperationFailed)). | |
| When(). | |
| // Trigger refresh again to make sure controller notices previously failed sync attempt before expectation timeout expires | |
| Refresh(RefreshTypeNormal). | |
| Then(). | |
| Expect(SyncStatusIs(SyncStatusCodeOutOfSync)). | |
| Expect(Condition(ApplicationConditionSyncError, "Failed sync attempt")). | |
| PatchFile("guestbook-ui-deployment.yaml", `[{"op": "add", "path": "/spec/selector/matchLabels/foo", "value": "bar"}, {"op": "add", "path": "/spec/template/metadata/labels/foo", "value": "bar"}]`). | |
| Refresh(RefreshTypeNormal). | |
| Then(). | |
| Expect(OperationPhaseIs(OperationRunning)). | |
| When(). |
I suppose that you copied this part from previous test and your case doesnt require it.
- Applying healthy manifest
- Waiting for Healthy state
- Patching with corrupted manifest (this case application will stuck in
Syncingstate. (operationState.phase == 'Running') - Expecting phase running
- Patching with healthy manifest
- Expecting that introduced feature works as expected (previous sync stopped and new started & application goes to healthy)
Let me know if it makes sense
There was a problem hiding this comment.
@aslafy-z I will see if I can give this a try
| state.Message = "Operation forced to terminate (new revision available)" | ||
| ctrl.setOperationState(app, state) | ||
| return | ||
| } |
There was a problem hiding this comment.
There's a setOperationState below as well, let's combine the two.
|
I don't think tying this to the retry logic is a good thng. The problem is orthogonal to retries. For more context, see: #11494 (comment) |
|
Can be closed in favor of #23038 |
|
Thank you for taking over @olivergondza! |
This feature allows users to configure their apps to refresh on new revisions, when the current sync is retrying.
This is controlled by a new boolean Application CRD field
syncPolicy.retry.refreshor via the--sync-retry-refreshflag.Closes #11494
Related to #6055
Discussed at https://www.youtube.com/watch?v=baIX9Bk6f5w&t=1173s
Initially based of the work Sayrus did at Sayrus@817bc34
Checklist: