Skip to content
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
08618f3
wip
iamayushm Feb 3, 2023
596188f
wip
iamayushm Feb 3, 2023
694f703
added deployment app delete request flag for both cd pipeline and ins…
vikramdevtron Feb 6, 2023
796b342
wip: adding handling if kubewatch delete status is lost
iamayushm Feb 6, 2023
ea8da67
Merge branch 'delete_acd_app_status' into acd-app-partially-delete
iamayushm Feb 6, 2023
158c7aa
temp commit
iamayushm Feb 6, 2023
ba899f6
shifting code from temp branch to main branch
iamayushm Feb 9, 2023
bce5ea5
wip: temp change
iamayushm Feb 13, 2023
eef877f
wip: temp change
iamayushm Feb 13, 2023
7847e83
Merge remote-tracking branch 'origin/acd-app-partially-delete' into a…
iamayushm Feb 13, 2023
40d1cfb
migration scripts
iamayushm Feb 13, 2023
7b8cd96
migration scripts
iamayushm Feb 13, 2023
d27ac8c
Merge branch 'main' into acd-app-partially-delete
iamayushm Feb 13, 2023
896365a
migration scripts
iamayushm Feb 13, 2023
ad6e820
adding app delete check
iamayushm Feb 14, 2023
24fff1a
adding deployment app created flag
iamayushm Feb 14, 2023
ef941b2
removing app delete check
iamayushm Feb 14, 2023
094269a
refactoring and corner case handle
iamayushm Feb 14, 2023
b4a7f5e
reverting schemas
iamayushm Feb 14, 2023
f709052
wip: fixes after refactoring
iamayushm Feb 14, 2023
28061db
updating migration scripts
iamayushm Feb 17, 2023
ffe9b2b
updating vendor file
iamayushm Feb 20, 2023
3edac6f
adding back argocd file
iamayushm Feb 20, 2023
ff314fe
updating vendor
iamayushm Feb 20, 2023
ad44a3c
adding back asset folder
iamayushm Feb 20, 2023
b5a5520
Merge branch 'main' into acd-app-partially-delete
iamayushm Feb 24, 2023
e0ed134
fixing merge errors
iamayushm Feb 24, 2023
658f89f
correcting sql script sequence no
iamayushm Feb 24, 2023
ca4fac6
skipping app status deletion if not found in database
iamayushm Feb 25, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Wire.go
Original file line number Diff line number Diff line change
Expand Up @@ -407,8 +407,8 @@ func InitializeApp() (*App, error) {
pubsub.NewWorkflowStatusUpdateHandlerImpl,
wire.Bind(new(pubsub.WorkflowStatusUpdateHandler), new(*pubsub.WorkflowStatusUpdateHandlerImpl)),

pubsub.NewApplicationStatusUpdateHandlerImpl,
wire.Bind(new(pubsub.ApplicationStatusUpdateHandler), new(*pubsub.ApplicationStatusUpdateHandlerImpl)),
pubsub.NewApplicationStatusHandlerImpl,
wire.Bind(new(pubsub.ApplicationStatusHandler), new(*pubsub.ApplicationStatusHandlerImpl)),

pubsub.NewCiEventHandlerImpl,
wire.Bind(new(pubsub.CiEventHandler), new(*pubsub.CiEventHandlerImpl)),
Expand Down
34 changes: 30 additions & 4 deletions api/appStore/InstalledAppRestHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import (
openapi "github.com/devtron-labs/devtron/api/helm-app/openapiClient"
"github.com/devtron-labs/devtron/api/restHandler/common"
"github.com/devtron-labs/devtron/client/argocdServer/application"
"github.com/devtron-labs/devtron/internal/constants"
util2 "github.com/devtron-labs/devtron/internal/util"
appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean"
"github.com/devtron-labs/devtron/pkg/appStore/deployment/service"
"github.com/devtron-labs/devtron/pkg/cluster"
Expand All @@ -34,6 +36,7 @@ import (
"github.com/devtron-labs/devtron/util/argo"
"github.com/devtron-labs/devtron/util/rbac"
"github.com/devtron-labs/devtron/util/response"
"github.com/go-pg/pg"
"github.com/gorilla/mux"
"go.uber.org/zap"
"gopkg.in/go-playground/validator.v9"
Expand Down Expand Up @@ -401,6 +404,12 @@ func (handler *InstalledAppRestHandlerImpl) FetchAppDetailsForInstalledApp(w htt
}
handler.Logger.Infow("request payload, FetchAppDetailsForInstalledApp, app store", "installedAppId", installedAppId, "envId", envId)

err = handler.installedAppService.CheckAppExistsByInstalledAppId(installedAppId)
if err == pg.ErrNoRows {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

avoid this check in rest handler, handle it in service layer.

common.WriteJsonResp(w, err, "App not found in database", http.StatusBadRequest)
return
}

appDetail, err := handler.installedAppService.FindAppDetailsForAppstoreApplication(installedAppId, envId)
if err != nil {
handler.Logger.Errorw("service err, FetchAppDetailsForInstalledApp, app store", "err", err, "installedAppId", installedAppId, "envId", envId)
Expand All @@ -425,16 +434,33 @@ func (handler *InstalledAppRestHandlerImpl) FetchAppDetailsForInstalledApp(w htt
}
//rback block ends here
if len(appDetail.AppName) > 0 && len(appDetail.EnvironmentName) > 0 {
handler.fetchResourceTree(w, r, &appDetail)
err = handler.fetchResourceTree(w, r, &appDetail)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we move this logic at service layer

if appDetail.DeploymentAppType == util2.PIPELINE_DEPLOYMENT_TYPE_ACD {
apiError, ok := err.(*util2.ApiError)
if ok && apiError != nil {
if apiError.Code == constants.AppDetailResourceTreeNotFound && appDetail.DeploymentAppDeleteRequest == true {
err = handler.installedAppService.MarkGitOpsInstalledAppsDeletedIfArgoAppIsDeleted(installedAppId, envId)
appDeleteErr, appDeleteErrOk := err.(*util2.ApiError)
if appDeleteErrOk && appDeleteErr != nil {
common.WriteJsonResp(w, fmt.Errorf(appDeleteErr.InternalMessage), nil, appDeleteErr.HttpStatusCode)
return
}
}
}
} else if err != nil {
common.WriteJsonResp(w, fmt.Errorf("error in fetching resource tree"), nil, http.StatusInternalServerError)
}

} else {
appDetail.ResourceTree = map[string]interface{}{}
handler.Logger.Warnw("appName and envName not found - avoiding resource tree call", "app", appDetail.AppName, "env", appDetail.EnvironmentName)
}
common.WriteJsonResp(w, err, appDetail, http.StatusOK)
common.WriteJsonResp(w, nil, appDetail, http.StatusOK)
}

func (handler *InstalledAppRestHandlerImpl) fetchResourceTree(w http.ResponseWriter, r *http.Request, appDetail *bean2.AppDetailContainer) {
func (handler *InstalledAppRestHandlerImpl) fetchResourceTree(w http.ResponseWriter, r *http.Request, appDetail *bean2.AppDetailContainer) error {
ctx := r.Context()
cn, _ := w.(http.CloseNotifier)
handler.installedAppService.FetchResourceTree(ctx, cn, appDetail)
_, err := handler.installedAppService.FetchResourceTree(ctx, cn, appDetail)
return err
}
20 changes: 16 additions & 4 deletions api/appStore/deployment/AppStoreDeploymentRestHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,11 +258,20 @@ func (handler AppStoreDeploymentRestHandlerImpl) DeleteInstalledApp(w http.Respo
if len(force) > 0 {
forceDelete, err = strconv.ParseBool(force)
if err != nil {
handler.Logger.Errorw("request err, DeleteInstalledApp", "err", err, "installAppId", installAppId)
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
}
}
partialDelete := false
partialDeleteStr := v.Get("partialDelete")
if len(partialDeleteStr) > 0 {
partialDelete, err = strconv.ParseBool(partialDeleteStr)
if err != nil {
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
}
}

handler.Logger.Infow("request payload, DeleteInstalledApp", "installAppId", installAppId)
token := r.Header.Get("token")
installedApp, err := handler.appStoreDeploymentService.GetInstalledApp(installAppId)
Expand Down Expand Up @@ -294,7 +303,7 @@ func (handler AppStoreDeploymentRestHandlerImpl) DeleteInstalledApp(w http.Respo
}
//rbac block ends here

request := appStoreBean.InstallAppVersionDTO{}
request := &appStoreBean.InstallAppVersionDTO{}
request.InstalledAppId = installAppId
request.AppName = installedApp.AppName
request.AppId = installedApp.AppId
Expand All @@ -304,6 +313,7 @@ func (handler AppStoreDeploymentRestHandlerImpl) DeleteInstalledApp(w http.Respo
request.AppOfferingMode = installedApp.AppOfferingMode
request.ClusterId = installedApp.ClusterId
request.Namespace = installedApp.Namespace
request.AcdPartialDelete = partialDelete
ctx, cancel := context.WithCancel(r.Context())
if cn, ok := w.(http.CloseNotifier); ok {
go func(done <-chan struct{}, closed <-chan bool) {
Expand All @@ -325,13 +335,15 @@ func (handler AppStoreDeploymentRestHandlerImpl) DeleteInstalledApp(w http.Respo
}
ctx = context.WithValue(r.Context(), "token", acdToken)
}
res, err := handler.appStoreDeploymentService.DeleteInstalledApp(ctx, &request)

request, err = handler.appStoreDeploymentService.DeleteInstalledApp(ctx, request)
if err != nil {
handler.Logger.Errorw("service err, DeleteInstalledApp", "err", err, "installAppId", installAppId)
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
return
}
common.WriteJsonResp(w, err, res, http.StatusOK)

common.WriteJsonResp(w, err, request, http.StatusOK)
}

func (handler *AppStoreDeploymentRestHandlerImpl) LinkHelmApplicationToChartStore(w http.ResponseWriter, r *http.Request) {
Expand Down
18 changes: 10 additions & 8 deletions api/bean/AppView.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ type DeploymentDetailContainer struct {
ClusterName string `json:"clusterName,omitempty"`
DockerRegistryId string `json:"dockerRegistryId,omitempty"`
IpsAccessProvided bool `json:"ipsAccessProvided"`
DeploymentAppDeleteRequest bool `json:"deploymentAppDeleteRequest"`
}

type AppDetailContainer struct {
Expand All @@ -124,14 +125,15 @@ type AppDetailContainer struct {
}

type Environment struct {
AppStatus string `json:"appStatus"` //this is not the status of environment , this make sense with a specific app only
EnvironmentId int `json:"environmentId"`
EnvironmentName string `json:"environmentName"`
AppMetrics *bool `json:"appMetrics"`
InfraMetrics *bool `json:"infraMetrics"`
Prod bool `json:"prod"`
ChartRefId int `json:"chartRefId"`
LastDeployed string `json:"lastDeployed"`
AppStatus string `json:"appStatus"` //this is not the status of environment , this make sense with a specific app only
EnvironmentId int `json:"environmentId"`
EnvironmentName string `json:"environmentName"`
AppMetrics *bool `json:"appMetrics"`
InfraMetrics *bool `json:"infraMetrics"`
Prod bool `json:"prod"`
ChartRefId int `json:"chartRefId"`
LastDeployed string `json:"lastDeployed"`
DeploymentAppDeleteRequest bool `json:"deploymentAppDeleteRequest"`
}

type InstanceDetail struct {
Expand Down
85 changes: 61 additions & 24 deletions api/restHandler/AppListingRestHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ import (
"github.com/devtron-labs/devtron/util/argo"
"github.com/devtron-labs/devtron/util/k8s"
"github.com/devtron-labs/devtron/util/rbac"
"github.com/go-pg/pg"
"github.com/gorilla/mux"
"go.opentelemetry.io/otel"
"go.uber.org/zap"
Expand Down Expand Up @@ -355,6 +356,20 @@ func (handler AppListingRestHandlerImpl) FetchAppDetails(w http.ResponseWriter,
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
}
pipelines, err := handler.pipelineRepository.FindActiveByAppIdAndEnvironmentId(appId, envId)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we have to move this logic in service

if err == pg.ErrNoRows {
common.WriteJsonResp(w, err, "pipeline Not found in database", http.StatusNotFound)
return
}
if len(pipelines) == 0 {
common.WriteJsonResp(w, fmt.Errorf("app deleted"), nil, http.StatusNotFound)
return
}
if len(pipelines) != 1 {
common.WriteJsonResp(w, err, "multiple pipelines found for an envId", http.StatusBadRequest)
return
}
cdPipeline := pipelines[0]
appDetail, err := handler.appListingService.FetchAppDetails(r.Context(), appId, envId)
if err != nil {
handler.logger.Errorw("service err, FetchAppDetails", "err", err, "appId", appId, "envId", envId)
Expand All @@ -367,7 +382,31 @@ func (handler AppListingRestHandlerImpl) FetchAppDetails(w http.ResponseWriter,
common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), nil, http.StatusForbidden)
return
}
appDetail = handler.fetchResourceTree(w, r, appId, envId, appDetail)
acdToken, err := handler.argoUserService.GetLatestDevtronArgoCdUserToken()
if err != nil {
common.WriteJsonResp(w, fmt.Errorf("error in getting acd token"), nil, http.StatusInternalServerError)
return
}
appDetail, err = handler.fetchResourceTree(w, r, appId, envId, appDetail, acdToken, cdPipeline)
if appDetail.DeploymentAppType == util.PIPELINE_DEPLOYMENT_TYPE_ACD {
apiError, ok := err.(*util.ApiError)
if ok && apiError != nil {
if apiError.Code == constants.AppDetailResourceTreeNotFound && appDetail.DeploymentAppDeleteRequest == true {
acdAppFound, _ := handler.pipeline.MarkGitOpsDevtronAppsDeletedWhereArgoAppIsDeleted(appId, envId, acdToken, cdPipeline)
if acdAppFound {
common.WriteJsonResp(w, fmt.Errorf("unable to fetch resource tree"), nil, http.StatusInternalServerError)
return
} else {
common.WriteJsonResp(w, fmt.Errorf("app deleted"), nil, http.StatusNotFound)
return
}
}
}
}
if err != nil {
common.WriteJsonResp(w, fmt.Errorf("unable to fetch resource tree"), nil, http.StatusInternalServerError)
return
}
common.WriteJsonResp(w, err, appDetail, http.StatusOK)
}

Expand Down Expand Up @@ -624,7 +663,8 @@ func (handler AppListingRestHandlerImpl) RedirectToLinkouts(w http.ResponseWrite
func (handler AppListingRestHandlerImpl) fetchResourceTreeFromInstallAppService(w http.ResponseWriter, r *http.Request, appDetail bean.AppDetailContainer) bean.AppDetailContainer {
rctx := r.Context()
cn, _ := w.(http.CloseNotifier)
return handler.installedAppService.FetchResourceTree(rctx, cn, &appDetail)
_, _ = handler.installedAppService.FetchResourceTree(rctx, cn, &appDetail)
return appDetail
}
func (handler AppListingRestHandlerImpl) GetHostUrlsByBatch(w http.ResponseWriter, r *http.Request) {
vars := r.URL.Query()
Expand Down Expand Up @@ -659,6 +699,16 @@ func (handler AppListingRestHandlerImpl) GetHostUrlsByBatch(w http.ResponseWrite
common.WriteJsonResp(w, fmt.Errorf("error in parsing envId : %s must be integer", envIdParam), nil, http.StatusBadRequest)
return
}
pipelines, err := handler.pipelineRepository.FindActiveByAppIdAndEnvironmentId(appId, envId)
if err == pg.ErrNoRows {
common.WriteJsonResp(w, err, "pipeline Not found in database", http.StatusNotFound)
return
}
if len(pipelines) != 1 {
common.WriteJsonResp(w, err, "multiple pipelines found for an envId", http.StatusBadRequest)
return
}
cdPipeline := pipelines[0]
appDetail, err, appId = handler.getAppDetails(r.Context(), appIdParam, installedAppIdParam, envId)
if err != nil {
handler.logger.Errorw("error occurred while getting app details", "appId", appIdParam, "installedAppId", installedAppIdParam, "envId", envId)
Expand Down Expand Up @@ -686,7 +736,12 @@ func (handler AppListingRestHandlerImpl) GetHostUrlsByBatch(w http.ResponseWrite
if installedAppIdParam != "" {
appDetail = handler.fetchResourceTreeFromInstallAppService(w, r, appDetail)
} else {
appDetail = handler.fetchResourceTree(w, r, appId, envId, appDetail)
acdToken, err := handler.argoUserService.GetLatestDevtronArgoCdUserToken()
if err != nil {
common.WriteJsonResp(w, fmt.Errorf("error in getting acd token"), nil, http.StatusInternalServerError)
return
}
appDetail, err = handler.fetchResourceTree(w, r, appId, envId, appDetail, acdToken, cdPipeline)
}

resourceTree := appDetail.ResourceTree
Expand Down Expand Up @@ -737,20 +792,9 @@ func (handler AppListingRestHandlerImpl) getAppDetails(ctx context.Context, appI
}

// TODO: move this to service
func (handler AppListingRestHandlerImpl) fetchResourceTree(w http.ResponseWriter, r *http.Request, appId int, envId int, appDetail bean.AppDetailContainer) bean.AppDetailContainer {
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) {
if len(appDetail.AppName) > 0 && len(appDetail.EnvironmentName) > 0 && util.IsAcdApp(appDetail.DeploymentAppType) {
//RBAC enforcer Ends
cdPipelines, err := handler.pipelineRepository.FindActiveByAppIdAndEnvironmentId(appId, envId)
if err != nil {
handler.logger.Errorw("error in getting cdPipeline by appId and envId", "err", err, "appid", appId, "envId", envId)
common.WriteJsonResp(w, err, "", http.StatusInternalServerError)
return appDetail
}
if len(cdPipelines) != 1 {
common.WriteJsonResp(w, err, "", http.StatusInternalServerError)
return appDetail
}
cdPipeline := cdPipelines[0]
query := &application2.ResourcesQuery{
ApplicationName: &cdPipeline.DeploymentAppName,
}
Expand All @@ -765,12 +809,6 @@ func (handler AppListingRestHandlerImpl) fetchResourceTree(w http.ResponseWriter
}(ctx.Done(), cn.CloseNotify())
}
defer cancel()
acdToken, err := handler.argoUserService.GetLatestDevtronArgoCdUserToken()
if err != nil {
handler.logger.Errorw("error in getting acd token", "err", err)
common.WriteJsonResp(w, err, "", http.StatusInternalServerError)
return appDetail
}
ctx = context.WithValue(ctx, "token", acdToken)
start := time.Now()
resp, err := handler.application.ResourceTree(ctx, query)
Expand All @@ -782,8 +820,7 @@ func (handler AppListingRestHandlerImpl) fetchResourceTree(w http.ResponseWriter
InternalMessage: "app detail fetched, failed to get resource tree from acd",
UserMessage: "Error fetching detail, if you have recently created this deployment pipeline please try after sometime.",
}
common.WriteJsonResp(w, err, "", http.StatusInternalServerError)
return appDetail
return appDetail, err
}
if resp.Status == string(health.HealthStatusHealthy) {
status, err := handler.appListingService.ISLastReleaseStopType(appId, envId)
Expand Down Expand Up @@ -842,7 +879,7 @@ func (handler AppListingRestHandlerImpl) fetchResourceTree(w http.ResponseWriter
appDetail.ResourceTree = map[string]interface{}{}
handler.logger.Warnw("appName and envName not found - avoiding resource tree call", "app", appDetail.AppName, "env", appDetail.EnvironmentName)
}
return appDetail
return appDetail, nil
}

func (handler AppListingRestHandlerImpl) ManualSyncAcdPipelineDeploymentStatus(w http.ResponseWriter, r *http.Request) {
Expand Down
2 changes: 2 additions & 0 deletions api/restHandler/app/DeploymentPipelineRestHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,8 @@ func (handler PipelineConfigRestHandlerImpl) PatchCdPipeline(w http.ResponseWrit
err = handler.validator.Struct(cdPipeline.Pipeline)
} else if cdPipeline.Action == bean.CD_DELETE {
err = handler.validator.Var(cdPipeline.Pipeline.Id, "gt=0")
} else if cdPipeline.Action == bean.CD_DELETE_PARTIAL {
err = handler.validator.Var(cdPipeline.Pipeline.Id, "gt=0")
}
}
if err != nil {
Expand Down
Loading