diff --git a/workflow/util/util.go b/workflow/util/util.go index eaebd8af8634..dc336ff703b9 100644 --- a/workflow/util/util.go +++ b/workflow/util/util.go @@ -1079,7 +1079,14 @@ func patchShutdownStrategy(ctx context.Context, wfClient v1alpha1.WorkflowInterf return errors.InternalWrapError(err) } err = waitutil.Backoff(retry.DefaultRetry, func() (bool, error) { - _, err := wfClient.Patch(ctx, name, types.MergePatchType, patch, metav1.PatchOptions{}) + wf, err := wfClient.Get(ctx, name, metav1.GetOptions{}) + if err != nil { + return !errorsutil.IsTransientErr(err), err + } + if wf.Status.Fulfilled() { + return true, fmt.Errorf("cannot shutdown a completed workflow") + } + _, err = wfClient.Patch(ctx, name, types.MergePatchType, patch, metav1.PatchOptions{}) if apierr.IsConflict(err) { return false, nil } diff --git a/workflow/util/util_test.go b/workflow/util/util_test.go index 5ff335f80d74..a6605905beac 100644 --- a/workflow/util/util_test.go +++ b/workflow/util/util_test.go @@ -312,6 +312,13 @@ func TestStopWorkflowByNodeName(t *testing.T) { wf, err = wfIf.Get(ctx, "suspend", metav1.GetOptions{}) assert.NoError(t, err) assert.Equal(t, wfv1.NodeFailed, wf.Status.Nodes.FindByDisplayName("approve").Phase) + + origWf.Status = wfv1.WorkflowStatus{Phase: wfv1.WorkflowSucceeded} + origWf.Name = "succeeded-wf" + _, err = wfIf.Create(ctx, origWf, metav1.CreateOptions{}) + assert.NoError(t, err) + err = StopWorkflow(ctx, wfIf, hydratorfake.Noop, "succeeded-wf", "", "") + assert.EqualError(t, err, "cannot shutdown a completed workflow") } // Regression test for #6478