@@ -29,6 +29,7 @@ import (
2929 "github.com/devtron-labs/devtron/api/restHandler/common"
3030 "github.com/devtron-labs/devtron/client/argocdServer/application"
3131 "github.com/devtron-labs/devtron/client/cron"
32+ "github.com/devtron-labs/devtron/internal/constants"
3233 "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig"
3334 "github.com/devtron-labs/devtron/internal/util"
3435 "github.com/devtron-labs/devtron/pkg/app"
@@ -44,6 +45,7 @@ import (
4445 "github.com/devtron-labs/devtron/util/argo"
4546 "github.com/devtron-labs/devtron/util/k8s"
4647 "github.com/devtron-labs/devtron/util/rbac"
48+ "github.com/go-pg/pg"
4749 "github.com/gorilla/mux"
4850 "go.opentelemetry.io/otel"
4951 "go.uber.org/zap"
@@ -355,6 +357,20 @@ func (handler AppListingRestHandlerImpl) FetchAppDetails(w http.ResponseWriter,
355357 common .WriteJsonResp (w , err , nil , http .StatusBadRequest )
356358 return
357359 }
360+ pipelines , err := handler .pipelineRepository .FindActiveByAppIdAndEnvironmentId (appId , envId )
361+ if err == pg .ErrNoRows {
362+ common .WriteJsonResp (w , err , "pipeline Not found in database" , http .StatusNotFound )
363+ return
364+ }
365+ if len (pipelines ) == 0 {
366+ common .WriteJsonResp (w , fmt .Errorf ("app deleted" ), nil , http .StatusNotFound )
367+ return
368+ }
369+ if len (pipelines ) != 1 {
370+ common .WriteJsonResp (w , err , "multiple pipelines found for an envId" , http .StatusBadRequest )
371+ return
372+ }
373+ cdPipeline := pipelines [0 ]
358374 appDetail , err := handler .appListingService .FetchAppDetails (r .Context (), appId , envId )
359375 if err != nil {
360376 handler .logger .Errorw ("service err, FetchAppDetails" , "err" , err , "appId" , appId , "envId" , envId )
@@ -367,7 +383,31 @@ func (handler AppListingRestHandlerImpl) FetchAppDetails(w http.ResponseWriter,
367383 common .WriteJsonResp (w , fmt .Errorf ("unauthorized user" ), nil , http .StatusForbidden )
368384 return
369385 }
370- appDetail = handler .fetchResourceTree (w , r , appId , envId , appDetail )
386+ acdToken , err := handler .argoUserService .GetLatestDevtronArgoCdUserToken ()
387+ if err != nil {
388+ common .WriteJsonResp (w , fmt .Errorf ("error in getting acd token" ), nil , http .StatusInternalServerError )
389+ return
390+ }
391+ appDetail , err = handler .fetchResourceTree (w , r , appId , envId , appDetail , acdToken , cdPipeline )
392+ if appDetail .DeploymentAppType == util .PIPELINE_DEPLOYMENT_TYPE_ACD {
393+ apiError , ok := err .(* util.ApiError )
394+ if ok && apiError != nil {
395+ if apiError .Code == constants .AppDetailResourceTreeNotFound && appDetail .DeploymentAppDeleteRequest == true {
396+ acdAppFound , _ := handler .pipeline .MarkGitOpsDevtronAppsDeletedWhereArgoAppIsDeleted (appId , envId , acdToken , cdPipeline )
397+ if acdAppFound {
398+ common .WriteJsonResp (w , fmt .Errorf ("unable to fetch resource tree" ), nil , http .StatusInternalServerError )
399+ return
400+ } else {
401+ common .WriteJsonResp (w , fmt .Errorf ("app deleted" ), nil , http .StatusNotFound )
402+ return
403+ }
404+ }
405+ }
406+ }
407+ if err != nil {
408+ common .WriteJsonResp (w , fmt .Errorf ("unable to fetch resource tree" ), nil , http .StatusInternalServerError )
409+ return
410+ }
371411 common .WriteJsonResp (w , err , appDetail , http .StatusOK )
372412}
373413
@@ -624,7 +664,8 @@ func (handler AppListingRestHandlerImpl) RedirectToLinkouts(w http.ResponseWrite
624664func (handler AppListingRestHandlerImpl ) fetchResourceTreeFromInstallAppService (w http.ResponseWriter , r * http.Request , appDetail bean.AppDetailContainer ) bean.AppDetailContainer {
625665 rctx := r .Context ()
626666 cn , _ := w .(http.CloseNotifier )
627- return handler .installedAppService .FetchResourceTree (rctx , cn , & appDetail )
667+ _ , _ = handler .installedAppService .FetchResourceTree (rctx , cn , & appDetail )
668+ return appDetail
628669}
629670func (handler AppListingRestHandlerImpl ) GetHostUrlsByBatch (w http.ResponseWriter , r * http.Request ) {
630671 vars := r .URL .Query ()
@@ -659,6 +700,16 @@ func (handler AppListingRestHandlerImpl) GetHostUrlsByBatch(w http.ResponseWrite
659700 common .WriteJsonResp (w , fmt .Errorf ("error in parsing envId : %s must be integer" , envIdParam ), nil , http .StatusBadRequest )
660701 return
661702 }
703+ pipelines , err := handler .pipelineRepository .FindActiveByAppIdAndEnvironmentId (appId , envId )
704+ if err == pg .ErrNoRows {
705+ common .WriteJsonResp (w , err , "pipeline Not found in database" , http .StatusNotFound )
706+ return
707+ }
708+ if len (pipelines ) != 1 {
709+ common .WriteJsonResp (w , err , "multiple pipelines found for an envId" , http .StatusBadRequest )
710+ return
711+ }
712+ cdPipeline := pipelines [0 ]
662713 appDetail , err , appId = handler .getAppDetails (r .Context (), appIdParam , installedAppIdParam , envId )
663714 if err != nil {
664715 handler .logger .Errorw ("error occurred while getting app details" , "appId" , appIdParam , "installedAppId" , installedAppIdParam , "envId" , envId )
@@ -686,7 +737,12 @@ func (handler AppListingRestHandlerImpl) GetHostUrlsByBatch(w http.ResponseWrite
686737 if installedAppIdParam != "" {
687738 appDetail = handler .fetchResourceTreeFromInstallAppService (w , r , appDetail )
688739 } else {
689- appDetail = handler .fetchResourceTree (w , r , appId , envId , appDetail )
740+ acdToken , err := handler .argoUserService .GetLatestDevtronArgoCdUserToken ()
741+ if err != nil {
742+ common .WriteJsonResp (w , fmt .Errorf ("error in getting acd token" ), nil , http .StatusInternalServerError )
743+ return
744+ }
745+ appDetail , err = handler .fetchResourceTree (w , r , appId , envId , appDetail , acdToken , cdPipeline )
690746 }
691747
692748 resourceTree := appDetail .ResourceTree
@@ -737,20 +793,9 @@ func (handler AppListingRestHandlerImpl) getAppDetails(ctx context.Context, appI
737793}
738794
739795// TODO: move this to service
740- func (handler AppListingRestHandlerImpl ) fetchResourceTree (w http.ResponseWriter , r * http.Request , appId int , envId int , appDetail bean.AppDetailContainer ) bean.AppDetailContainer {
796+ func (handler AppListingRestHandlerImpl ) fetchResourceTree (w http.ResponseWriter , r * http.Request , appId int , envId int , appDetail bean.AppDetailContainer , acdToken string , cdPipeline * pipelineConfig. Pipeline ) ( bean.AppDetailContainer , error ) {
741797 if len (appDetail .AppName ) > 0 && len (appDetail .EnvironmentName ) > 0 && util .IsAcdApp (appDetail .DeploymentAppType ) {
742798 //RBAC enforcer Ends
743- cdPipelines , err := handler .pipelineRepository .FindActiveByAppIdAndEnvironmentId (appId , envId )
744- if err != nil {
745- handler .logger .Errorw ("error in getting cdPipeline by appId and envId" , "err" , err , "appid" , appId , "envId" , envId )
746- common .WriteJsonResp (w , err , "" , http .StatusInternalServerError )
747- return appDetail
748- }
749- if len (cdPipelines ) != 1 {
750- common .WriteJsonResp (w , err , "" , http .StatusInternalServerError )
751- return appDetail
752- }
753- cdPipeline := cdPipelines [0 ]
754799 query := & application2.ResourcesQuery {
755800 ApplicationName : & cdPipeline .DeploymentAppName ,
756801 }
@@ -765,23 +810,18 @@ func (handler AppListingRestHandlerImpl) fetchResourceTree(w http.ResponseWriter
765810 }(ctx .Done (), cn .CloseNotify ())
766811 }
767812 defer cancel ()
768- acdToken , err := handler .argoUserService .GetLatestDevtronArgoCdUserToken ()
769- if err != nil {
770- handler .logger .Errorw ("error in getting acd token" , "err" , err )
771- common .WriteJsonResp (w , err , "" , http .StatusInternalServerError )
772- return appDetail
773- }
774813 ctx = context .WithValue (ctx , "token" , acdToken )
775814 start := time .Now ()
776815 resp , err := handler .application .ResourceTree (ctx , query )
777816 elapsed := time .Since (start )
778817 if err != nil {
779- handler .logger .Errorw ("service err, FetchAppDetails, resource tree" ,
780- "err" , err ,
781- "app" , appId ,
782- "env" , envId )
783-
784- return appDetail
818+ handler .logger .Errorw ("service err, FetchAppDetails, resource tree" , "err" , err , "app" , appId , "env" , envId )
819+ err = & util.ApiError {
820+ Code : constants .AppDetailResourceTreeNotFound ,
821+ InternalMessage : "app detail fetched, failed to get resource tree from acd" ,
822+ UserMessage : "Error fetching detail, if you have recently created this deployment pipeline please try after sometime." ,
823+ }
824+ return appDetail , err
785825 }
786826 if resp .Status == string (health .HealthStatusHealthy ) {
787827 status , err := handler .appListingService .ISLastReleaseStopType (appId , envId )
@@ -849,7 +889,7 @@ func (handler AppListingRestHandlerImpl) fetchResourceTree(w http.ResponseWriter
849889 appDetail .ResourceTree = map [string ]interface {}{}
850890 handler .logger .Warnw ("appName and envName not found - avoiding resource tree call" , "app" , appDetail .AppName , "env" , appDetail .EnvironmentName )
851891 }
852- return appDetail
892+ return appDetail , nil
853893}
854894
855895func (handler AppListingRestHandlerImpl ) ManualSyncAcdPipelineDeploymentStatus (w http.ResponseWriter , r * http.Request ) {
0 commit comments