@@ -21,6 +21,7 @@ import (
2121 "errors"
2222 "fmt"
2323 "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig/adapter/cdWorkflow"
24+ bean2 "github.com/devtron-labs/devtron/pkg/bean"
2425 common2 "github.com/devtron-labs/devtron/pkg/deployment/common"
2526 util2 "github.com/devtron-labs/devtron/pkg/pipeline/util"
2627 "os"
@@ -64,7 +65,7 @@ type CdHandler interface {
6465 FetchCdWorkflowDetails (appId int , environmentId int , pipelineId int , buildId int ) (types.WorkflowResponse , error )
6566 DownloadCdWorkflowArtifacts (buildId int ) (* os.File , error )
6667 FetchCdPrePostStageStatus (pipelineId int ) ([]pipelineBean.CdWorkflowWithArtifact , error )
67- CancelStage (workflowRunnerId int , userId int32 ) (int , error )
68+ CancelStage (workflowRunnerId int , forceAbort bool , userId int32 ) (int , error )
6869 FetchAppWorkflowStatusForTriggerView (appId int ) ([]* pipelineConfig.CdWorkflowStatus , error )
6970 FetchAppWorkflowStatusForTriggerViewForEnvironment (request resourceGroup2.ResourceGroupingRequest , token string ) ([]* pipelineConfig.CdWorkflowStatus , error )
7071 FetchAppDeploymentStatusForEnvironments (request resourceGroup2.ResourceGroupingRequest , token string ) ([]* pipelineConfig.AppDeploymentStatus , error )
@@ -133,16 +134,12 @@ func NewCdHandlerImpl(Logger *zap.SugaredLogger, userService user.UserService,
133134 return cdh
134135}
135136
136- func (impl * CdHandlerImpl ) CancelStage (workflowRunnerId int , userId int32 ) (int , error ) {
137+ func (impl * CdHandlerImpl ) CancelStage (workflowRunnerId int , forceAbort bool , userId int32 ) (int , error ) {
137138 workflowRunner , err := impl .cdWorkflowRepository .FindWorkflowRunnerById (workflowRunnerId )
138139 if err != nil {
139140 impl .Logger .Errorw ("err" , "err" , err )
140141 return 0 , err
141142 }
142- if ! (string (v1alpha1 .NodePending ) == workflowRunner .Status || string (v1alpha1 .NodeRunning ) == workflowRunner .Status ) {
143- impl .Logger .Info ("cannot cancel stage, stage not in progress" )
144- return 0 , errors .New ("cannot cancel stage, stage not in progress" )
145- }
146143 pipeline , err := impl .pipelineRepository .FindById (workflowRunner .CdWorkflow .PipelineId )
147144 if err != nil {
148145 impl .Logger .Errorw ("error while fetching cd pipeline" , "err" , err )
@@ -175,11 +172,35 @@ func (impl *CdHandlerImpl) CancelStage(workflowRunnerId int, userId int32) (int,
175172 }
176173 }
177174 // Terminate workflow
178- err = impl .workflowService .TerminateWorkflow (workflowRunner .ExecutorType , workflowRunner .Name , workflowRunner .Namespace , restConfig , isExtCluster , nil )
179- if err != nil {
175+ cancelWfDtoRequest := & types.CancelWfRequestDto {
176+ ExecutorType : workflowRunner .ExecutorType ,
177+ WorkflowName : workflowRunner .Name ,
178+ Namespace : workflowRunner .Namespace ,
179+ RestConfig : restConfig ,
180+ IsExt : isExtCluster ,
181+ Environment : nil ,
182+ }
183+ err = impl .workflowService .TerminateWorkflow (cancelWfDtoRequest )
184+ if err != nil && forceAbort {
185+ impl .Logger .Errorw ("error in terminating workflow, with force abort flag as true" , "workflowName" , workflowRunner .Name , "err" , err )
186+ cancelWfDtoRequest .WorkflowGenerateName = fmt .Sprintf ("%d-%s" , workflowRunnerId , workflowRunner .Name )
187+ err1 := impl .workflowService .TerminateDanglingWorkflows (cancelWfDtoRequest )
188+ if err1 != nil {
189+ impl .Logger .Errorw ("error in terminating dangling workflows" , "cancelWfDtoRequest" , cancelWfDtoRequest , "err" , err )
190+ // ignoring error here in case of force abort, confirmed from product
191+ }
192+ } else if err != nil {
180193 impl .Logger .Error ("cannot terminate wf runner" , "err" , err )
181194 return 0 , err
182195 }
196+ if forceAbort {
197+ err = impl .handleForceAbortCaseForCdStage (workflowRunner , forceAbort )
198+ if err != nil {
199+ impl .Logger .Errorw ("error in handleForceAbortCaseForCdStage" , "forceAbortFlag" , forceAbort , "workflowRunner" , workflowRunner , "err" , err )
200+ return 0 , err
201+ }
202+ return workflowRunner .Id , nil
203+ }
183204 if len (workflowRunner .ImagePathReservationIds ) > 0 {
184205 err := impl .customTagService .DeactivateImagePathReservationByImageIds (workflowRunner .ImagePathReservationIds )
185206 if err != nil {
@@ -198,6 +219,34 @@ func (impl *CdHandlerImpl) CancelStage(workflowRunnerId int, userId int32) (int,
198219 return workflowRunner .Id , nil
199220}
200221
222+ func (impl * CdHandlerImpl ) updateWorkflowRunnerForForceAbort (workflowRunner * pipelineConfig.CdWorkflowRunner ) error {
223+ workflowRunner .Status = executors .WorkflowCancel
224+ workflowRunner .PodStatus = string (bean2 .Failed )
225+ workflowRunner .Message = FORCE_ABORT_MESSAGE_AFTER_STARTING_STAGE
226+ err := impl .cdWorkflowRepository .UpdateWorkFlowRunner (workflowRunner )
227+ if err != nil {
228+ impl .Logger .Errorw ("error in updating workflow status in cd workflow runner in force abort case" , "err" , err )
229+ return err
230+ }
231+ return nil
232+ }
233+
234+ func (impl * CdHandlerImpl ) handleForceAbortCaseForCdStage (workflowRunner * pipelineConfig.CdWorkflowRunner , forceAbort bool ) error {
235+ isWorkflowInNonTerminalStage := workflowRunner .Status == string (v1alpha1 .NodePending ) || workflowRunner .Status == string (v1alpha1 .NodeRunning )
236+ if ! isWorkflowInNonTerminalStage {
237+ if forceAbort {
238+ return impl .updateWorkflowRunnerForForceAbort (workflowRunner )
239+ } else {
240+ return & util.ApiError {Code : "200" , HttpStatusCode : 400 , UserMessage : "cannot cancel stage, stage not in progress" }
241+ }
242+ }
243+ //this arises when someone deletes the workflow in resource browser and wants to force abort a cd stage(pre/post)
244+ if workflowRunner .Status == string (v1alpha1 .NodeRunning ) && forceAbort {
245+ return impl .updateWorkflowRunnerForForceAbort (workflowRunner )
246+ }
247+ return nil
248+ }
249+
201250func (impl * CdHandlerImpl ) UpdateWorkflow (workflowStatus v1alpha1.WorkflowStatus ) (int , string , error ) {
202251 wfStatusRs := impl .extractWorkfowStatus (workflowStatus )
203252 workflowName , status , podStatus , message , podName := wfStatusRs .WorkflowName , wfStatusRs .Status , wfStatusRs .PodStatus , wfStatusRs .Message , wfStatusRs .PodName
0 commit comments