Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: multiple rows in EA mode #5865

Merged
merged 2 commits into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
7 changes: 6 additions & 1 deletion api/helm-app/service/HelmAppService.go
Original file line number Diff line number Diff line change
Expand Up @@ -1159,7 +1159,12 @@ func (impl *HelmAppServiceImpl) appListRespProtoTransformer(deployedApps *gRPC.D
}
// end
lastDeployed := deployedapp.LastDeployed.AsTime()
appDetails, appFetchErr := impl.appRepository.FindActiveByName(deployedapp.AppName)
appDetails, appFetchErr := impl.getAppForAppIdentifier(
&helmBean.AppIdentifier{
ClusterId: int(deployedapp.EnvironmentDetail.ClusterId),
Namespace: deployedapp.EnvironmentDetail.Namespace,
ReleaseName: deployedapp.AppName,
})
projectId := int32(0)
if appFetchErr == nil {
projectId = int32(appDetails.TeamId)
Expand Down
78 changes: 73 additions & 5 deletions internal/sql/repository/app/AppRepository.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ type App struct {
sql.AuditLog
}

const (
SYSTEM_USER_ID = 1
)

func (r *App) IsAppJobOrExternalType() bool {
return len(r.DisplayName) > 0
}
Expand Down Expand Up @@ -129,16 +133,37 @@ func (repo AppRepositoryImpl) SetDescription(id int, description string, userId
}

func (repo AppRepositoryImpl) FindActiveByName(appName string) (*App, error) {
pipelineGroup := &App{}
var apps []*App
err := repo.dbConnection.
Model(pipelineGroup).
Model(&apps).
Where("app_name = ?", appName).
Where("active = ?", true).
Order("id DESC").Limit(1).
Order("id DESC").
Select()
// there is only single active app will be present in db with a same name.
return pipelineGroup, err
if len(apps) == 1 {
return apps[0], nil
} else if len(apps) > 1 {
isHelmApp := true
for _, app := range apps {
if app.AppType != helper.ChartStoreApp && app.AppType != helper.ExternalChartStoreApp {
isHelmApp = false
break
}
}
if isHelmApp {
err := repo.fixMultipleHelmAppsWithSameName(appName)
if err != nil {
repo.logger.Errorw("error in fixing duplicate helm apps with same name")
return nil, err
}
}
return apps[0], nil
} else {
err = pg.ErrNoRows
}
return nil, err
}

func (repo AppRepositoryImpl) FindAppIdByName(appName string) (int, error) {
app := &App{}
err := repo.dbConnection.
Expand Down Expand Up @@ -324,9 +349,52 @@ func (repo AppRepositoryImpl) FindAppAndProjectByAppName(appName string) (*App,
Where("app.app_name = ?", appName).
Where("app.active=?", true).
Select()

if err == pg.ErrMultiRows && (app.AppType == helper.ChartStoreApp || app.AppType == helper.ExternalChartStoreApp) {
// this case can arise in helms apps only

err := repo.fixMultipleHelmAppsWithSameName(appName)
if err != nil {
repo.logger.Errorw("error in fixing duplicate helm apps with same name")
return nil, err
}

err = repo.dbConnection.Model(app).Column("Team").
Where("app.app_name = ?", appName).
Where("app.active=?", true).
Select()
if err != nil {
repo.logger.Errorw("error in fetching apps by name", "appName", appName, "err", err)
return nil, err
}
}
return app, err
}

func (repo AppRepositoryImpl) fixMultipleHelmAppsWithSameName(appName string) error {
// updating installed apps setting app_id = max app_id
installAppUpdateQuery := `update installed_apps set
app_id=(select max(id) as id from app where app_name = ?)
where app_id in (select id from app where app_name= ? )`

_, err := repo.dbConnection.Exec(installAppUpdateQuery, appName, appName)
if err != nil {
repo.logger.Errorw("error in updating maxAppId in installedApps", "appName", appName, "err", err)
return err
}

maxAppIdQuery := repo.dbConnection.Model((*App)(nil)).ColumnExpr("max(id)").
Where("app_name = ? ", appName).
Where("active = ? ", true)

// deleting all apps other than app with max id
_, err = repo.dbConnection.Model((*App)(nil)).
Set("active = ?", false).Set("updated_by = ?", SYSTEM_USER_ID).Set("updated_on = ?", time.Now()).
Where("id not in (?) ", maxAppIdQuery).Update()

return nil
}

func (repo AppRepositoryImpl) FindAllMatchesByAppName(appName string, appType helper.AppType) ([]*App, error) {
var apps []*App
var err error
Expand Down
37 changes: 34 additions & 3 deletions pkg/app/AppCrudOperationService.go
Original file line number Diff line number Diff line change
Expand Up @@ -533,10 +533,15 @@ func (impl AppCrudOperationServiceImpl) GetHelmAppMetaInfo(appId string) (*bean.
}
// if app.DisplayName is empty then that app_name is not yet migrated to app name unique identifier
if app.Id > 0 && len(app.DisplayName) == 0 {
err = impl.updateAppNameToUniqueAppIdentifierInApp(app, appIdDecoded)
appNameUniqueIdentifier := appIdDecoded.GetUniqueAppNameIdentifier()
app.AppName = appNameUniqueIdentifier
app.DisplayName = appIdDecoded.ReleaseName
app.UpdatedBy = bean2.SystemUserId
app.UpdatedOn = time.Now()
err = impl.appRepository.Update(app)
if err != nil {
impl.logger.Errorw("GetHelmAppMetaInfo, error in migrating displayName and appName to unique identifier for external apps", "appIdentifier", appIdDecoded, "err", err)
//not returning from here as we need to show helm app metadata even if migration of app_name fails, then migration can happen on project update
impl.logger.Errorw("error in migrating displayName and appName to unique identifier", "appNameUniqueIdentifier", appNameUniqueIdentifier, "err", err)
return nil, err
}
}
if app.Id == 0 {
Expand Down Expand Up @@ -569,6 +574,12 @@ func (impl AppCrudOperationServiceImpl) GetHelmAppMetaInfo(appId string) (*bean.
}
}

err = impl.fixMultipleInstalledAppForSingleApp(app)
if err != nil {
impl.logger.Errorw("GetHelmAppMetaInfo, error in fixing multiple installed apps linked to same app", "appId", appId, "err", err)
return nil, err
}

user, err := impl.userRepository.GetByIdIncludeDeleted(app.CreatedBy)
if err != nil && err != pg.ErrNoRows {
impl.logger.Errorw("error in fetching user for app meta info", "error", err)
Expand Down Expand Up @@ -598,6 +609,26 @@ func (impl AppCrudOperationServiceImpl) GetHelmAppMetaInfo(appId string) (*bean.
return info, nil
}

// fixMultipleInstalledAppForSingleApp fixes multiple entries of installed app for single app
func (impl AppCrudOperationServiceImpl) fixMultipleInstalledAppForSingleApp(app *appRepository.App) error {
isLinked, installedApps, err := impl.installedAppDbService.IsExternalAppLinkedToChartStore(app.Id)
if err != nil {
impl.logger.Errorw("error in checking IsExternalAppLinkedToChartStore", "appId", app.Id, "err", err)
return err
}
//if isLinked is true and more than one installed app is found for that app, we will create new app for each installed app
if isLinked && len(installedApps) > 1 {
// if installed_apps are already present for that display_name then migrate the app_name to unique identifier with installedApp's ns and clusterId.
// creating new entry for app all installedApps with uniqueAppNameIdentifier and display name
err := impl.installedAppDbService.CreateNewAppEntryForAllInstalledApps(installedApps)
if err != nil {
impl.logger.Errorw("error in CreateNewAppEntryForAllInstalledApps", "appName", app.AppName, "err", err)
//not returning from here as we have to migrate the app for requested ext-app and return the response for meta info
}
}
return nil
}

func (impl AppCrudOperationServiceImpl) getLabelsByAppIdForDeployment(appId int) (map[string]string, error) {
labelsDto := make(map[string]string)
labels, err := impl.appLabelRepository.FindAllByAppId(appId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,17 @@ func (impl *InstalledAppDBServiceImpl) CreateNewAppEntryForAllInstalledApps(inst
if err != nil {
return err
}
currApp, err := impl.AppRepository.FindById(installedApps[0].AppId)
if err != nil {
impl.Logger.Errorw("error in fetching app by id", "appId", currApp.Id, "err", err)
return err
}
currApp.Active = false
err = impl.AppRepository.UpdateWithTxn(currApp, tx)
if err != nil {
impl.Logger.Errorw("error in marking current app inactive while creating new apps", "currentAppId", currApp.Id, "err", err)
return err
}
// Rollback tx on error.
defer tx.Rollback()
for _, installedApp := range installedApps {
Expand Down