diff --git a/gitops-engine/pkg/sync/sync_context.go b/gitops-engine/pkg/sync/sync_context.go index 12712f5302aed..3fd5d83e2e369 100644 --- a/gitops-engine/pkg/sync/sync_context.go +++ b/gitops-engine/pkg/sync/sync_context.go @@ -422,9 +422,22 @@ func (sc *syncContext) setRunningPhase(tasks syncTasks, isPendingDeletion bool) } else { firstTask = resources[0] } + nbAdditionalTask := tasks.Len() - 1 + + if !sc.pruneConfirmed { + tasksToPrune := tasks.Filter(func(task *syncTask) bool { + return task.isPrune() && resourceutil.HasAnnotationOption(task.liveObj, common.AnnotationSyncOptions, common.SyncOptionPruneRequireConfirm) + }) + + if len(tasksToPrune) > 0 { + reason = "pruning confirmation of" + firstTask = tasksToPrune[0] + nbAdditionalTask = len(tasksToPrune) - 1 + } + } message := fmt.Sprintf("waiting for %s %s/%s/%s", reason, firstTask.group(), firstTask.kind(), firstTask.name()) - if nbAdditionalTask := len(tasks) - 1; nbAdditionalTask > 0 { + if nbAdditionalTask > 0 { message = fmt.Sprintf("%s and %d more %s", message, nbAdditionalTask, taskType) } sc.setOperationPhase(common.OperationRunning, message) @@ -1487,20 +1500,11 @@ func (sc *syncContext) runTasks(tasks syncTasks, dryRun bool) runState { // prune first { if !sc.pruneConfirmed { - var resources []string for _, task := range pruneTasks { if resourceutil.HasAnnotationOption(task.liveObj, common.AnnotationSyncOptions, common.SyncOptionPruneRequireConfirm) { - resources = append(resources, fmt.Sprintf("%s/%s/%s", task.obj().GetAPIVersion(), task.obj().GetKind(), task.name())) - } - } - if len(resources) > 0 { - sc.log.WithValues("resources", resources).Info("Prune requires confirmation") - andMessage := "" - if len(resources) > 1 { - andMessage = fmt.Sprintf(" and %d more resources", len(resources)-1) + sc.log.WithValues("task", task).Info("Prune requires confirmation") + return pending } - sc.message = fmt.Sprintf("Waiting for pruning confirmation of %s%s", resources[0], andMessage) - return pending } } diff --git a/gitops-engine/pkg/sync/sync_context_test.go b/gitops-engine/pkg/sync/sync_context_test.go index f5905d8e0ff6c..5681dde624f30 100644 --- a/gitops-engine/pkg/sync/sync_context_test.go +++ b/gitops-engine/pkg/sync/sync_context_test.go @@ -850,6 +850,33 @@ func TestDoNotPrunePruneFalse(t *testing.T) { assert.Equal(t, synccommon.OperationSucceeded, phase) } +func TestPruneConfirm(t *testing.T) { + syncCtx := newTestSyncCtx(nil, WithOperationSettings(false, true, false, false)) + pod := testingutils.NewPod() + pod.SetAnnotations(map[string]string{synccommon.AnnotationSyncOptions: "Prune=confirm"}) + pod.SetNamespace(testingutils.FakeArgoCDNamespace) + syncCtx.resources = groupResources(ReconciliationResult{ + Live: []*unstructured.Unstructured{pod}, + Target: []*unstructured.Unstructured{nil}, + }) + + syncCtx.Sync() + phase, msg, resources := syncCtx.GetState() + + assert.Equal(t, synccommon.OperationRunning, phase) + assert.Empty(t, resources) + assert.Equal(t, "waiting for pruning confirmation of /Pod/my-pod", msg) + + syncCtx.pruneConfirmed = true + syncCtx.Sync() + + phase, _, resources = syncCtx.GetState() + assert.Equal(t, synccommon.OperationSucceeded, phase) + assert.Len(t, resources, 1) + assert.Equal(t, synccommon.ResultCodePruned, resources[0].Status) + assert.Equal(t, "pruned", resources[0].Message) +} + // // make sure Validate=false means we don't validate func TestSyncOptionValidate(t *testing.T) { tests := []struct {