Skip to content

Commit e5beefe

Browse files
authored
fix: app update migration (#5903)
* wip: adding app name check * wip * wip * wip * moving migration to code * wip: adding app name in log * wip: moving sql logic to code * pg no rows handling * adding db migration call * fixing fetch app query * wip: adding pg multiple rows handling * audit log update
1 parent 3af467a commit e5beefe

File tree

9 files changed

+135
-75
lines changed

9 files changed

+135
-75
lines changed

Wire.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ import (
105105
security2 "github.com/devtron-labs/devtron/internal/sql/repository/security"
106106
"github.com/devtron-labs/devtron/internal/util"
107107
"github.com/devtron-labs/devtron/pkg/app"
108+
"github.com/devtron-labs/devtron/pkg/app/dbMigration"
108109
"github.com/devtron-labs/devtron/pkg/app/status"
109110
"github.com/devtron-labs/devtron/pkg/appClone"
110111
"github.com/devtron-labs/devtron/pkg/appClone/batch"
@@ -1005,6 +1006,9 @@ func InitializeApp() (*App, error) {
10051006

10061007
repocreds.NewServiceClientImpl,
10071008
wire.Bind(new(repocreds.ServiceClient), new(*repocreds.ServiceClientImpl)),
1009+
1010+
dbMigration.NewDbMigrationServiceImpl,
1011+
wire.Bind(new(dbMigration.DbMigration), new(*dbMigration.DbMigrationServiceImpl)),
10081012
)
10091013
return &App{}, nil
10101014
}

cmd/external-app/wire.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ import (
6464
security2 "github.com/devtron-labs/devtron/internal/sql/repository/security"
6565
"github.com/devtron-labs/devtron/internal/util"
6666
"github.com/devtron-labs/devtron/pkg/app"
67+
"github.com/devtron-labs/devtron/pkg/app/dbMigration"
6768
repository4 "github.com/devtron-labs/devtron/pkg/appStore/chartGroup/repository"
6869
"github.com/devtron-labs/devtron/pkg/appStore/installedApp/service/EAMode"
6970
"github.com/devtron-labs/devtron/pkg/appStore/installedApp/service/FullMode/deployment"
@@ -253,6 +254,9 @@ func InitializeApp() (*App, error) {
253254

254255
argoRepositoryCreds.NewRepositorySecret,
255256
wire.Bind(new(argoRepositoryCreds.RepositorySecret), new(*argoRepositoryCreds.RepositorySecretImpl)),
257+
258+
dbMigration.NewDbMigrationServiceImpl,
259+
wire.Bind(new(dbMigration.DbMigration), new(*dbMigration.DbMigrationServiceImpl)),
256260
)
257261
return &App{}, nil
258262
}

cmd/external-app/wire_gen.go

Lines changed: 4 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/sql/repository/app/AppRepository.go

Lines changed: 13 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ type AppRepository interface {
5454
UpdateWithTxn(app *App, tx *pg.Tx) error
5555
SetDescription(id int, description string, userId int32) error
5656
FindActiveByName(appName string) (pipelineGroup *App, err error)
57+
FindAllActiveByName(appName string) ([]*App, error)
5758
FindAppIdByName(appName string) (int, error)
5859

5960
FindJobByDisplayName(appName string) (pipelineGroup *App, err error)
@@ -133,35 +134,24 @@ func (repo AppRepositoryImpl) SetDescription(id int, description string, userId
133134
}
134135

135136
func (repo AppRepositoryImpl) FindActiveByName(appName string) (*App, error) {
137+
pipelineGroup := &App{}
138+
err := repo.dbConnection.
139+
Model(pipelineGroup).
140+
Where("app_name = ?", appName).
141+
Where("active = ?", true).
142+
Order("id DESC").Limit(1).
143+
Select()
144+
return pipelineGroup, err
145+
}
146+
147+
func (repo AppRepositoryImpl) FindAllActiveByName(appName string) ([]*App, error) {
136148
var apps []*App
137149
err := repo.dbConnection.
138150
Model(&apps).
139151
Where("app_name = ?", appName).
140152
Where("active = ?", true).
141-
Order("id DESC").
142153
Select()
143-
if len(apps) == 1 {
144-
return apps[0], nil
145-
} else if len(apps) > 1 {
146-
isHelmApp := true
147-
for _, app := range apps {
148-
if app.AppType != helper.ChartStoreApp && app.AppType != helper.ExternalChartStoreApp {
149-
isHelmApp = false
150-
break
151-
}
152-
}
153-
if isHelmApp {
154-
err := repo.fixMultipleHelmAppsWithSameName(appName)
155-
if err != nil {
156-
repo.logger.Errorw("error in fixing duplicate helm apps with same name")
157-
return nil, err
158-
}
159-
}
160-
return apps[0], nil
161-
} else {
162-
err = pg.ErrNoRows
163-
}
164-
return nil, err
154+
return apps, err
165155
}
166156

167157
func (repo AppRepositoryImpl) FindAppIdByName(appName string) (int, error) {
@@ -349,52 +339,9 @@ func (repo AppRepositoryImpl) FindAppAndProjectByAppName(appName string) (*App,
349339
Where("app.app_name = ?", appName).
350340
Where("app.active=?", true).
351341
Select()
352-
353-
if err == pg.ErrMultiRows && (app.AppType == helper.ChartStoreApp || app.AppType == helper.ExternalChartStoreApp) {
354-
// this case can arise in helms apps only
355-
356-
err := repo.fixMultipleHelmAppsWithSameName(appName)
357-
if err != nil {
358-
repo.logger.Errorw("error in fixing duplicate helm apps with same name")
359-
return nil, err
360-
}
361-
362-
err = repo.dbConnection.Model(app).Column("Team").
363-
Where("app.app_name = ?", appName).
364-
Where("app.active=?", true).
365-
Select()
366-
if err != nil {
367-
repo.logger.Errorw("error in fetching apps by name", "appName", appName, "err", err)
368-
return nil, err
369-
}
370-
}
371342
return app, err
372343
}
373344

374-
func (repo AppRepositoryImpl) fixMultipleHelmAppsWithSameName(appName string) error {
375-
// updating installed apps setting app_id = max app_id
376-
installAppUpdateQuery := `update installed_apps set
377-
app_id=(select max(id) as id from app where app_name = ?)
378-
where app_id in (select id from app where app_name= ? )`
379-
380-
_, err := repo.dbConnection.Exec(installAppUpdateQuery, appName, appName)
381-
if err != nil {
382-
repo.logger.Errorw("error in updating maxAppId in installedApps", "appName", appName, "err", err)
383-
return err
384-
}
385-
386-
maxAppIdQuery := repo.dbConnection.Model((*App)(nil)).ColumnExpr("max(id)").
387-
Where("app_name = ? ", appName).
388-
Where("active = ? ", true)
389-
390-
// deleting all apps other than app with max id
391-
_, err = repo.dbConnection.Model((*App)(nil)).
392-
Set("active = ?", false).Set("updated_by = ?", SYSTEM_USER_ID).Set("updated_on = ?", time.Now()).
393-
Where("id not in (?) ", maxAppIdQuery).Update()
394-
395-
return nil
396-
}
397-
398345
func (repo AppRepositoryImpl) FindAllMatchesByAppName(appName string, appType helper.AppType) ([]*App, error) {
399346
var apps []*App
400347
var err error

pkg/app/AppCrudOperationService.go

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
client "github.com/devtron-labs/devtron/api/helm-app/service"
2525
helmBean "github.com/devtron-labs/devtron/api/helm-app/service/bean"
2626
"github.com/devtron-labs/devtron/internal/util"
27+
"github.com/devtron-labs/devtron/pkg/app/dbMigration"
2728
"github.com/devtron-labs/devtron/pkg/appStore/installedApp/service/EAMode"
2829
util2 "github.com/devtron-labs/devtron/pkg/appStore/util"
2930
bean2 "github.com/devtron-labs/devtron/pkg/auth/user/bean"
@@ -88,6 +89,7 @@ type AppCrudOperationServiceImpl struct {
8889
gitMaterialRepository pipelineConfig.MaterialRepository
8990
installedAppDbService EAMode.InstalledAppDBService
9091
crudOperationServiceConfig *CrudOperationServiceConfig
92+
dbMigration dbMigration.DbMigration
9193
}
9294

9395
func NewAppCrudOperationServiceImpl(appLabelRepository pipelineConfig.AppLabelRepository,
@@ -96,7 +98,8 @@ func NewAppCrudOperationServiceImpl(appLabelRepository pipelineConfig.AppLabelRe
9698
genericNoteService genericNotes.GenericNoteService,
9799
gitMaterialRepository pipelineConfig.MaterialRepository,
98100
installedAppDbService EAMode.InstalledAppDBService,
99-
crudOperationServiceConfig *CrudOperationServiceConfig) *AppCrudOperationServiceImpl {
101+
crudOperationServiceConfig *CrudOperationServiceConfig,
102+
dbMigration dbMigration.DbMigration) *AppCrudOperationServiceImpl {
100103
impl := &AppCrudOperationServiceImpl{
101104
appLabelRepository: appLabelRepository,
102105
logger: logger,
@@ -106,6 +109,7 @@ func NewAppCrudOperationServiceImpl(appLabelRepository pipelineConfig.AppLabelRe
106109
genericNoteService: genericNoteService,
107110
gitMaterialRepository: gitMaterialRepository,
108111
installedAppDbService: installedAppDbService,
112+
dbMigration: dbMigration,
109113
}
110114
crudOperationServiceConfig, err := GetCrudOperationServiceConfig()
111115
if err != nil {
@@ -463,13 +467,29 @@ func (impl AppCrudOperationServiceImpl) getAppAndProjectForAppIdentifier(appIden
463467
var err error
464468
appNameUniqueIdentifier := appIdentifier.GetUniqueAppNameIdentifier()
465469
app, err = impl.appRepository.FindAppAndProjectByAppName(appNameUniqueIdentifier)
466-
if err != nil && err != pg.ErrNoRows {
470+
if err != nil && err != pg.ErrNoRows && err != pg.ErrMultiRows {
467471
impl.logger.Errorw("error in fetching app meta data by unique app identifier", "appNameUniqueIdentifier", appNameUniqueIdentifier, "err", err)
468472
return app, err
469473
}
474+
if err == pg.ErrMultiRows {
475+
validApp, err := impl.dbMigration.FixMultipleAppsForInstalledApp(appNameUniqueIdentifier)
476+
if err != nil {
477+
impl.logger.Errorw("error in fixing multiple installed app entries", "appName", appNameUniqueIdentifier, "err", err)
478+
return app, err
479+
}
480+
return validApp, err
481+
}
470482
if util.IsErrNoRows(err) {
471483
//find app by display name if not found by unique identifier
472484
app, err = impl.appRepository.FindAppAndProjectByAppName(appIdentifier.ReleaseName)
485+
if err == pg.ErrMultiRows {
486+
validApp, err := impl.dbMigration.FixMultipleAppsForInstalledApp(appNameUniqueIdentifier)
487+
if err != nil {
488+
impl.logger.Errorw("error in fixing multiple installed app entries", "appName", appNameUniqueIdentifier, "err", err)
489+
return app, err
490+
}
491+
return validApp, err
492+
}
473493
if err != nil {
474494
impl.logger.Errorw("error in fetching app meta data by display name", "displayName", appIdentifier.ReleaseName, "err", err)
475495
return app, err

pkg/app/dbMigration/migration.go

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
package dbMigration
2+
3+
import (
4+
appRepository "github.com/devtron-labs/devtron/internal/sql/repository/app"
5+
repository2 "github.com/devtron-labs/devtron/pkg/appStore/installedApp/repository"
6+
"go.uber.org/zap"
7+
"time"
8+
)
9+
10+
type DbMigration interface {
11+
FixMultipleAppsForInstalledApp(appNameUniqueIdentifier string) (*appRepository.App, error)
12+
}
13+
14+
type DbMigrationServiceImpl struct {
15+
logger *zap.SugaredLogger
16+
appRepository appRepository.AppRepository
17+
installedAppRepository repository2.InstalledAppRepository
18+
}
19+
20+
func NewDbMigrationServiceImpl(
21+
logger *zap.SugaredLogger, appRepository appRepository.AppRepository,
22+
installedAppRepository repository2.InstalledAppRepository,
23+
) *DbMigrationServiceImpl {
24+
impl := &DbMigrationServiceImpl{
25+
logger: logger,
26+
appRepository: appRepository,
27+
installedAppRepository: installedAppRepository,
28+
}
29+
return impl
30+
}
31+
32+
func (impl DbMigrationServiceImpl) FixMultipleAppsForInstalledApp(appNameUniqueIdentifier string) (*appRepository.App, error) {
33+
installedApp, err := impl.installedAppRepository.GetInstalledAppByAppName(appNameUniqueIdentifier)
34+
if err != nil {
35+
impl.logger.Errorw("error in fetching installed app by unique identifier", "appNameUniqueIdentifier", appNameUniqueIdentifier, "err", err)
36+
return nil, err
37+
}
38+
validAppId := installedApp.AppId
39+
allActiveApps, err := impl.appRepository.FindAllActiveByName(appNameUniqueIdentifier)
40+
if err != nil {
41+
impl.logger.Errorw("error in fetching all active apps by name", "appName", appNameUniqueIdentifier, "err", err)
42+
return nil, err
43+
}
44+
var validApp *appRepository.App
45+
for _, activeApp := range allActiveApps {
46+
if activeApp.Id != validAppId {
47+
impl.logger.Info("duplicate entries found for app, marking app inactive ", "appName", appNameUniqueIdentifier)
48+
activeApp.Active = false
49+
activeApp.UpdatedOn = time.Now()
50+
activeApp.UpdatedBy = 1
51+
err := impl.appRepository.Update(activeApp)
52+
if err != nil {
53+
impl.logger.Errorw("error in marking app inactive", "name", activeApp.AppName, "err", err)
54+
return nil, err
55+
}
56+
} else {
57+
validApp = activeApp
58+
}
59+
}
60+
return validApp, nil
61+
}

util/rbac/EnforcerUtil.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package rbac
1818

1919
import (
2020
"fmt"
21+
"github.com/devtron-labs/devtron/pkg/app/dbMigration"
2122
"golang.org/x/exp/maps"
2223
"strings"
2324

@@ -89,12 +90,14 @@ type EnforcerUtilImpl struct {
8990
ciPipelineRepository pipelineConfig.CiPipelineRepository
9091
clusterRepository repository.ClusterRepository
9192
enforcer casbin.Enforcer
93+
dbMigration dbMigration.DbMigration
9294
}
9395

9496
func NewEnforcerUtilImpl(logger *zap.SugaredLogger, teamRepository team.TeamRepository,
9597
appRepo app.AppRepository, environmentRepository repository.EnvironmentRepository,
9698
pipelineRepository pipelineConfig.PipelineRepository, ciPipelineRepository pipelineConfig.CiPipelineRepository,
97-
clusterRepository repository.ClusterRepository, enforcer casbin.Enforcer) *EnforcerUtilImpl {
99+
clusterRepository repository.ClusterRepository, enforcer casbin.Enforcer,
100+
dbMigration dbMigration.DbMigration) *EnforcerUtilImpl {
98101
return &EnforcerUtilImpl{
99102
logger: logger,
100103
teamRepository: teamRepository,
@@ -104,6 +107,7 @@ func NewEnforcerUtilImpl(logger *zap.SugaredLogger, teamRepository team.TeamRepo
104107
ciPipelineRepository: ciPipelineRepository,
105108
clusterRepository: clusterRepository,
106109
enforcer: enforcer,
110+
dbMigration: dbMigration,
107111
}
108112
}
109113

@@ -401,6 +405,13 @@ func (impl EnforcerUtilImpl) GetHelmObject(appId int, envId int) (string, string
401405

402406
func (impl EnforcerUtilImpl) GetHelmObjectByAppNameAndEnvId(appName string, envId int) (string, string) {
403407
application, err := impl.appRepo.FindAppAndProjectByAppName(appName)
408+
if err == pg.ErrMultiRows {
409+
application, err = impl.dbMigration.FixMultipleAppsForInstalledApp(appName)
410+
if err != nil {
411+
impl.logger.Errorw("error on fetching data for rbac object", "appName", appName, "err", err)
412+
return fmt.Sprintf("%s/%s/%s", "", "", ""), ""
413+
}
414+
}
404415
if err != nil {
405416
impl.logger.Errorw("error on fetching data for rbac object", "err", err)
406417
return fmt.Sprintf("%s/%s/%s", "", "", ""), ""

0 commit comments

Comments
 (0)