From aaed35c6d4db270a1e633e9d89fa4d34fef888b9 Mon Sep 17 00:00:00 2001 From: "gcp-cherry-pick-bot[bot]" <98988430+gcp-cherry-pick-bot[bot]@users.noreply.github.com> Date: Sat, 22 Feb 2025 15:07:42 -0500 Subject: [PATCH] fix(applicationset): ApplicationSets with rolling sync stuck in Pending (cherry-pick #20230) (#21948) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fabián Sellés Co-authored-by: Fabián Sellés Rosa <1088313+Fsero@users.noreply.github.com> Co-authored-by: Thibault Jamet Co-authored-by: Carlos Rejano --- .../controllers/applicationset_controller.go | 37 ++++----- .../applicationset_controller_test.go | 76 +++++++++---------- 2 files changed, 50 insertions(+), 63 deletions(-) diff --git a/applicationset/controllers/applicationset_controller.go b/applicationset/controllers/applicationset_controller.go index fa6e096ca01aa..271ee1012476c 100644 --- a/applicationset/controllers/applicationset_controller.go +++ b/applicationset/controllers/applicationset_controller.go @@ -1060,19 +1060,20 @@ func (r *ApplicationSetReconciler) updateApplicationSetApplicationStatus(ctx con Message: "No Application status found, defaulting status to Waiting.", Status: "Waiting", Step: strconv.Itoa(getAppStep(app.Name, appStepMap)), - TargetRevisions: app.Status.GetRevisions(), } } else { // we have an existing AppStatus currentAppStatus = applicationSet.Status.ApplicationStatus[idx] - - // upgrade any existing AppStatus that might have been set by an older argo-cd version - // note: currentAppStatus.TargetRevisions may be set to empty list earlier during migrations, - // to prevent other usage of r.Client.Status().Update to fail before reaching here. - if len(currentAppStatus.TargetRevisions) == 0 { - currentAppStatus.TargetRevisions = app.Status.GetRevisions() + if !reflect.DeepEqual(currentAppStatus.TargetRevisions, app.Status.GetRevisions()) { + currentAppStatus.Message = "Application has pending changes, setting status to Waiting." } } + if !reflect.DeepEqual(currentAppStatus.TargetRevisions, app.Status.GetRevisions()) { + currentAppStatus.TargetRevisions = app.Status.GetRevisions() + currentAppStatus.Status = "Waiting" + currentAppStatus.LastTransitionTime = &now + currentAppStatus.Step = strconv.Itoa(getAppStep(currentAppStatus.Application, appStepMap)) + } appOutdated := false if progressiveSyncsRollingSyncStrategyEnabled(applicationSet) { @@ -1085,25 +1086,15 @@ func (r *ApplicationSetReconciler) updateApplicationSetApplicationStatus(ctx con currentAppStatus.Status = "Waiting" currentAppStatus.Message = "Application has pending changes, setting status to Waiting." currentAppStatus.Step = strconv.Itoa(getAppStep(currentAppStatus.Application, appStepMap)) - currentAppStatus.TargetRevisions = app.Status.GetRevisions() } if currentAppStatus.Status == "Pending" { - if operationPhaseString == "Succeeded" { - revisions := []string{} - if len(app.Status.OperationState.SyncResult.Revisions) > 0 { - revisions = app.Status.OperationState.SyncResult.Revisions - } else if app.Status.OperationState.SyncResult.Revision != "" { - revisions = append(revisions, app.Status.OperationState.SyncResult.Revision) - } - - if reflect.DeepEqual(currentAppStatus.TargetRevisions, revisions) { - logCtx.Infof("Application %v has completed a sync successfully, updating its ApplicationSet status to Progressing", app.Name) - currentAppStatus.LastTransitionTime = &now - currentAppStatus.Status = "Progressing" - currentAppStatus.Message = "Application resource completed a sync successfully, updating status from Pending to Progressing." - currentAppStatus.Step = strconv.Itoa(getAppStep(currentAppStatus.Application, appStepMap)) - } + if !appOutdated && operationPhaseString == "Succeeded" { + logCtx.Infof("Application %v has completed a sync successfully, updating its ApplicationSet status to Progressing", app.Name) + currentAppStatus.LastTransitionTime = &now + currentAppStatus.Status = "Progressing" + currentAppStatus.Message = "Application resource completed a sync successfully, updating status from Pending to Progressing." + currentAppStatus.Step = strconv.Itoa(getAppStep(currentAppStatus.Application, appStepMap)) } else if operationPhaseString == "Running" || healthStatusString == "Progressing" { logCtx.Infof("Application %v has entered Progressing status, updating its ApplicationSet status to Progressing", app.Name) currentAppStatus.LastTransitionTime = &now diff --git a/applicationset/controllers/applicationset_controller_test.go b/applicationset/controllers/applicationset_controller_test.go index b502181405481..31a21ae7a81a1 100644 --- a/applicationset/controllers/applicationset_controller_test.go +++ b/applicationset/controllers/applicationset_controller_test.go @@ -4733,6 +4733,9 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) { Health: v1alpha1.HealthStatus{ Status: health.HealthStatusProgressing, }, + Sync: v1alpha1.SyncStatus{ + Revision: "Next", + }, }, }, }, @@ -4796,7 +4799,8 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) { Phase: common.OperationRunning, }, Sync: v1alpha1.SyncStatus{ - Status: v1alpha1.SyncStatusCodeSynced, + Status: v1alpha1.SyncStatusCodeSynced, + Revision: "Current", }, }, }, @@ -4861,7 +4865,8 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) { Phase: common.OperationSucceeded, }, Sync: v1alpha1.SyncStatus{ - Status: v1alpha1.SyncStatusCodeSynced, + Status: v1alpha1.SyncStatusCodeSynced, + Revision: "Next", }, }, }, @@ -4926,7 +4931,8 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) { Phase: common.OperationSucceeded, }, Sync: v1alpha1.SyncStatus{ - Status: v1alpha1.SyncStatusCodeSynced, + Revision: "Current", + Status: v1alpha1.SyncStatusCodeSynced, }, }, }, @@ -5166,7 +5172,7 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) { }, }, { - name: "does not progresses a pending application with a successful sync triggered by controller with invalid revision to progressing", + name: "removes the appStatus for applications that no longer exist", appSet: v1alpha1.ApplicationSet{ ObjectMeta: metav1.ObjectMeta{ Name: "name", @@ -5190,14 +5196,18 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) { Status: v1alpha1.ApplicationSetStatus{ ApplicationStatus: []v1alpha1.ApplicationSetApplicationStatus{ { - Application: "app1", - LastTransitionTime: &metav1.Time{ - Time: time.Now().Add(time.Duration(-1) * time.Minute), - }, - Message: "", - Status: "Pending", + Application: "app1", + Message: "Application has pending changes, setting status to Waiting.", + Status: "Waiting", Step: "1", - TargetRevisions: []string{"Next"}, + TargetRevisions: []string{"Current"}, + }, + { + Application: "app2", + Message: "Application has pending changes, setting status to Waiting.", + Status: "Waiting", + Step: "1", + TargetRevisions: []string{"Current"}, }, }, }, @@ -5209,25 +5219,14 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) { }, Status: v1alpha1.ApplicationStatus{ Health: v1alpha1.HealthStatus{ - Status: health.HealthStatusDegraded, + Status: health.HealthStatusHealthy, }, OperationState: &v1alpha1.OperationState{ Phase: common.OperationSucceeded, - StartedAt: metav1.Time{ - Time: time.Now(), - }, - Operation: v1alpha1.Operation{ - InitiatedBy: v1alpha1.OperationInitiator{ - Username: "applicationset-controller", - Automated: true, - }, - }, - SyncResult: &v1alpha1.SyncOperationResult{ - Revision: "Previous", - }, }, Sync: v1alpha1.SyncStatus{ - Status: v1alpha1.SyncStatusCodeSynced, + Status: v1alpha1.SyncStatusCodeSynced, + Revision: "Current", }, }, }, @@ -5238,15 +5237,15 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) { expectedAppStatus: []v1alpha1.ApplicationSetApplicationStatus{ { Application: "app1", - Message: "", - Status: "Pending", + Message: "Application resource is already Healthy, updating status from Waiting to Healthy.", + Status: "Healthy", Step: "1", - TargetRevisions: []string{"Next"}, + TargetRevisions: []string{"Current"}, }, }, }, { - name: "removes the appStatus for applications that no longer exist", + name: "progresses a pending synced application with an old revision to progressing with the Current one", appSet: v1alpha1.ApplicationSet{ ObjectMeta: metav1.ObjectMeta{ Name: "name", @@ -5271,17 +5270,10 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) { ApplicationStatus: []v1alpha1.ApplicationSetApplicationStatus{ { Application: "app1", - Message: "Application has pending changes, setting status to Waiting.", - Status: "Waiting", - Step: "1", - TargetRevisions: []string{"Current"}, - }, - { - Application: "app2", - Message: "Application has pending changes, setting status to Waiting.", - Status: "Waiting", + Message: "", + Status: "Pending", Step: "1", - TargetRevisions: []string{"Current"}, + TargetRevisions: []string{"Old"}, }, }, }, @@ -5297,9 +5289,13 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) { }, OperationState: &v1alpha1.OperationState{ Phase: common.OperationSucceeded, + SyncResult: &v1alpha1.SyncOperationResult{ + Revision: "Current", + }, }, Sync: v1alpha1.SyncStatus{ - Status: v1alpha1.SyncStatusCodeSynced, + Status: v1alpha1.SyncStatusCodeSynced, + Revisions: []string{"Current"}, }, }, },