From 5272d9eed8a03476ba928f7292fa5b9c33763225 Mon Sep 17 00:00:00 2001 From: kartik-579 <84493919+kartik-579@users.noreply.github.com> Date: Thu, 1 Feb 2024 12:50:44 +0530 Subject: [PATCH 1/2] chore: Refactoring deployment template GitOps (#4615) * removed registerInArgo multiple impls * extracted app metrics code * migrated envLevel app metrics code to new service * chore: Removed unused jira and migration integration (#4498) * removed unsued jira integration * removed test-suite-code * db migration conf removal * chore: removed unused injection * chore: removed dead code * added: migration script --------- Co-authored-by: Ash-exp * chore: App store dead code cleanup and restructuring (#4497) * moved chart-group in seperate code * removed unused dependency * removed dead code * extracted resource tree * moved notes * resource movement * removed unused code * removed unused dependency * commit methods * extracted status update * chore: clean up unused dead code * updated: EA mode docker file * updated: migration number --------- Co-authored-by: Ash-exp * chart ref refactoring * removed infra metrics db calls * moved app metrics repositories from /internal to /pkg * moved: const and types to bean * removed: unused const * review comments * migrated some methods from chartService to chartRefService * added dt validation service interface * minor refactoring * moved validation method - 1 * wip * removed redundant appMetrics req obj * moved app metrics bindings to wireset * removed multiple dead code * remove redundant dependency * moved ChartGroup router and rest handler to respective folder * gitOps refactoring * moved gitClient code to a common wrapper service * review changes * wip * fix for unsupported charts * minor cleanup * renamed remote package to git * renamed gitOpsRemoteOpService If and impl * migrated usages of gitService to gitOperationService * shifted git service and all gitOps clients to pkg * gitops repository usages refactor * refactored gitOpsRepository usages * gitlab client creation refactoring * renamed util/ChartService * reverted renaming changes * reverted renaming changes * reverted renaming changes * wip * wip * removed typo * changes * changes --------- Co-authored-by: Nishant <58689354+nishant-d@users.noreply.github.com> Co-authored-by: Ash-exp --- Wire.go | 24 +- api/chartRepo/ChartRepositoryRestHandler.go | 7 +- api/deployment/DeploymentConfigRestHandler.go | 56 +- api/restHandler/BatchOperationRestHandler.go | 12 - api/restHandler/ChartRefRestHandler.go | 15 +- api/restHandler/CommonRestHanlder.go | 25 +- api/restHandler/CoreAppRestHandler.go | 48 +- api/restHandler/GitOpsConfigRestHandler.go | 5 +- .../app/DeploymentPipelineRestHandler.go | 139 +-- .../app/PipelineConfigRestHandler.go | 163 ++- api/restHandler/common/apiError.go | 32 - api/router/PipelineConfigRouter.go | 3 - .../argocdServer/ArgoClientWrapperService.go | 37 +- .../telemetry/TelemetryEventClientExtended.go | 19 +- cmd/external-app/wire.go | 23 +- cmd/external-app/wire_gen.go | 34 +- .../sql/repository/AppListingRepository.go | 27 +- .../DeploymentTemplateRepository.go | 6 +- .../sql/repository/GitOpsConfigRepository.go | 13 - .../mocks/AppLevelMetricsRepository.go | 2 +- .../mocks/EnvLevelAppMetricsRepository.go | 2 +- internal/util/ChartDeploymentService.go | 38 - internal/util/ChartService.go | 823 ------------- internal/util/ChartTemplateService.go | 453 +++++++ ...e_test.go => ChartTemplateService_test.go} | 0 pkg/app/AppListingService.go | 103 +- pkg/app/AppService.go | 161 +-- pkg/app/ManifestPushService.go | 68 +- .../AppServiceDeployment_test.go | 10 +- pkg/app/integrationTest/AppService_test.go | 3 +- pkg/appClone/AppCloneService.go | 16 +- pkg/appStore/bean/bean.go | 4 + .../common/AppStoreDeploymentCommonService.go | 146 +-- .../AppStoreDeploymentFullModeService.go | 54 +- .../service/AppStoreDeploymentService.go | 46 +- .../deployment/service/InstalledAppService.go | 47 +- .../service/InstalledAppService_test.go | 14 +- .../tool/AppStoreDeploymentArgoCdService.go | 33 +- .../tool/AppStoreDeploymentHelmService.go | 24 +- pkg/bulkAction/BulkUpdateService.go | 96 +- pkg/chart/ChartCompatibility_test.go | 18 +- pkg/chart/ChartService.go | 1037 ++--------------- pkg/chart/ChartUtils.go | 21 +- pkg/chart/bean.go | 12 - pkg/chart/mocks/ChartService.go | 13 - .../repository/ChartRefRepository.go | 7 +- pkg/cluster/ClusterServiceExtended.go | 33 +- pkg/commonService/CommonService.go | 3 - pkg/deployment/gitOps/common/bean/bean.go | 6 + .../gitOps/config/GitOpsConfigReadService.go | 145 +++ pkg/deployment/gitOps/config/bean/bean.go | 14 + .../deployment/gitOps/git}/GitCliUtil.go | 2 +- .../gitOps/git/GitOperationService.go | 401 +++++++ .../deployment/gitOps/git}/GitService.go | 168 +-- .../deployment/gitOps/git}/GitServiceAzure.go | 51 +- .../gitOps/git}/GitServiceBitbucket.go | 67 +- .../gitOps/git}/GitServiceGithub.go | 52 +- .../gitOps/git}/GitServiceGitlab.go | 76 +- .../deployment/gitOps/git}/GitService_test.go | 10 +- pkg/deployment/gitOps/git/adapter/adapter.go | 21 + pkg/deployment/gitOps/git/bean/bean.go | 21 + pkg/deployment/gitOps/wire_gitOps.go | 19 + .../deployedAppMetrics/DeployedAppMetrics.go | 215 ++++ .../manifest/deployedAppMetrics/bean/bean.go | 9 + .../repository/AppLevelMetricsRepository.go | 10 +- .../EnvLevelAppMetricsRepository.go | 15 +- .../DeploymentTemplateService.go | 16 + .../DeploymentTemplateValidationService.go | 127 ++ .../deploymentTemplate/adapter/adapter.go | 1 + .../manifest/deploymentTemplate/bean/bean.go | 11 + .../chartRef}/ChartCompatibility.go | 14 +- .../chartRef/ChartRefService.go | 627 ++++++++++ .../chartRef/adapter/adapter.go | 45 + .../deploymentTemplate/chartRef/bean/bean.go | 96 ++ .../manifest/wire_deployment_manifest.go | 25 + pkg/deployment/wire_deployment.go | 14 + .../DeployementTemplateService.go | 13 +- .../DeployementTemplateService_test.go | 24 +- pkg/gitops/GitOpsConfigService.go | 128 +- .../AppDeploymentTypeChangeManager.go | 31 +- pkg/pipeline/DeploymentConfigService.go | 76 +- .../DeploymentPipelineConfigService.go | 130 +-- pkg/pipeline/PropertiesConfig.go | 254 +--- pkg/pipeline/WorkflowDagExecutor.go | 78 +- .../DeploymentTemplateHistoryService.go | 78 +- util/argo/ArgoUserService.go | 24 +- wire_gen.go | 327 +++--- 87 files changed, 3432 insertions(+), 3984 deletions(-) delete mode 100644 internal/util/ChartDeploymentService.go delete mode 100644 internal/util/ChartService.go create mode 100644 internal/util/ChartTemplateService.go rename internal/util/{ChartService_test.go => ChartTemplateService_test.go} (100%) create mode 100644 pkg/deployment/gitOps/common/bean/bean.go create mode 100644 pkg/deployment/gitOps/config/GitOpsConfigReadService.go create mode 100644 pkg/deployment/gitOps/config/bean/bean.go rename {internal/util => pkg/deployment/gitOps/git}/GitCliUtil.go (99%) create mode 100644 pkg/deployment/gitOps/git/GitOperationService.go rename {internal/util => pkg/deployment/gitOps/git}/GitService.go (65%) rename {internal/util => pkg/deployment/gitOps/git}/GitServiceAzure.go (87%) rename {internal/util => pkg/deployment/gitOps/git}/GitServiceBitbucket.go (81%) rename {internal/util => pkg/deployment/gitOps/git}/GitServiceGithub.go (85%) rename {internal/util => pkg/deployment/gitOps/git}/GitServiceGitlab.go (89%) rename {internal/util => pkg/deployment/gitOps/git}/GitService_test.go (81%) create mode 100644 pkg/deployment/gitOps/git/adapter/adapter.go create mode 100644 pkg/deployment/gitOps/git/bean/bean.go create mode 100644 pkg/deployment/gitOps/wire_gitOps.go create mode 100644 pkg/deployment/manifest/deployedAppMetrics/DeployedAppMetrics.go create mode 100644 pkg/deployment/manifest/deployedAppMetrics/bean/bean.go rename {internal/sql => pkg/deployment/manifest/deployedAppMetrics}/repository/AppLevelMetricsRepository.go (86%) rename {internal/sql => pkg/deployment/manifest/deployedAppMetrics}/repository/EnvLevelAppMetricsRepository.go (87%) create mode 100644 pkg/deployment/manifest/deploymentTemplate/DeploymentTemplateService.go create mode 100644 pkg/deployment/manifest/deploymentTemplate/DeploymentTemplateValidationService.go create mode 100644 pkg/deployment/manifest/deploymentTemplate/adapter/adapter.go create mode 100644 pkg/deployment/manifest/deploymentTemplate/bean/bean.go rename pkg/{chart => deployment/manifest/deploymentTemplate/chartRef}/ChartCompatibility.go (67%) create mode 100644 pkg/deployment/manifest/deploymentTemplate/chartRef/ChartRefService.go create mode 100644 pkg/deployment/manifest/deploymentTemplate/chartRef/adapter/adapter.go create mode 100644 pkg/deployment/manifest/deploymentTemplate/chartRef/bean/bean.go create mode 100644 pkg/deployment/manifest/wire_deployment_manifest.go create mode 100644 pkg/deployment/wire_deployment.go diff --git a/Wire.go b/Wire.go index 2d58868a603..eaef59be908 100644 --- a/Wire.go +++ b/Wire.go @@ -87,7 +87,6 @@ import ( "github.com/devtron-labs/devtron/pkg/appClone" "github.com/devtron-labs/devtron/pkg/appClone/batch" "github.com/devtron-labs/devtron/pkg/appStatus" - appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" "github.com/devtron-labs/devtron/pkg/appStore/chartGroup" repository4 "github.com/devtron-labs/devtron/pkg/appStore/chartGroup/repository" appStoreDeploymentFullMode "github.com/devtron-labs/devtron/pkg/appStore/deployment/fullMode" @@ -100,6 +99,8 @@ import ( chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository" "github.com/devtron-labs/devtron/pkg/commonService" delete2 "github.com/devtron-labs/devtron/pkg/delete" + deployment2 "github.com/devtron-labs/devtron/pkg/deployment" + git2 "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git" "github.com/devtron-labs/devtron/pkg/deploymentGroup" "github.com/devtron-labs/devtron/pkg/devtronResource" repository9 "github.com/devtron-labs/devtron/pkg/devtronResource/repository" @@ -161,6 +162,8 @@ func InitializeApp() (*App, error) { apiToken.ApiTokenWireSet, webhookHelm.WebhookHelmWireSet, terminal.TerminalWireSet, + deployment2.DeploymentWireSet, + // -------wireset end ---------- //------- gitSensor.GetConfig, @@ -174,10 +177,6 @@ func InitializeApp() (*App, error) { //sql.NewDbConnection, //app.GetACDAuthConfig, util3.GetACDAuthConfig, - wire.Value(chartRepoRepository.RefChartDir("scripts/devtron-reference-helm-charts")), - wire.Value(appStoreBean.RefChartProxyDir("scripts/devtron-reference-helm-charts")), - wire.Value(chart.DefaultChart("reference-app-rolling")), - wire.Value(util.ChartWorkingDir("/tmp/charts/")), connection.SettingsManager, //auth.GetConfig, @@ -265,8 +264,6 @@ func InitializeApp() (*App, error) { util.NewChartTemplateServiceImpl, wire.Bind(new(util.ChartTemplateService), new(*util.ChartTemplateServiceImpl)), - util.NewChartDeploymentServiceImpl, - wire.Bind(new(util.ChartDeploymentService), new(*util.ChartDeploymentServiceImpl)), //scoped variables start variables.NewScopedVariableServiceImpl, @@ -335,8 +332,6 @@ func InitializeApp() (*App, error) { eClient.NewEventRESTClientImpl, wire.Bind(new(eClient.EventClient), new(*eClient.EventRESTClientImpl)), - util3.NewTokenCache, - eClient.NewEventSimpleFactoryImpl, wire.Bind(new(eClient.EventFactory), new(*eClient.EventSimpleFactoryImpl)), @@ -353,7 +348,7 @@ func InitializeApp() (*App, error) { wire.Bind(new(pipelineConfig.CiPipelineRepository), new(*pipelineConfig.CiPipelineRepositoryImpl)), pipelineConfig.NewCiPipelineMaterialRepositoryImpl, wire.Bind(new(pipelineConfig.CiPipelineMaterialRepository), new(*pipelineConfig.CiPipelineMaterialRepositoryImpl)), - util.NewGitFactory, + git2.NewGitFactory, application.NewApplicationClientImpl, wire.Bind(new(application.ServiceClient), new(*application.ServiceClientImpl)), @@ -527,11 +522,6 @@ func InitializeApp() (*App, error) { restHandler.NewExternalCiRestHandlerImpl, wire.Bind(new(restHandler.ExternalCiRestHandler), new(*restHandler.ExternalCiRestHandlerImpl)), - repository.NewAppLevelMetricsRepositoryImpl, - wire.Bind(new(repository.AppLevelMetricsRepository), new(*repository.AppLevelMetricsRepositoryImpl)), - - repository.NewEnvLevelAppMetricsRepositoryImpl, - wire.Bind(new(repository.EnvLevelAppMetricsRepository), new(*repository.EnvLevelAppMetricsRepositoryImpl)), grafana.GetGrafanaClientConfig, grafana.NewGrafanaClientImpl, @@ -649,8 +639,6 @@ func InitializeApp() (*App, error) { wire.Bind(new(restHandler.GitOpsConfigRestHandler), new(*restHandler.GitOpsConfigRestHandlerImpl)), gitops.NewGitOpsConfigServiceImpl, wire.Bind(new(gitops.GitOpsConfigService), new(*gitops.GitOpsConfigServiceImpl)), - repository.NewGitOpsConfigRepositoryImpl, - wire.Bind(new(repository.GitOpsConfigRepository), new(*repository.GitOpsConfigRepositoryImpl)), router.NewAttributesRouterImpl, wire.Bind(new(router.AttributesRouter), new(*router.AttributesRouterImpl)), @@ -671,7 +659,7 @@ func InitializeApp() (*App, error) { scopedVariable.NewScopedVariableRestHandlerImpl, wire.Bind(new(scopedVariable.ScopedVariableRestHandler), new(*scopedVariable.ScopedVariableRestHandlerImpl)), - util.NewGitCliUtil, + git2.NewGitCliUtil, router.NewTelemetryRouterImpl, wire.Bind(new(router.TelemetryRouter), new(*router.TelemetryRouterImpl)), diff --git a/api/chartRepo/ChartRepositoryRestHandler.go b/api/chartRepo/ChartRepositoryRestHandler.go index 495fa5b2bbf..b7c0486d5f0 100644 --- a/api/chartRepo/ChartRepositoryRestHandler.go +++ b/api/chartRepo/ChartRepositoryRestHandler.go @@ -30,7 +30,6 @@ import ( "github.com/devtron-labs/devtron/pkg/auth/authorisation/casbin" "github.com/devtron-labs/devtron/pkg/auth/user" "github.com/devtron-labs/devtron/pkg/chartRepo" - chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository" delete2 "github.com/devtron-labs/devtron/pkg/delete" "github.com/gorilla/mux" "go.uber.org/zap" @@ -64,14 +63,12 @@ type ChartRepositoryRestHandlerImpl struct { enforcer casbin.Enforcer validator *validator.Validate deleteService delete2.DeleteService - chartRefRepository chartRepoRepository.ChartRefRepository - refChartDir chartRepoRepository.RefChartDir attributesService attributes.AttributesService } func NewChartRepositoryRestHandlerImpl(Logger *zap.SugaredLogger, userAuthService user.UserService, chartRepositoryService chartRepo.ChartRepositoryService, enforcer casbin.Enforcer, validator *validator.Validate, deleteService delete2.DeleteService, - chartRefRepository chartRepoRepository.ChartRefRepository, refChartDir chartRepoRepository.RefChartDir, attributesService attributes.AttributesService) *ChartRepositoryRestHandlerImpl { + attributesService attributes.AttributesService) *ChartRepositoryRestHandlerImpl { return &ChartRepositoryRestHandlerImpl{ Logger: Logger, chartRepositoryService: chartRepositoryService, @@ -79,8 +76,6 @@ func NewChartRepositoryRestHandlerImpl(Logger *zap.SugaredLogger, userAuthServic enforcer: enforcer, validator: validator, deleteService: deleteService, - chartRefRepository: chartRefRepository, - refChartDir: refChartDir, attributesService: attributesService, } } diff --git a/api/deployment/DeploymentConfigRestHandler.go b/api/deployment/DeploymentConfigRestHandler.go index 9e17ce9f97d..ac877b17cc0 100644 --- a/api/deployment/DeploymentConfigRestHandler.go +++ b/api/deployment/DeploymentConfigRestHandler.go @@ -3,6 +3,8 @@ package deployment import ( "encoding/json" "fmt" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/chartRef" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/chartRef/bean" "io/ioutil" "net/http" "os" @@ -15,12 +17,10 @@ import ( "github.com/devtron-labs/devtron/pkg/auth/authorisation/casbin" "github.com/devtron-labs/devtron/pkg/auth/user" "github.com/devtron-labs/devtron/pkg/chart" - chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository" "github.com/devtron-labs/devtron/pkg/sql" "github.com/gorilla/mux" "github.com/juju/errors" "go.uber.org/zap" - "gopkg.in/go-playground/validator.v9" ) type DeploymentConfigRestHandler interface { @@ -31,13 +31,11 @@ type DeploymentConfigRestHandler interface { } type DeploymentConfigRestHandlerImpl struct { - Logger *zap.SugaredLogger - userAuthService user.UserService - enforcer casbin.Enforcer - validator *validator.Validate - refChartDir chartRepoRepository.RefChartDir - chartService chart.ChartService - chartRefRepository chartRepoRepository.ChartRefRepository + Logger *zap.SugaredLogger + userAuthService user.UserService + enforcer casbin.Enforcer + chartService chart.ChartService + chartRefService chartRef.ChartRefService } type DeploymentChartInfo struct { @@ -49,16 +47,14 @@ type DeploymentChartInfo struct { Message string `json:"message"` } -func NewDeploymentConfigRestHandlerImpl(Logger *zap.SugaredLogger, userAuthService user.UserService, enforcer casbin.Enforcer, validator *validator.Validate, - refChartDir chartRepoRepository.RefChartDir, chartService chart.ChartService, chartRefRepository chartRepoRepository.ChartRefRepository) *DeploymentConfigRestHandlerImpl { +func NewDeploymentConfigRestHandlerImpl(Logger *zap.SugaredLogger, userAuthService user.UserService, enforcer casbin.Enforcer, + chartService chart.ChartService, chartRefService chartRef.ChartRefService) *DeploymentConfigRestHandlerImpl { return &DeploymentConfigRestHandlerImpl{ - Logger: Logger, - userAuthService: userAuthService, - enforcer: enforcer, - validator: validator, - refChartDir: refChartDir, - chartService: chartService, - chartRefRepository: chartRefRepository, + Logger: Logger, + userAuthService: userAuthService, + enforcer: enforcer, + chartService: chartService, + chartRefService: chartRefService, } } @@ -88,7 +84,7 @@ func (handler *DeploymentConfigRestHandlerImpl) CreateChartFromFile(w http.Respo return } - err = handler.chartService.ValidateUploadedFileFormat(fileHeader.Filename) + err = handler.chartRefService.ValidateCustomChartUploadedFileFormat(fileHeader.Filename) if err != nil { handler.Logger.Errorw("request err, Unsupported format", "err", err, "payload", file) common.WriteJsonResp(w, errors.New("Unsupported format file is uploaded, please upload file with .tgz extension"), nil, http.StatusBadRequest) @@ -102,7 +98,7 @@ func (handler *DeploymentConfigRestHandlerImpl) CreateChartFromFile(w http.Respo return } - chartInfo, err := handler.chartService.ExtractChartIfMissing(fileBytes, string(handler.refChartDir), "") + chartInfo, err := handler.chartRefService.ExtractChartIfMissing(fileBytes, bean.RefChartDirPath, "") if err != nil { if chartInfo != nil && chartInfo.TemporaryFolder != "" { @@ -111,7 +107,7 @@ func (handler *DeploymentConfigRestHandlerImpl) CreateChartFromFile(w http.Respo handler.Logger.Errorw("error in deleting temp dir ", "err", err1) } } - if err.Error() == chart.CHART_ALREADY_EXISTS_INTERNAL_ERROR || err.Error() == chart.CHART_NAME_RESERVED_INTERNAL_ERROR { + if err.Error() == bean.ChartAlreadyExistsInternalError || err.Error() == bean.ChartNameReservedInternalError { common.WriteJsonResp(w, err, nil, http.StatusBadRequest) return } @@ -119,7 +115,7 @@ func (handler *DeploymentConfigRestHandlerImpl) CreateChartFromFile(w http.Respo return } - chartRefs := &chartRepoRepository.ChartRef{ + chartRefs := &bean.CustomChartRefDto{ Name: chartInfo.ChartName, Version: chartInfo.ChartVersion, Location: chartInfo.ChartLocation, @@ -178,7 +174,7 @@ func (handler *DeploymentConfigRestHandlerImpl) SaveChart(w http.ResponseWriter, return } - location := filepath.Join(string(handler.refChartDir), request.FileId) + location := filepath.Join(bean.RefChartDirPath, request.FileId) if request.Action == "Save" { file, err := ioutil.ReadFile(filepath.Join(location, "output.json")) if err != nil { @@ -186,17 +182,17 @@ func (handler *DeploymentConfigRestHandlerImpl) SaveChart(w http.ResponseWriter, common.WriteJsonResp(w, err, nil, http.StatusBadRequest) return } - chartRefs := &chartRepoRepository.ChartRef{} - err = json.Unmarshal(file, &chartRefs) + customChartRefDto := &bean.CustomChartRefDto{} + err = json.Unmarshal(file, &customChartRefDto) if err != nil { handler.Logger.Errorw("unmarshall err", "err", err) common.WriteJsonResp(w, err, nil, http.StatusBadRequest) return } - chartRefs.ChartDescription = request.Description - err = handler.chartRefRepository.Save(chartRefs) + customChartRefDto.ChartDescription = request.Description + err = handler.chartRefService.SaveCustomChart(customChartRefDto) if err != nil { - handler.Logger.Errorw("error in saving Chart", "err", err) + handler.Logger.Errorw("error in saving Chart", "err", err, "request", customChartRefDto) common.WriteJsonResp(w, err, "Chart couldn't be saved", http.StatusInternalServerError) return } @@ -234,7 +230,7 @@ func (handler *DeploymentConfigRestHandlerImpl) DownloadChart(w http.ResponseWri common.WriteJsonResp(w, fmt.Errorf("error in parsing chartRefId : %s must be integer", chartRefId), nil, http.StatusBadRequest) return } - manifestByteArr, err := handler.chartService.GetCustomChartInBytes(chartRefId) + manifestByteArr, err := handler.chartRefService.GetChartInBytes(chartRefId) if err != nil { handler.Logger.Errorw("error in converting chart to bytes", "err", err) common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) @@ -258,7 +254,7 @@ func (handler *DeploymentConfigRestHandlerImpl) GetUploadedCharts(w http.Respons return } - charts, err := handler.chartService.FetchCustomChartsInfo() + charts, err := handler.chartRefService.FetchCustomChartsInfo() if err != nil { common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) return diff --git a/api/restHandler/BatchOperationRestHandler.go b/api/restHandler/BatchOperationRestHandler.go index d89bafbd55d..1c1178568ab 100644 --- a/api/restHandler/BatchOperationRestHandler.go +++ b/api/restHandler/BatchOperationRestHandler.go @@ -145,15 +145,3 @@ func validatePipeline(pipeline *v1.Pipeline, props v1.InheritedProps) error { } return nil } - -func executePipeline(pipeline *v1.Pipeline, props v1.InheritedProps) error { - if pipeline.Build == nil && pipeline.Deployment == nil { - return nil - } else if pipeline.Build != nil { - pipeline.Build.UpdateMissingProps(props) - return validation.ValidateBuild(pipeline.Build) - } else if pipeline.Deployment != nil { - //return batch.ExecuteDeployment(pipeline.Deployment, props) - } - return nil -} diff --git a/api/restHandler/ChartRefRestHandler.go b/api/restHandler/ChartRefRestHandler.go index 9e85cdc09cb..decebfbfe74 100644 --- a/api/restHandler/ChartRefRestHandler.go +++ b/api/restHandler/ChartRefRestHandler.go @@ -19,7 +19,8 @@ package restHandler import ( "github.com/devtron-labs/devtron/api/restHandler/common" - "github.com/devtron-labs/devtron/pkg/chart" + chartService "github.com/devtron-labs/devtron/pkg/chart" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/chartRef" "github.com/gorilla/mux" "go.uber.org/zap" "net/http" @@ -33,17 +34,19 @@ type ChartRefRestHandler interface { } type ChartRefRestHandlerImpl struct { - chartService chart.ChartService - logger *zap.SugaredLogger + logger *zap.SugaredLogger + chartRefService chartRef.ChartRefService + chartService chartService.ChartService } -func NewChartRefRestHandlerImpl(chartService chart.ChartService, logger *zap.SugaredLogger) *ChartRefRestHandlerImpl { - handler := &ChartRefRestHandlerImpl{chartService: chartService, logger: logger} +func NewChartRefRestHandlerImpl(logger *zap.SugaredLogger, chartRefService chartRef.ChartRefService, + chartService chartService.ChartService) *ChartRefRestHandlerImpl { + handler := &ChartRefRestHandlerImpl{logger: logger, chartRefService: chartRefService, chartService: chartService} return handler } func (handler ChartRefRestHandlerImpl) ChartRefAutocomplete(w http.ResponseWriter, r *http.Request) { - result, err := handler.chartService.ChartRefAutocomplete() + result, err := handler.chartRefService.ChartRefAutocomplete() if err != nil { handler.logger.Errorw("service err, ChartRefAutocomplete", "err", err) common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) diff --git a/api/restHandler/CommonRestHanlder.go b/api/restHandler/CommonRestHanlder.go index 41007976c8a..3f95c46cf38 100644 --- a/api/restHandler/CommonRestHanlder.go +++ b/api/restHandler/CommonRestHanlder.go @@ -21,12 +21,9 @@ import ( "net/http" "github.com/devtron-labs/devtron/api/restHandler/common" - "github.com/devtron-labs/devtron/pkg/auth/authorisation/casbin" "github.com/devtron-labs/devtron/pkg/auth/user" "github.com/devtron-labs/devtron/pkg/commonService" - "github.com/devtron-labs/devtron/pkg/gitops" "go.uber.org/zap" - "gopkg.in/go-playground/validator.v9" ) type CommonRestHanlder interface { @@ -34,25 +31,19 @@ type CommonRestHanlder interface { } type CommonRestHanlderImpl struct { - logger *zap.SugaredLogger - gitOpsConfigService gitops.GitOpsConfigService - userAuthService user.UserService - validator *validator.Validate - enforcer casbin.Enforcer - commonService commonService.CommonService + logger *zap.SugaredLogger + userAuthService user.UserService + commonService commonService.CommonService } func NewCommonRestHanlderImpl( logger *zap.SugaredLogger, - gitOpsConfigService gitops.GitOpsConfigService, userAuthService user.UserService, - validator *validator.Validate, enforcer casbin.Enforcer, commonService commonService.CommonService) *CommonRestHanlderImpl { + userAuthService user.UserService, + commonService commonService.CommonService) *CommonRestHanlderImpl { return &CommonRestHanlderImpl{ - logger: logger, - gitOpsConfigService: gitOpsConfigService, - userAuthService: userAuthService, - validator: validator, - enforcer: enforcer, - commonService: commonService, + logger: logger, + userAuthService: userAuthService, + commonService: commonService, } } diff --git a/api/restHandler/CoreAppRestHandler.go b/api/restHandler/CoreAppRestHandler.go index 5cd951d7d83..b8098c2f3db 100644 --- a/api/restHandler/CoreAppRestHandler.go +++ b/api/restHandler/CoreAppRestHandler.go @@ -93,7 +93,6 @@ type CoreAppRestHandlerImpl struct { appWorkflowRepository appWorkflow2.AppWorkflowRepository environmentRepository repository2.EnvironmentRepository configMapRepository chartConfig.ConfigMapRepository - envConfigRepo chartConfig.EnvConfigOverrideRepository chartRepo chartRepoRepository.ChartRepository teamService team.TeamService argoUserService argo.ArgoUserService @@ -107,7 +106,7 @@ func NewCoreAppRestHandlerImpl(logger *zap.SugaredLogger, userAuthService user.U propertiesConfigService pipeline.PropertiesConfigService, appWorkflowService appWorkflow.AppWorkflowService, materialRepository pipelineConfig.MaterialRepository, gitProviderRepo repository.GitProviderRepository, appWorkflowRepository appWorkflow2.AppWorkflowRepository, environmentRepository repository2.EnvironmentRepository, configMapRepository chartConfig.ConfigMapRepository, - envConfigRepo chartConfig.EnvConfigOverrideRepository, chartRepo chartRepoRepository.ChartRepository, teamService team.TeamService, + chartRepo chartRepoRepository.ChartRepository, teamService team.TeamService, argoUserService argo.ArgoUserService, pipelineStageService pipeline.PipelineStageService, ciPipelineRepository pipelineConfig.CiPipelineRepository) *CoreAppRestHandlerImpl { handler := &CoreAppRestHandlerImpl{ logger: logger, @@ -128,7 +127,6 @@ func NewCoreAppRestHandlerImpl(logger *zap.SugaredLogger, userAuthService user.U appWorkflowRepository: appWorkflowRepository, environmentRepository: environmentRepository, configMapRepository: configMapRepository, - envConfigRepo: envConfigRepo, chartRepo: chartRepo, teamService: teamService, argoUserService: argoUserService, @@ -1391,19 +1389,6 @@ func (handler CoreAppRestHandlerImpl) createDeploymentTemplate(ctx context.Conte handler.logger.Errorw("service err, Create in CreateDeploymentTemplate", "err", err, "createRequest", createDeploymentTemplateRequest) return err, http.StatusInternalServerError } - - //updating app metrics - appMetricsRequest := chart.AppMetricEnableDisableRequest{ - AppId: appId, - UserId: userId, - IsAppMetricsEnabled: deploymentTemplate.ShowAppMetrics, - } - _, err = handler.chartService.AppMetricsEnableDisable(appMetricsRequest) - if err != nil { - handler.logger.Errorw("service err, AppMetricsEnableDisable in createDeploymentTemplate", "err", err, "appId", appId, "payload", appMetricsRequest) - return err, http.StatusInternalServerError - } - return nil, http.StatusOK } @@ -1870,12 +1855,13 @@ func (handler CoreAppRestHandlerImpl) createEnvDeploymentTemplate(appId int, use appMetrics = *envConfigProperties.AppMetrics } chartEntry.GlobalOverride = string(envConfigProperties.EnvOverrideValues) - _, err = handler.propertiesConfigService.CreateIfRequired(chartEntry, envId, userId, envConfigProperties.ManualReviewed, models.CHARTSTATUS_SUCCESS, + _, updatedAppMetrics, err := handler.propertiesConfigService.CreateIfRequired(chartEntry, envId, userId, envConfigProperties.ManualReviewed, models.CHARTSTATUS_SUCCESS, true, appMetrics, envConfigProperties.Namespace, envConfigProperties.IsBasicViewLocked, envConfigProperties.CurrentViewEditor, nil) if err != nil { handler.logger.Errorw("service err, CreateIfRequired", "err", err, "appId", appId, "envId", envId, "chartRefId", chartRefId) return err } + envConfigProperties.AppMetrics = &updatedAppMetrics //getting environment properties for db table id(this properties get created when cd pipeline is created) env, err := handler.propertiesConfigService.GetEnvironmentProperties(appId, envId, deploymentTemplateOverride.ChartRefId) @@ -1892,20 +1878,6 @@ func (handler CoreAppRestHandlerImpl) createEnvDeploymentTemplate(appId int, use handler.logger.Errorw("service err, EnvConfigOverrideUpdate", "err", err, "appId", appId, "envId", envId) return err } - - //updating app metrics - appMetricsRequest := &chart.AppMetricEnableDisableRequest{ - AppId: appId, - UserId: userId, - EnvironmentId: envId, - IsAppMetricsEnabled: deploymentTemplateOverride.ShowAppMetrics, - } - _, err = handler.propertiesConfigService.EnvMetricsEnableDisable(appMetricsRequest) - if err != nil { - handler.logger.Errorw("service err, EnvMetricsEnableDisable", "err", err, "appId", appId, "envId", envId) - return err - } - return nil } @@ -2114,20 +2086,6 @@ func convertCdDeploymentStrategies(deploymentStrategies []*appBean.DeploymentStr return convertedStrategies, nil } -func ExtractErrorType(err error) int { - switch err.(type) { - case *util2.InternalServerError: - return http.StatusInternalServerError - case *util2.ForbiddenError: - return http.StatusForbidden - case *util2.BadRequestError: - return http.StatusBadRequest - default: - //TODO : ask and update response for this case - return 0 - } -} - func (handler CoreAppRestHandlerImpl) validateCdPipelines(cdPipelines []*appBean.CdPipelineDetails, appName, token string) (error, int) { for _, cdPipeline := range cdPipelines { envName := cdPipeline.EnvironmentName diff --git a/api/restHandler/GitOpsConfigRestHandler.go b/api/restHandler/GitOpsConfigRestHandler.go index 120d310a8b3..da9130f6c42 100644 --- a/api/restHandler/GitOpsConfigRestHandler.go +++ b/api/restHandler/GitOpsConfigRestHandler.go @@ -25,7 +25,6 @@ import ( bean2 "github.com/devtron-labs/devtron/api/bean" "github.com/devtron-labs/devtron/api/restHandler/common" - "github.com/devtron-labs/devtron/internal/sql/repository" "github.com/devtron-labs/devtron/pkg/auth/authorisation/casbin" "github.com/devtron-labs/devtron/pkg/auth/user" "github.com/devtron-labs/devtron/pkg/gitops" @@ -52,13 +51,12 @@ type GitOpsConfigRestHandlerImpl struct { validator *validator.Validate enforcer casbin.Enforcer teamService team.TeamService - gitOpsRepository repository.GitOpsConfigRepository } func NewGitOpsConfigRestHandlerImpl( logger *zap.SugaredLogger, gitOpsConfigService gitops.GitOpsConfigService, userAuthService user.UserService, - validator *validator.Validate, enforcer casbin.Enforcer, teamService team.TeamService, gitOpsRepository repository.GitOpsConfigRepository) *GitOpsConfigRestHandlerImpl { + validator *validator.Validate, enforcer casbin.Enforcer, teamService team.TeamService) *GitOpsConfigRestHandlerImpl { return &GitOpsConfigRestHandlerImpl{ logger: logger, gitOpsConfigService: gitOpsConfigService, @@ -66,7 +64,6 @@ func NewGitOpsConfigRestHandlerImpl( validator: validator, enforcer: enforcer, teamService: teamService, - gitOpsRepository: gitOpsRepository, } } diff --git a/api/restHandler/app/DeploymentPipelineRestHandler.go b/api/restHandler/app/DeploymentPipelineRestHandler.go index e7dfcac7198..d6076e34fc7 100644 --- a/api/restHandler/app/DeploymentPipelineRestHandler.go +++ b/api/restHandler/app/DeploymentPipelineRestHandler.go @@ -5,6 +5,7 @@ import ( "encoding/json" "errors" "fmt" + bean4 "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/chartRef/bean" "io" "net/http" "strconv" @@ -79,9 +80,6 @@ type DevtronAppDeploymentConfigRestHandler interface { GetDeploymentPipelineStrategy(w http.ResponseWriter, r *http.Request) GetDefaultDeploymentPipelineStrategy(w http.ResponseWriter, r *http.Request) - AppMetricsEnableDisable(w http.ResponseWriter, r *http.Request) - EnvMetricsEnableDisable(w http.ResponseWriter, r *http.Request) - EnvConfigOverrideCreateNamespace(w http.ResponseWriter, r *http.Request) } @@ -117,7 +115,7 @@ func (handler PipelineConfigRestHandlerImpl) ConfigureDeploymentTemplateForApp(w scope := resourceQualifiers.Scope{ AppId: templateRequest.AppId, } - validate, err2 := handler.chartService.DeploymentTemplateValidate(r.Context(), templateRequest.ValuesOverride, chartRefId, scope) + validate, err2 := handler.deploymentTemplateValidationService.DeploymentTemplateValidate(r.Context(), templateRequest.ValuesOverride, chartRefId, scope) if !validate { common.WriteJsonResp(w, err2, nil, http.StatusBadRequest) return @@ -184,7 +182,7 @@ func (handler PipelineConfigRestHandlerImpl) CreateCdPipeline(w http.ResponseWri return } handler.Logger.Infow("request payload, CreateCdPipeline", "payload", cdPipeline) - userUploaded, err := handler.chartService.CheckCustomChartByAppId(cdPipeline.AppId) + userUploaded, err := handler.chartService.CheckIfChartRefUserUploadedByAppId(cdPipeline.AppId) if !userUploaded { err = handler.validator.Struct(cdPipeline) if err != nil { @@ -540,7 +538,7 @@ func (handler PipelineConfigRestHandlerImpl) ChangeChartRef(w http.ResponseWrite common.WriteJsonResp(w, err, "specific environment is not overriden", http.StatusUnprocessableEntity) return } - compatible, oldChartType, newChartType := handler.chartService.ChartRefIdsCompatible(envConfigProperties.ChartRefId, request.TargetChartRefId) + compatible, oldChartType, newChartType := handler.chartRefService.ChartRefIdsCompatible(envConfigProperties.ChartRefId, request.TargetChartRefId) if !compatible { common.WriteJsonResp(w, fmt.Errorf("charts not compatible"), "chart not compatible", http.StatusUnprocessableEntity) return @@ -552,8 +550,8 @@ func (handler PipelineConfigRestHandlerImpl) ChangeChartRef(w http.ResponseWrite return } - if newChartType == chart.RolloutChartType { - enabled, err := handler.chartService.FlaggerCanaryEnabled(envConfigProperties.EnvOverrideValues) + if newChartType == bean4.RolloutChartType { + enabled, err := handler.deploymentTemplateValidationService.FlaggerCanaryEnabled(envConfigProperties.EnvOverrideValues) if err != nil || enabled { handler.Logger.Errorw("rollout charts do not support flaggerCanary, ChangeChartRef", "err", err, "payload", request) common.WriteJsonResp(w, err, "rollout charts do not support flaggerCanary, ChangeChartRef", http.StatusBadRequest) @@ -561,7 +559,7 @@ func (handler PipelineConfigRestHandlerImpl) ChangeChartRef(w http.ResponseWrite } } - envMetrics, err := handler.propertiesConfigService.FindEnvLevelAppMetricsByAppIdAndEnvId(request.AppId, request.EnvId) + envMetrics, err := handler.deployedAppMetricsService.GetMetricsFlagByAppIdAndEnvId(request.AppId, request.EnvId) if err != nil { handler.Logger.Errorw("could not find envMetrics for, ChangeChartRef", "err", err, "payload", request) common.WriteJsonResp(w, err, "env metric could not be fetched", http.StatusBadRequest) @@ -570,7 +568,7 @@ func (handler PipelineConfigRestHandlerImpl) ChangeChartRef(w http.ResponseWrite envConfigProperties.ChartRefId = request.TargetChartRefId envConfigProperties.UserId = userId envConfigProperties.EnvironmentId = request.EnvId - envConfigProperties.AppMetrics = envMetrics.AppMetrics + envConfigProperties.AppMetrics = &envMetrics token := r.Header.Get("token") handler.Logger.Infow("request payload, EnvConfigOverrideCreate", "payload", request) @@ -591,7 +589,7 @@ func (handler PipelineConfigRestHandlerImpl) ChangeChartRef(w http.ResponseWrite EnvId: request.EnvId, ClusterId: envConfigProperties.ClusterId, } - validate, err2 := handler.chartService.DeploymentTemplateValidate(r.Context(), envConfigProperties.EnvOverrideValues, envConfigProperties.ChartRefId, scope) + validate, err2 := handler.deploymentTemplateValidationService.DeploymentTemplateValidate(r.Context(), envConfigProperties.EnvOverrideValues, envConfigProperties.ChartRefId, scope) if !validate { handler.Logger.Errorw("validation err, UpdateAppOverride", "err", err2, "payload", request) common.WriteJsonResp(w, err2, "validation err, UpdateAppOverrid", http.StatusBadRequest) @@ -632,7 +630,7 @@ func (handler PipelineConfigRestHandlerImpl) ChangeChartRef(w http.ResponseWrite ctx = context.WithValue(r.Context(), "token", acdToken) appMetrics := false if envConfigProperties.AppMetrics != nil { - appMetrics = *envMetrics.AppMetrics + appMetrics = envMetrics } templateRequest := chart.TemplateRequest{ AppId: request.AppId, @@ -712,7 +710,7 @@ func (handler PipelineConfigRestHandlerImpl) EnvConfigOverrideCreate(w http.Resp EnvId: environmentId, ClusterId: envConfigProperties.ClusterId, } - validate, err2 := handler.chartService.DeploymentTemplateValidate(r.Context(), envConfigProperties.EnvOverrideValues, chartRefId, scope) + validate, err2 := handler.deploymentTemplateValidationService.DeploymentTemplateValidate(r.Context(), envConfigProperties.EnvOverrideValues, chartRefId, scope) if !validate { handler.Logger.Errorw("validation err, UpdateAppOverride", "err", err2, "payload", envConfigProperties) common.WriteJsonResp(w, err2, nil, http.StatusBadRequest) @@ -821,7 +819,7 @@ func (handler PipelineConfigRestHandlerImpl) EnvConfigOverrideUpdate(w http.Resp EnvId: envId, ClusterId: envConfigProperties.ClusterId, } - validate, err2 := handler.chartService.DeploymentTemplateValidate(r.Context(), envConfigProperties.EnvOverrideValues, chartRefId, scope) + validate, err2 := handler.deploymentTemplateValidationService.DeploymentTemplateValidate(r.Context(), envConfigProperties.EnvOverrideValues, chartRefId, scope) if !validate { handler.Logger.Errorw("validation err, UpdateAppOverride", "err", err2, "payload", envConfigProperties) common.WriteJsonResp(w, err2, nil, http.StatusBadRequest) @@ -875,7 +873,7 @@ func (handler PipelineConfigRestHandlerImpl) GetEnvConfigOverride(w http.Respons return } - schema, readme, err := handler.chartService.GetSchemaAndReadmeForTemplateByChartRefId(chartRefId) + schema, readme, err := handler.chartRefService.GetSchemaAndReadmeForTemplateByChartRefId(chartRefId) if err != nil { handler.Logger.Errorw("err in getting schema and readme, GetEnvConfigOverride", "err", err, "appId", appId, "chartRefId", chartRefId) } @@ -988,14 +986,14 @@ func (handler PipelineConfigRestHandlerImpl) GetDeploymentTemplate(w http.Respon appConfigResponse := make(map[string]interface{}) appConfigResponse["globalConfig"] = nil - err = handler.chartService.CheckChartExists(chartRefId) + err = handler.chartRefService.CheckChartExists(chartRefId) if err != nil { handler.Logger.Errorw("refChartDir Not Found err, JsonSchemaExtractFromFile", err) common.WriteJsonResp(w, err, nil, http.StatusForbidden) return } - schema, readme, err := handler.chartService.GetSchemaAndReadmeForTemplateByChartRefId(chartRefId) + schema, readme, err := handler.chartRefService.GetSchemaAndReadmeForTemplateByChartRefId(chartRefId) if err != nil { handler.Logger.Errorw("err in getting schema and readme, GetDeploymentTemplate", "err", err, "appId", appId, "chartRefId", chartRefId) } @@ -1008,7 +1006,7 @@ func (handler PipelineConfigRestHandlerImpl) GetDeploymentTemplate(w http.Respon } if pg.ErrNoRows == err { - appOverride, _, err := handler.chartService.GetAppOverrideForDefaultTemplate(chartRefId) + appOverride, _, err := handler.chartRefService.GetAppOverrideForDefaultTemplate(chartRefId) if err != nil { handler.Logger.Errorw("service err, GetDeploymentTemplate", "err", err, "appId", appId, "chartRefId", chartRefId) common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) @@ -1083,7 +1081,7 @@ func (handler *PipelineConfigRestHandlerImpl) GetDefaultDeploymentTemplate(w htt common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), "unauthorized user", http.StatusForbidden) return } - defaultTemplate, _, err := handler.chartService.GetAppOverrideForDefaultTemplate(chartRefId) + defaultTemplate, _, err := handler.chartRefService.GetAppOverrideForDefaultTemplate(chartRefId) if err != nil { handler.Logger.Errorw("error in getting default deployment template, GetDefaultDeploymentTemplate", "err", err, "appId", appId, "chartRefId", chartRefId) common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) @@ -1361,7 +1359,7 @@ func (handler PipelineConfigRestHandlerImpl) GetAppOverrideForDefaultTemplate(w } //RBAC - appOverride, _, err := handler.chartService.GetAppOverrideForDefaultTemplate(chartRefId) + appOverride, _, err := handler.chartRefService.GetAppOverrideForDefaultTemplate(chartRefId) if err != nil { handler.Logger.Errorw("service err, UpdateCiTemplate", "err", err, "appId", appId, "chartRefId", chartRefId) common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) @@ -1416,7 +1414,7 @@ func (handler PipelineConfigRestHandlerImpl) UpdateAppOverride(w http.ResponseWr AppId: templateRequest.AppId, } _, span = otel.Tracer("orchestrator").Start(ctx, "chartService.DeploymentTemplateValidate") - validate, err2 := handler.chartService.DeploymentTemplateValidate(ctx, templateRequest.ValuesOverride, chartRefId, scope) + validate, err2 := handler.deploymentTemplateValidationService.DeploymentTemplateValidate(ctx, templateRequest.ValuesOverride, chartRefId, scope) span.End() if !validate { handler.Logger.Errorw("validation err, UpdateAppOverride", "err", err2, "payload", templateRequest) @@ -1569,103 +1567,6 @@ func (handler PipelineConfigRestHandlerImpl) EnvConfigOverrideReset(w http.Respo common.WriteJsonResp(w, err, isSuccess, http.StatusOK) } -func (handler PipelineConfigRestHandlerImpl) AppMetricsEnableDisable(w http.ResponseWriter, r *http.Request) { - decoder := json.NewDecoder(r.Body) - userId, err := handler.userAuthService.GetLoggedInUser(r) - if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) - return - } - token := r.Header.Get("token") - vars := mux.Vars(r) - appId, err := strconv.Atoi(vars["appId"]) - if err != nil { - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) - return - } - var appMetricEnableDisableRequest chart.AppMetricEnableDisableRequest - err = decoder.Decode(&appMetricEnableDisableRequest) - appMetricEnableDisableRequest.AppId = appId - appMetricEnableDisableRequest.UserId = userId - if err != nil { - handler.Logger.Errorw("request err, AppMetricsEnableDisable", "err", err, "appId", appId, "payload", appMetricEnableDisableRequest) - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) - return - } - handler.Logger.Infow("request payload, AppMetricsEnableDisable", "err", err, "appId", appId, "payload", appMetricEnableDisableRequest) - app, err := handler.pipelineBuilder.GetApp(appId) - if err != nil { - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) - return - } - resourceName := handler.enforcerUtil.GetAppRBACName(app.AppName) - if ok := handler.enforcer.Enforce(token, casbin.ResourceApplications, casbin.ActionCreate, resourceName); !ok { - common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), "Unauthorized User", http.StatusForbidden) - return - } - createResp, err := handler.chartService.AppMetricsEnableDisable(appMetricEnableDisableRequest) - if err != nil { - handler.Logger.Errorw("service err, AppMetricsEnableDisable", "err", err, "appId", appId, "payload", appMetricEnableDisableRequest) - common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) - return - } - common.WriteJsonResp(w, err, createResp, http.StatusOK) -} - -func (handler PipelineConfigRestHandlerImpl) EnvMetricsEnableDisable(w http.ResponseWriter, r *http.Request) { - userId, err := handler.userAuthService.GetLoggedInUser(r) - if userId == 0 || err != nil { - common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized) - return - } - token := r.Header.Get("token") - vars := mux.Vars(r) - appId, err := strconv.Atoi(vars["appId"]) - if err != nil { - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) - return - } - environmentId, err := strconv.Atoi(vars["environmentId"]) - if err != nil { - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) - return - } - decoder := json.NewDecoder(r.Body) - var appMetricEnableDisableRequest chart.AppMetricEnableDisableRequest - err = decoder.Decode(&appMetricEnableDisableRequest) - appMetricEnableDisableRequest.UserId = userId - appMetricEnableDisableRequest.AppId = appId - appMetricEnableDisableRequest.EnvironmentId = environmentId - if err != nil { - handler.Logger.Errorw("request err, EnvMetricsEnableDisable", "err", err, "appId", appId, "environmentId", environmentId, "payload", appMetricEnableDisableRequest) - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) - return - } - handler.Logger.Infow("request payload, EnvMetricsEnableDisable", "err", err, "appId", appId, "environmentId", environmentId, "payload", appMetricEnableDisableRequest) - app, err := handler.pipelineBuilder.GetApp(appId) - if err != nil { - common.WriteJsonResp(w, err, nil, http.StatusBadRequest) - return - } - resourceName := handler.enforcerUtil.GetAppRBACNameByAppId(appId) - if ok := handler.enforcer.Enforce(token, casbin.ResourceApplications, casbin.ActionCreate, resourceName); !ok { - common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), "Unauthorized User", http.StatusForbidden) - return - } - object := handler.enforcerUtil.GetAppRBACByAppNameAndEnvId(app.AppName, appMetricEnableDisableRequest.EnvironmentId) - if ok := handler.enforcer.Enforce(token, casbin.ResourceEnvironment, casbin.ActionCreate, object); !ok { - common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), "Unauthorized User", http.StatusForbidden) - return - } - createResp, err := handler.propertiesConfigService.EnvMetricsEnableDisable(&appMetricEnableDisableRequest) - if err != nil { - handler.Logger.Errorw("service err, EnvMetricsEnableDisable", "err", err, "appId", appId, "environmentId", environmentId, "payload", appMetricEnableDisableRequest) - common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) - return - } - common.WriteJsonResp(w, err, createResp, http.StatusOK) -} - func (handler *PipelineConfigRestHandlerImpl) ListDeploymentHistory(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { @@ -2279,7 +2180,7 @@ func (handler PipelineConfigRestHandlerImpl) UpgradeForAllApps(w http.ResponseWr return } - newAppOverride, _, err := handler.chartService.GetAppOverrideForDefaultTemplate(chartUpgradeRequest.ChartRefId) + newAppOverride, _, err := handler.chartRefService.GetAppOverrideForDefaultTemplate(chartUpgradeRequest.ChartRefId) if err != nil { handler.Logger.Errorw("service err, UpgradeForAllApps", "err", err, "payload", chartUpgradeRequest) common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) diff --git a/api/restHandler/app/PipelineConfigRestHandler.go b/api/restHandler/app/PipelineConfigRestHandler.go index 71eeeade084..557d8c5e881 100644 --- a/api/restHandler/app/PipelineConfigRestHandler.go +++ b/api/restHandler/app/PipelineConfigRestHandler.go @@ -22,6 +22,9 @@ import ( "context" "encoding/json" "fmt" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deployedAppMetrics" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/chartRef" "io" "net/http" "strconv" @@ -41,8 +44,6 @@ import ( "github.com/go-pg/pg" "go.opentelemetry.io/otel" - bean2 "github.com/devtron-labs/devtron/api/bean" - "github.com/devtron-labs/devtron/client/argocdServer/application" "github.com/devtron-labs/devtron/internal/sql/repository" "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig" "github.com/devtron-labs/devtron/internal/sql/repository/security" @@ -57,10 +58,7 @@ import ( util2 "github.com/devtron-labs/devtron/util" "github.com/devtron-labs/devtron/util/rbac" "github.com/gorilla/mux" - "github.com/grpc-ecosystem/grpc-gateway/runtime" "go.uber.org/zap" - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" "gopkg.in/go-playground/validator.v9" ) @@ -101,42 +99,44 @@ type PipelineConfigRestHandler interface { } type PipelineConfigRestHandlerImpl struct { - pipelineBuilder pipeline.PipelineBuilder - ciPipelineRepository pipelineConfig.CiPipelineRepository - ciPipelineMaterialRepository pipelineConfig.CiPipelineMaterialRepository - ciHandler pipeline.CiHandler - Logger *zap.SugaredLogger - chartService chart.ChartService - propertiesConfigService pipeline.PropertiesConfigService - application application.ServiceClient - userAuthService user.UserService - validator *validator.Validate - teamService team.TeamService - enforcer casbin.Enforcer - gitSensorClient gitSensor.Client - pipelineRepository pipelineConfig.PipelineRepository - appWorkflowService appWorkflow.AppWorkflowService - enforcerUtil rbac.EnforcerUtil - envService request.EnvironmentService - gitRegistryConfig pipeline.GitRegistryConfig - dockerRegistryConfig pipeline.DockerRegistryConfig - cdHandler pipeline.CdHandler - appCloneService appClone.AppCloneService - materialRepository pipelineConfig.MaterialRepository - policyService security2.PolicyService - scanResultRepository security.ImageScanResultRepository - gitProviderRepo repository.GitProviderRepository - argoUserService argo.ArgoUserService - imageTaggingService pipeline.ImageTaggingService - deploymentTemplateService generateManifest.DeploymentTemplateService - pipelineRestHandlerEnvConfig *PipelineRestHandlerEnvConfig - ciArtifactRepository repository.CiArtifactRepository + pipelineBuilder pipeline.PipelineBuilder + ciPipelineRepository pipelineConfig.CiPipelineRepository + ciPipelineMaterialRepository pipelineConfig.CiPipelineMaterialRepository + ciHandler pipeline.CiHandler + Logger *zap.SugaredLogger + deploymentTemplateValidationService deploymentTemplate.DeploymentTemplateValidationService + chartService chart.ChartService + propertiesConfigService pipeline.PropertiesConfigService + userAuthService user.UserService + validator *validator.Validate + teamService team.TeamService + enforcer casbin.Enforcer + gitSensorClient gitSensor.Client + pipelineRepository pipelineConfig.PipelineRepository + appWorkflowService appWorkflow.AppWorkflowService + enforcerUtil rbac.EnforcerUtil + envService request.EnvironmentService + gitRegistryConfig pipeline.GitRegistryConfig + dockerRegistryConfig pipeline.DockerRegistryConfig + cdHandler pipeline.CdHandler + appCloneService appClone.AppCloneService + materialRepository pipelineConfig.MaterialRepository + policyService security2.PolicyService + scanResultRepository security.ImageScanResultRepository + gitProviderRepo repository.GitProviderRepository + argoUserService argo.ArgoUserService + imageTaggingService pipeline.ImageTaggingService + deploymentTemplateService generateManifest.DeploymentTemplateService + pipelineRestHandlerEnvConfig *PipelineRestHandlerEnvConfig + ciArtifactRepository repository.CiArtifactRepository + deployedAppMetricsService deployedAppMetrics.DeployedAppMetricsService + chartRefService chartRef.ChartRefService } func NewPipelineRestHandlerImpl(pipelineBuilder pipeline.PipelineBuilder, Logger *zap.SugaredLogger, + deploymentTemplateValidationService deploymentTemplate.DeploymentTemplateValidationService, chartService chart.ChartService, propertiesConfigService pipeline.PropertiesConfigService, - application application.ServiceClient, userAuthService user.UserService, teamService team.TeamService, enforcer casbin.Enforcer, @@ -154,43 +154,47 @@ func NewPipelineRestHandlerImpl(pipelineBuilder pipeline.PipelineBuilder, Logger scanResultRepository security.ImageScanResultRepository, gitProviderRepo repository.GitProviderRepository, argoUserService argo.ArgoUserService, ciPipelineMaterialRepository pipelineConfig.CiPipelineMaterialRepository, imageTaggingService pipeline.ImageTaggingService, - ciArtifactRepository repository.CiArtifactRepository) *PipelineConfigRestHandlerImpl { + ciArtifactRepository repository.CiArtifactRepository, + deployedAppMetricsService deployedAppMetrics.DeployedAppMetricsService, + chartRefService chartRef.ChartRefService) *PipelineConfigRestHandlerImpl { envConfig := &PipelineRestHandlerEnvConfig{} err := env.Parse(envConfig) if err != nil { Logger.Errorw("error in parsing PipelineRestHandlerEnvConfig", "err", err) } return &PipelineConfigRestHandlerImpl{ - pipelineBuilder: pipelineBuilder, - Logger: Logger, - chartService: chartService, - propertiesConfigService: propertiesConfigService, - application: application, - userAuthService: userAuthService, - validator: validator, - teamService: teamService, - enforcer: enforcer, - ciHandler: ciHandler, - gitSensorClient: gitSensorClient, - ciPipelineRepository: ciPipelineRepository, - pipelineRepository: pipelineRepository, - enforcerUtil: enforcerUtil, - envService: envService, - gitRegistryConfig: gitRegistryConfig, - dockerRegistryConfig: dockerRegistryConfig, - cdHandler: cdHandler, - appCloneService: appCloneService, - appWorkflowService: appWorkflowService, - materialRepository: materialRepository, - policyService: policyService, - scanResultRepository: scanResultRepository, - gitProviderRepo: gitProviderRepo, - argoUserService: argoUserService, - ciPipelineMaterialRepository: ciPipelineMaterialRepository, - imageTaggingService: imageTaggingService, - deploymentTemplateService: deploymentTemplateService, - pipelineRestHandlerEnvConfig: envConfig, - ciArtifactRepository: ciArtifactRepository, + pipelineBuilder: pipelineBuilder, + Logger: Logger, + deploymentTemplateValidationService: deploymentTemplateValidationService, + chartService: chartService, + propertiesConfigService: propertiesConfigService, + userAuthService: userAuthService, + validator: validator, + teamService: teamService, + enforcer: enforcer, + ciHandler: ciHandler, + gitSensorClient: gitSensorClient, + ciPipelineRepository: ciPipelineRepository, + pipelineRepository: pipelineRepository, + enforcerUtil: enforcerUtil, + envService: envService, + gitRegistryConfig: gitRegistryConfig, + dockerRegistryConfig: dockerRegistryConfig, + cdHandler: cdHandler, + appCloneService: appCloneService, + appWorkflowService: appWorkflowService, + materialRepository: materialRepository, + policyService: policyService, + scanResultRepository: scanResultRepository, + gitProviderRepo: gitProviderRepo, + argoUserService: argoUserService, + ciPipelineMaterialRepository: ciPipelineMaterialRepository, + imageTaggingService: imageTaggingService, + deploymentTemplateService: deploymentTemplateService, + pipelineRestHandlerEnvConfig: envConfig, + ciArtifactRepository: ciArtifactRepository, + deployedAppMetricsService: deployedAppMetricsService, + chartRefService: chartRefService, } } @@ -562,31 +566,6 @@ func (handler *PipelineConfigRestHandlerImpl) sendData(event []byte, w http.Resp } } -func (handler *PipelineConfigRestHandlerImpl) handleForwardResponseStreamError(wroteHeader bool, w http.ResponseWriter, err error) { - code := "000" - if !wroteHeader { - s, ok := status.FromError(err) - if !ok { - s = status.New(codes.Unknown, err.Error()) - } - w.WriteHeader(runtime.HTTPStatusFromCode(s.Code())) - code = fmt.Sprint(s.Code()) - } - response := bean2.Response{} - apiErr := bean2.ApiError{} - apiErr.Code = code // 000=unknown - apiErr.InternalMessage = err.Error() - response.Errors = []bean2.ApiError{apiErr} - buf, err2 := json.Marshal(response) - if err2 != nil { - handler.Logger.Errorw("marshal err, handleForwardResponseStreamError", "err", err2, "response", response) - } - if _, err3 := w.Write(buf); err3 != nil { - handler.Logger.Errorw("Failed to notify error to client, handleForwardResponseStreamError", "err", err3, "response", response) - return - } -} - func (handler PipelineConfigRestHandlerImpl) FetchAppWorkflowStatusForTriggerView(w http.ResponseWriter, r *http.Request) { userId, err := handler.userAuthService.GetLoggedInUser(r) if userId == 0 || err != nil { diff --git a/api/restHandler/common/apiError.go b/api/restHandler/common/apiError.go index 8d4c29689db..b95074876b7 100644 --- a/api/restHandler/common/apiError.go +++ b/api/restHandler/common/apiError.go @@ -126,29 +126,6 @@ func WriteJsonResp(w http.ResponseWriter, err error, respBody interface{}, statu } -// use this method when we have specific api error to be conveyed to api User -func writeJsonRespStructured(w http.ResponseWriter, err error, respBody interface{}, status int, apiErrors []*util.ApiError) { - response := Response{} - response.Code = status - response.Status = http.StatusText(status) - if err == nil { - response.Result = respBody - } else { - response.Errors = apiErrors - } - b, err := json.Marshal(response) - if err != nil { - util.GetLogger().Error("error in marshaling err object", err) - status = 500 - } - w.Header().Set(CONTENT_TYPE, APPLICATION_JSON) - w.WriteHeader(status) - _, err = w.Write(b) - if err != nil { - util.GetLogger().Error(err) - } -} - // global response body used across api type Response struct { Code int `json:"code,omitempty"` @@ -156,12 +133,3 @@ type Response struct { Result interface{} `json:"result,omitempty"` Errors []*util.ApiError `json:"errors,omitempty"` } - -func contains(s []*string, e *string) bool { - for _, a := range s { - if a == e { - return true - } - } - return false -} diff --git a/api/router/PipelineConfigRouter.go b/api/router/PipelineConfigRouter.go index 1f1339645be..17ed897e733 100644 --- a/api/router/PipelineConfigRouter.go +++ b/api/router/PipelineConfigRouter.go @@ -130,9 +130,6 @@ func (router PipelineConfigRouterImpl) initPipelineConfigRouter(configRouter *mu configRouter.Path("/env/reset/{appId}/{environmentId}/{id}").HandlerFunc(router.restHandler.EnvConfigOverrideReset).Methods("DELETE") configRouter.Path("/env/namespace/{appId}/{environmentId}").HandlerFunc(router.restHandler.EnvConfigOverrideCreateNamespace).Methods("POST") - configRouter.Path("/template/metrics/{appId}").HandlerFunc(router.restHandler.AppMetricsEnableDisable).Methods("POST") - configRouter.Path("/env/metrics/{appId}/{environmentId}").HandlerFunc(router.restHandler.EnvMetricsEnableDisable).Methods("POST") - configRouter.Path("/app-wf"). HandlerFunc(router.appWorkflowRestHandler.CreateAppWorkflow).Methods("POST") diff --git a/client/argocdServer/ArgoClientWrapperService.go b/client/argocdServer/ArgoClientWrapperService.go index 3cd2cf73808..add0a58122f 100644 --- a/client/argocdServer/ArgoClientWrapperService.go +++ b/client/argocdServer/ArgoClientWrapperService.go @@ -3,10 +3,12 @@ package argocdServer import ( "context" application2 "github.com/argoproj/argo-cd/v2/pkg/apiclient/application" + repository2 "github.com/argoproj/argo-cd/v2/pkg/apiclient/repository" "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" "github.com/caarlos0/env" "github.com/devtron-labs/devtron/client/argocdServer/application" "github.com/devtron-labs/devtron/client/argocdServer/bean" + "github.com/devtron-labs/devtron/client/argocdServer/repository" "go.uber.org/zap" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -34,22 +36,25 @@ type ArgoClientWrapperService interface { // UpdateArgoCDSyncModeIfNeeded - if ARGO_AUTO_SYNC_ENABLED=true and app is in manual sync mode or vice versa update app UpdateArgoCDSyncModeIfNeeded(ctx context.Context, argoApplication *v1alpha1.Application) (err error) + + //RegisterGitOpsRepoInArgo - register a repository in argo-cd + RegisterGitOpsRepoInArgo(ctx context.Context, repoUrl string) (err error) } type ArgoClientWrapperServiceImpl struct { - logger *zap.SugaredLogger - acdClient application.ServiceClient - ACDConfig *ACDConfig + logger *zap.SugaredLogger + acdClient application.ServiceClient + ACDConfig *ACDConfig + repositoryService repository.ServiceClient } -func NewArgoClientWrapperServiceImpl(logger *zap.SugaredLogger, - acdClient application.ServiceClient, - ACDConfig *ACDConfig, -) *ArgoClientWrapperServiceImpl { +func NewArgoClientWrapperServiceImpl(logger *zap.SugaredLogger, acdClient application.ServiceClient, + ACDConfig *ACDConfig, repositoryService repository.ServiceClient) *ArgoClientWrapperServiceImpl { return &ArgoClientWrapperServiceImpl{ - logger: logger, - acdClient: acdClient, - ACDConfig: ACDConfig, + logger: logger, + acdClient: acdClient, + ACDConfig: ACDConfig, + repositoryService: repositoryService, } } @@ -130,3 +135,15 @@ func (impl *ArgoClientWrapperServiceImpl) CreateRequestForArgoCDSyncModeUpdateRe Retry: argoApplication.Spec.SyncPolicy.Retry, }}} } + +func (impl *ArgoClientWrapperServiceImpl) RegisterGitOpsRepoInArgo(ctx context.Context, repoUrl string) (err error) { + repo := &v1alpha1.Repository{ + Repo: repoUrl, + } + repo, err = impl.repositoryService.Create(ctx, &repository2.RepoCreateRequest{Repo: repo, Upsert: true}) + if err != nil { + impl.logger.Errorw("error in creating argo Repository ", "err", err) + } + impl.logger.Infow("gitOps repo registered in argo", "name", repoUrl) + return err +} diff --git a/client/telemetry/TelemetryEventClientExtended.go b/client/telemetry/TelemetryEventClientExtended.go index c04328aa723..386b3f33e3b 100644 --- a/client/telemetry/TelemetryEventClientExtended.go +++ b/client/telemetry/TelemetryEventClientExtended.go @@ -3,6 +3,7 @@ package telemetry import ( "encoding/json" cloudProviderIdentifier "github.com/devtron-labs/common-lib/cloud-provider-identifier" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config" cron3 "github.com/devtron-labs/devtron/util/cron" "net/http" "time" @@ -36,7 +37,6 @@ type TelemetryEventClientImplExtended struct { appListingRepository repository.AppListingRepository ciPipelineRepository pipelineConfig.CiPipelineRepository pipelineRepository pipelineConfig.PipelineRepository - gitOpsConfigRepository repository.GitOpsConfigRepository gitProviderRepository repository.GitProviderRepository dockerArtifactStoreRepository dockerRegistryRepository.DockerArtifactStoreRepository appRepository app.AppRepository @@ -46,6 +46,7 @@ type TelemetryEventClientImplExtended struct { ciTemplateRepository pipelineConfig.CiTemplateRepository chartRepository chartRepoRepository.ChartRepository ciBuildConfigService pipeline.CiBuildConfigService + gitOpsConfigReadService config.GitOpsConfigReadService *TelemetryEventClientImpl } @@ -54,15 +55,16 @@ func NewTelemetryEventClientImplExtended(logger *zap.SugaredLogger, client *http environmentService cluster.EnvironmentService, userService user2.UserService, appListingRepository repository.AppListingRepository, PosthogClient *PosthogClient, ciPipelineRepository pipelineConfig.CiPipelineRepository, pipelineRepository pipelineConfig.PipelineRepository, - gitOpsConfigRepository repository.GitOpsConfigRepository, gitProviderRepository repository.GitProviderRepository, - attributeRepo repository.AttributesRepository, ssoLoginService sso.SSOLoginService, appRepository app.AppRepository, + gitProviderRepository repository.GitProviderRepository, attributeRepo repository.AttributesRepository, + ssoLoginService sso.SSOLoginService, appRepository app.AppRepository, ciWorkflowRepository pipelineConfig.CiWorkflowRepository, cdWorkflowRepository pipelineConfig.CdWorkflowRepository, dockerArtifactStoreRepository dockerRegistryRepository.DockerArtifactStoreRepository, materialRepository pipelineConfig.MaterialRepository, ciTemplateRepository pipelineConfig.CiTemplateRepository, chartRepository chartRepoRepository.ChartRepository, userAuditService user2.UserAuditService, ciBuildConfigService pipeline.CiBuildConfigService, moduleRepository moduleRepo.ModuleRepository, serverDataStore *serverDataStore.ServerDataStore, helmAppClient client.HelmAppClient, InstalledAppRepository repository2.InstalledAppRepository, userAttributesRepository repository.UserAttributesRepository, - cloudProviderIdentifierService cloudProviderIdentifier.ProviderIdentifierService, cronLogger *cron3.CronLoggerImpl) (*TelemetryEventClientImplExtended, error) { + cloudProviderIdentifierService cloudProviderIdentifier.ProviderIdentifierService,cronLogger *cron3.CronLoggerImpl, + gitOpsConfigReadService config.GitOpsConfigReadService) (*TelemetryEventClientImplExtended, error) { cron := cron.New( cron.WithChain(cron.Recover(cronLogger))) @@ -72,7 +74,6 @@ func NewTelemetryEventClientImplExtended(logger *zap.SugaredLogger, client *http appListingRepository: appListingRepository, ciPipelineRepository: ciPipelineRepository, pipelineRepository: pipelineRepository, - gitOpsConfigRepository: gitOpsConfigRepository, gitProviderRepository: gitProviderRepository, dockerArtifactStoreRepository: dockerArtifactStoreRepository, appRepository: appRepository, @@ -82,7 +83,7 @@ func NewTelemetryEventClientImplExtended(logger *zap.SugaredLogger, client *http ciTemplateRepository: ciTemplateRepository, chartRepository: chartRepository, ciBuildConfigService: ciBuildConfigService, - + gitOpsConfigReadService: gitOpsConfigReadService, TelemetryEventClientImpl: &TelemetryEventClientImpl{ cron: cron, logger: logger, @@ -235,8 +236,8 @@ func (impl *TelemetryEventClientImplExtended) SendSummaryEvent(eventType string) return err } - gitOps, err := impl.gitOpsConfigRepository.GetAllGitOpsConfig() - if err != nil && err != pg.ErrNoRows { + gitOpsCount, err := impl.gitOpsConfigReadService.GetConfiguredGitOpsCount() + if err != nil { impl.logger.Errorw("exception caught inside telemetry summary event", "err", err) return err } @@ -310,7 +311,7 @@ func (impl *TelemetryEventClientImplExtended) SendSummaryEvent(eventType string) payload.CdCountPerDay = len(cdPipeline) payload.GitAccountsCount = len(gitAccounts) - payload.GitOpsCount = len(gitOps) + payload.GitOpsCount = gitOpsCount payload.HostURL = hostURL payload.DevtronGitVersion = devtronVersion.GitCommit payload.Build = build diff --git a/cmd/external-app/wire.go b/cmd/external-app/wire.go index c26d2a84702..4c94633236b 100644 --- a/cmd/external-app/wire.go +++ b/cmd/external-app/wire.go @@ -39,12 +39,12 @@ import ( security2 "github.com/devtron-labs/devtron/internal/sql/repository/security" "github.com/devtron-labs/devtron/internal/util" "github.com/devtron-labs/devtron/pkg/app" - appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" - repository3 "github.com/devtron-labs/devtron/pkg/appStore/chartGroup/repository" + repository4 "github.com/devtron-labs/devtron/pkg/appStore/chartGroup/repository" appStoreDeploymentTool "github.com/devtron-labs/devtron/pkg/appStore/deployment/tool" "github.com/devtron-labs/devtron/pkg/attributes" - chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository" delete2 "github.com/devtron-labs/devtron/pkg/delete" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git" "github.com/devtron-labs/devtron/pkg/kubernetesResourceAuditLogs" repository2 "github.com/devtron-labs/devtron/pkg/kubernetesResourceAuditLogs/repository" "github.com/devtron-labs/devtron/pkg/pipeline" @@ -82,7 +82,7 @@ func InitializeApp() (*App, error) { apiToken.ApiTokenWireSet, webhookHelm.WebhookHelmWireSet, terminal.TerminalWireSet, - + gitOps.GitOpsWireSet, NewApp, NewMuxRouter, util3.GetGlobalEnvVariables, @@ -143,8 +143,6 @@ func InitializeApp() (*App, error) { // binding gitops to helm (for hyperion) wire.Bind(new(appStoreDeploymentTool.AppStoreDeploymentArgoCdService), new(*appStoreDeploymentTool.AppStoreDeploymentHelmServiceImpl)), - wire.Value(chartRepoRepository.RefChartDir("scripts/devtron-reference-helm-charts")), - router.NewTelemetryRouterImpl, wire.Bind(new(router.TelemetryRouter), new(*router.TelemetryRouterImpl)), restHandler.NewTelemetryRestHandlerImpl, @@ -157,9 +155,6 @@ func InitializeApp() (*App, error) { wire.Bind(new(dashboardEvent.DashboardTelemetryRouter), new(*dashboardEvent.DashboardTelemetryRouterImpl)), - repository.NewGitOpsConfigRepositoryImpl, - wire.Bind(new(repository.GitOpsConfigRepository), new(*repository.GitOpsConfigRepositoryImpl)), - //binding argoUserService to helm via dummy implementation(HelmUserServiceImpl) argo.NewHelmUserServiceImpl, wire.Bind(new(argo.ArgoUserService), new(*argo.HelmUserServiceImpl)), @@ -182,10 +177,8 @@ func InitializeApp() (*App, error) { util.NewChartTemplateServiceImpl, wire.Bind(new(util.ChartTemplateService), new(*util.ChartTemplateServiceImpl)), - wire.Value(util.ChartWorkingDir("/tmp/charts/")), - wire.Value(appStoreBean.RefChartProxyDir("scripts/devtron-reference-helm-charts")), - util.NewGitFactory, - util.NewGitCliUtil, + git.NewGitFactory, + git.NewGitCliUtil, security2.NewScanToolMetadataRepositoryImpl, wire.Bind(new(security2.ScanToolMetadataRepository), new(*security2.ScanToolMetadataRepositoryImpl)), @@ -206,8 +199,8 @@ func InitializeApp() (*App, error) { wire.Bind(new(dockerRegistryRepository.OCIRegistryConfigRepository), new(*dockerRegistryRepository.OCIRegistryConfigRepositoryImpl)), // chart group repository layer wire injection started - repository3.NewChartGroupDeploymentRepositoryImpl, - wire.Bind(new(repository3.ChartGroupDeploymentRepository), new(*repository3.ChartGroupDeploymentRepositoryImpl)), + repository4.NewChartGroupDeploymentRepositoryImpl, + wire.Bind(new(repository4.ChartGroupDeploymentRepository), new(*repository4.ChartGroupDeploymentRepositoryImpl)), // chart group repository layer wire injection ended // end: docker registry wire set injection diff --git a/cmd/external-app/wire_gen.go b/cmd/external-app/wire_gen.go index 547f195ba2d..889a659a107 100644 --- a/cmd/external-app/wire_gen.go +++ b/cmd/external-app/wire_gen.go @@ -46,7 +46,6 @@ import ( "github.com/devtron-labs/devtron/internal/util" "github.com/devtron-labs/devtron/pkg/apiToken" app2 "github.com/devtron-labs/devtron/pkg/app" - "github.com/devtron-labs/devtron/pkg/appStore/bean" repository8 "github.com/devtron-labs/devtron/pkg/appStore/chartGroup/repository" "github.com/devtron-labs/devtron/pkg/appStore/chartProvider" "github.com/devtron-labs/devtron/pkg/appStore/deployment/common" @@ -69,6 +68,8 @@ import ( repository2 "github.com/devtron-labs/devtron/pkg/cluster/repository" "github.com/devtron-labs/devtron/pkg/clusterTerminalAccess" delete2 "github.com/devtron-labs/devtron/pkg/delete" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git" "github.com/devtron-labs/devtron/pkg/externalLink" "github.com/devtron-labs/devtron/pkg/genericNotes" repository6 "github.com/devtron-labs/devtron/pkg/genericNotes/repository" @@ -99,7 +100,7 @@ import ( // Injectors from wire.go: func InitializeApp() (*App, error) { - config, err := sql.GetConfig() + sqlConfig, err := sql.GetConfig() if err != nil { return nil, err } @@ -107,7 +108,7 @@ func InitializeApp() (*App, error) { if err != nil { return nil, err } - db, err := sql.NewDbConnection(config, sugaredLogger) + db, err := sql.NewDbConnection(sqlConfig, sugaredLogger) if err != nil { return nil, err } @@ -232,10 +233,10 @@ func InitializeApp() (*App, error) { return nil, err } dashboardRouterImpl := dashboard.NewDashboardRouterImpl(sugaredLogger, dashboardConfig) - chartWorkingDir := _wireChartWorkingDirValue + chartTemplateServiceImpl := util.NewChartTemplateServiceImpl(sugaredLogger) gitOpsConfigRepositoryImpl := repository3.NewGitOpsConfigRepositoryImpl(sugaredLogger, db) - gitCliUtil := util.NewGitCliUtil(sugaredLogger) - gitFactory, err := util.NewGitFactory(sugaredLogger, gitOpsConfigRepositoryImpl, gitCliUtil) + gitCliUtil := git.NewGitCliUtil(sugaredLogger) + gitFactory, err := git.NewGitFactory(sugaredLogger, gitOpsConfigRepositoryImpl, gitCliUtil) if err != nil { return nil, err } @@ -243,10 +244,9 @@ func InitializeApp() (*App, error) { if err != nil { return nil, err } - chartRepositoryImpl := chartRepoRepository.NewChartRepository(db) - chartTemplateServiceImpl := util.NewChartTemplateServiceImpl(sugaredLogger, chartWorkingDir, httpClient, gitFactory, globalEnvVariables, gitOpsConfigRepositoryImpl, userRepositoryImpl, chartRepositoryImpl) - refChartProxyDir := _wireRefChartProxyDirValue - appStoreDeploymentCommonServiceImpl := appStoreDeploymentCommon.NewAppStoreDeploymentCommonServiceImpl(sugaredLogger, installedAppRepositoryImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl, chartTemplateServiceImpl, refChartProxyDir, gitFactory, gitOpsConfigRepositoryImpl) + gitOpsConfigReadServiceImpl := config.NewGitOpsConfigReadServiceImpl(sugaredLogger, gitOpsConfigRepositoryImpl, userServiceImpl, globalEnvVariables) + gitOperationServiceImpl := git.NewGitOperationServiceImpl(sugaredLogger, gitFactory, gitOpsConfigReadServiceImpl, chartTemplateServiceImpl) + appStoreDeploymentCommonServiceImpl := appStoreDeploymentCommon.NewAppStoreDeploymentCommonServiceImpl(sugaredLogger, installedAppRepositoryImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl, chartTemplateServiceImpl, gitFactory, gitOpsConfigReadServiceImpl, gitOperationServiceImpl) attributesServiceImpl := attributes.NewAttributesServiceImpl(sugaredLogger, attributesRepositoryImpl) helmAppRestHandlerImpl := client2.NewHelmAppRestHandlerImpl(sugaredLogger, helmAppServiceImpl, enforcerImpl, clusterServiceImpl, enforcerUtilHelmImpl, appStoreDeploymentCommonServiceImpl, userServiceImpl, attributesServiceImpl, serverEnvConfigServerEnvConfig) helmAppRouterImpl := client2.NewHelmAppRouterImpl(helmAppRestHandlerImpl) @@ -266,9 +266,7 @@ func InitializeApp() (*App, error) { enforcerUtilImpl := rbac.NewEnforcerUtilImpl(sugaredLogger, teamRepositoryImpl, appRepositoryImpl, environmentRepositoryImpl, pipelineRepositoryImpl, ciPipelineRepositoryImpl, clusterRepositoryImpl, enforcerImpl) k8sApplicationRestHandlerImpl := application2.NewK8sApplicationRestHandlerImpl(sugaredLogger, k8sApplicationServiceImpl, pumpImpl, terminalSessionHandlerImpl, enforcerImpl, enforcerUtilHelmImpl, enforcerUtilImpl, helmAppServiceImpl, userServiceImpl, k8sCommonServiceImpl, validate) k8sApplicationRouterImpl := application2.NewK8sApplicationRouterImpl(k8sApplicationRestHandlerImpl) - chartRefRepositoryImpl := chartRepoRepository.NewChartRefRepositoryImpl(db) - refChartDir := _wireRefChartDirValue - chartRepositoryRestHandlerImpl := chartRepo2.NewChartRepositoryRestHandlerImpl(sugaredLogger, userServiceImpl, chartRepositoryServiceImpl, enforcerImpl, validate, deleteServiceImpl, chartRefRepositoryImpl, refChartDir, attributesServiceImpl) + chartRepositoryRestHandlerImpl := chartRepo2.NewChartRepositoryRestHandlerImpl(sugaredLogger, userServiceImpl, chartRepositoryServiceImpl, enforcerImpl, validate, deleteServiceImpl, attributesServiceImpl) chartRepositoryRouterImpl := chartRepo2.NewChartRepositoryRouterImpl(chartRepositoryRestHandlerImpl) appStoreServiceImpl := service.NewAppStoreServiceImpl(sugaredLogger, appStoreApplicationVersionRepositoryImpl) appStoreRestHandlerImpl := appStoreDiscover.NewAppStoreRestHandlerImpl(sugaredLogger, userServiceImpl, appStoreServiceImpl, enforcerImpl) @@ -279,7 +277,7 @@ func InitializeApp() (*App, error) { appStoreValuesRouterImpl := appStoreValues.NewAppStoreValuesRouterImpl(appStoreValuesRestHandlerImpl) chartGroupDeploymentRepositoryImpl := repository8.NewChartGroupDeploymentRepositoryImpl(db, sugaredLogger) clusterInstalledAppsRepositoryImpl := repository4.NewClusterInstalledAppsRepositoryImpl(db, sugaredLogger) - appStoreDeploymentHelmServiceImpl := appStoreDeploymentTool.NewAppStoreDeploymentHelmServiceImpl(sugaredLogger, helmAppServiceImpl, appStoreApplicationVersionRepositoryImpl, helmAppClientImpl, installedAppRepositoryImpl, appStoreDeploymentCommonServiceImpl, ociRegistryConfigRepositoryImpl) + appStoreDeploymentHelmServiceImpl := appStoreDeploymentTool.NewAppStoreDeploymentHelmServiceImpl(sugaredLogger, helmAppServiceImpl, appStoreApplicationVersionRepositoryImpl, helmAppClientImpl, installedAppRepositoryImpl, appStoreDeploymentCommonServiceImpl, ociRegistryConfigRepositoryImpl, gitOperationServiceImpl) installedAppVersionHistoryRepositoryImpl := repository4.NewInstalledAppVersionHistoryRepositoryImpl(sugaredLogger, db) deploymentServiceTypeConfig, err := service3.GetDeploymentServiceTypeConfig() if err != nil { @@ -289,7 +287,7 @@ func InitializeApp() (*App, error) { if err != nil { return nil, err } - appStoreDeploymentServiceImpl := service3.NewAppStoreDeploymentServiceImpl(sugaredLogger, installedAppRepositoryImpl, chartGroupDeploymentRepositoryImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl, clusterInstalledAppsRepositoryImpl, appRepositoryImpl, appStoreDeploymentHelmServiceImpl, appStoreDeploymentHelmServiceImpl, environmentServiceImpl, clusterServiceImpl, helmAppServiceImpl, appStoreDeploymentCommonServiceImpl, installedAppVersionHistoryRepositoryImpl, gitOpsConfigRepositoryImpl, attributesServiceImpl, deploymentServiceTypeConfig, chartTemplateServiceImpl, acdConfig) + appStoreDeploymentServiceImpl := service3.NewAppStoreDeploymentServiceImpl(sugaredLogger, installedAppRepositoryImpl, chartGroupDeploymentRepositoryImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl, clusterInstalledAppsRepositoryImpl, appRepositoryImpl, appStoreDeploymentHelmServiceImpl, appStoreDeploymentHelmServiceImpl, environmentServiceImpl, clusterServiceImpl, helmAppServiceImpl, appStoreDeploymentCommonServiceImpl, installedAppVersionHistoryRepositoryImpl, deploymentServiceTypeConfig, acdConfig, gitOpsConfigReadServiceImpl, gitOperationServiceImpl) appStoreDeploymentRestHandlerImpl := appStoreDeployment.NewAppStoreDeploymentRestHandlerImpl(sugaredLogger, userServiceImpl, enforcerImpl, enforcerUtilImpl, enforcerUtilHelmImpl, appStoreDeploymentServiceImpl, validate, helmAppServiceImpl, appStoreDeploymentCommonServiceImpl, helmUserServiceImpl, attributesServiceImpl) appStoreDeploymentRouterImpl := appStoreDeployment.NewAppStoreDeploymentRouterImpl(appStoreDeploymentRestHandlerImpl) chartProviderServiceImpl := chartProvider.NewChartProviderServiceImpl(sugaredLogger, chartRepoRepositoryImpl, chartRepositoryServiceImpl, dockerArtifactStoreRepositoryImpl, ociRegistryConfigRepositoryImpl) @@ -389,9 +387,3 @@ func InitializeApp() (*App, error) { mainApp := NewApp(db, sessionManager, muxRouter, telemetryEventClientImpl, posthogClient, sugaredLogger) return mainApp, nil } - -var ( - _wireChartWorkingDirValue = util.ChartWorkingDir("/tmp/charts/") - _wireRefChartProxyDirValue = appStoreBean.RefChartProxyDir("scripts/devtron-reference-helm-charts") - _wireRefChartDirValue = chartRepoRepository.RefChartDir("scripts/devtron-reference-helm-charts") -) diff --git a/internal/sql/repository/AppListingRepository.go b/internal/sql/repository/AppListingRepository.go index ecff1f94c22..ac1edd885eb 100644 --- a/internal/sql/repository/AppListingRepository.go +++ b/internal/sql/repository/AppListingRepository.go @@ -181,18 +181,6 @@ func (impl AppListingRepositoryImpl) FetchJobsLastSucceededOn(CiPipelineIDs []in return lastSucceededTimeArray, nil } -func getRequiredAppIdsInSequence(appIds []int) []int { - resIDs := make([]int, 0) - appIdsSet := make(map[int]bool) - for _, appId := range appIds { - if _, ok := appIdsSet[appId]; !ok { - resIDs = append(resIDs, appId) - appIdsSet[appId] = true - } - } - return resIDs -} - func (impl AppListingRepositoryImpl) FetchAppsByEnvironment(appListingFilter helper.AppListingFilter) ([]*bean.AppEnvironmentContainer, error) { impl.Logger.Debug("reached at FetchAppsByEnvironment:") var appEnvArr []*bean.AppEnvironmentContainer @@ -492,19 +480,6 @@ func (impl AppListingRepositoryImpl) FetchAppDetail(ctx context.Context, appId i return appDetailContainer, nil } -func (impl AppListingRepositoryImpl) fetchLinkOutsByAppIdAndEnvId(appId int, envId int) ([]string, error) { - impl.Logger.Debug("reached at AppListingRepository:") - - var linkOuts []string - query := "SELECT ael.link from app_env_linkouts ael where ael.app_id=? and ael.environment_id=?" - impl.Logger.Debugw("lingOut query:", query) - _, err := impl.dbConnection.Query(&linkOuts, query, appId, envId) - if err != nil { - impl.Logger.Errorw("err", err) - } - return linkOuts, err -} - func (impl AppListingRepositoryImpl) PrometheusApiByEnvId(id int) (*string, error) { impl.Logger.Debug("reached at PrometheusApiByEnvId:") var prometheusEndpoint string @@ -663,6 +638,7 @@ func (impl AppListingRepositoryImpl) makeAppStageStatus(stage int, stageName str func (impl AppListingRepositoryImpl) FetchOtherEnvironment(appId int) ([]*bean.Environment, error) { // other environment tab var otherEnvironments []*bean.Environment + //TODO: remove infra metrics from query as it is not being used from here query := `select pcwr.pipeline_id, pcwr.last_deployed, pcwr.latest_cd_workflow_runner_id, pcwr.environment_id, pcwr.deployment_app_delete_request, e.cluster_id, e.environment_name, e.default as prod, e.description, ca.image as last_deployed_image, u.email_id as last_deployed_by, elam.app_metrics, elam.infra_metrics, ap.status as app_status @@ -691,6 +667,7 @@ func (impl AppListingRepositoryImpl) FetchOtherEnvironment(appId int) ([]*bean.E func (impl AppListingRepositoryImpl) FetchMinDetailOtherEnvironment(appId int) ([]*bean.Environment, error) { impl.Logger.Debug("reached at FetchMinDetailOtherEnvironment:") var otherEnvironments []*bean.Environment + //TODO: remove infra metrics from query as it is not being used from here query := `SELECT p.environment_id,env.environment_name,env.description,env.is_virtual_environment, env.cluster_id, env.default as prod, p.deployment_app_delete_request, env_app_m.app_metrics,env_app_m.infra_metrics from (SELECT pl.id,pl.app_id,pl.environment_id,pl.deleted, pl.deployment_app_delete_request from pipeline pl diff --git a/internal/sql/repository/DeploymentTemplateRepository.go b/internal/sql/repository/DeploymentTemplateRepository.go index c96760ece54..c35df61721b 100644 --- a/internal/sql/repository/DeploymentTemplateRepository.go +++ b/internal/sql/repository/DeploymentTemplateRepository.go @@ -16,7 +16,7 @@ const ( ) type DeploymentTemplateComparisonMetadata struct { - ChartId int `json:"chartRefId"` + ChartRefId int `json:"chartRefId"` ChartVersion string `json:"chartVersion,omitempty"` ChartType string `json:"chartType,omitempty"` EnvironmentId int `json:"environmentId,omitempty"` @@ -78,7 +78,7 @@ func (impl DeploymentTemplateRepositoryImpl) FetchLatestDeploymentWithChartRefs( p.id as pipeline_id, p.environment_id, dth.id as deployment_template_history_id, - ceco.chart_id, + c.chart_ref_id, c.chart_version, ROW_NUMBER() OVER (PARTITION BY p.environment_id ORDER BY pco.id DESC) AS row_num FROM @@ -100,7 +100,7 @@ func (impl DeploymentTemplateRepositoryImpl) FetchLatestDeploymentWithChartRefs( rr.pipeline_id, rr.environment_id, rr.deployment_template_history_id, - rr.chart_id, + rr.chart_ref_id, rr.chart_version, e.environment_name FROM diff --git a/internal/sql/repository/GitOpsConfigRepository.go b/internal/sql/repository/GitOpsConfigRepository.go index 557cfaf488f..8e682f5bbfb 100644 --- a/internal/sql/repository/GitOpsConfigRepository.go +++ b/internal/sql/repository/GitOpsConfigRepository.go @@ -32,7 +32,6 @@ type GitOpsConfigRepository interface { GetGitOpsConfigActive() (*GitOpsConfig, error) GetConnection() *pg.DB GetEmailIdFromActiveGitOpsConfig() (string, error) - IsGitOpsConfigured() (bool, error) } type GitOpsConfigRepositoryImpl struct { @@ -109,15 +108,3 @@ func (impl *GitOpsConfigRepositoryImpl) GetEmailIdFromActiveGitOpsConfig() (stri Where("active = ?", true).Select(&emailId) return emailId, err } - -func (impl *GitOpsConfigRepositoryImpl) IsGitOpsConfigured() (bool, error) { - gitOpsConfig, err := impl.GetGitOpsConfigActive() - if err != nil && err != pg.ErrNoRows { - impl.logger.Errorw("Error while getting git-ops config from DB to check if git-ops configured or not", "err", err) - return false, err - } - if gitOpsConfig != nil && gitOpsConfig.Id > 0 { - return true, nil - } - return false, nil -} diff --git a/internal/sql/repository/mocks/AppLevelMetricsRepository.go b/internal/sql/repository/mocks/AppLevelMetricsRepository.go index 4254e307651..8e1a77c8e11 100644 --- a/internal/sql/repository/mocks/AppLevelMetricsRepository.go +++ b/internal/sql/repository/mocks/AppLevelMetricsRepository.go @@ -3,7 +3,7 @@ package mocks import ( - repository "github.com/devtron-labs/devtron/internal/sql/repository" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deployedAppMetrics/repository" mock "github.com/stretchr/testify/mock" ) diff --git a/internal/sql/repository/mocks/EnvLevelAppMetricsRepository.go b/internal/sql/repository/mocks/EnvLevelAppMetricsRepository.go index 1037a5fd94f..6561e22c686 100644 --- a/internal/sql/repository/mocks/EnvLevelAppMetricsRepository.go +++ b/internal/sql/repository/mocks/EnvLevelAppMetricsRepository.go @@ -3,7 +3,7 @@ package mocks import ( - repository "github.com/devtron-labs/devtron/internal/sql/repository" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deployedAppMetrics/repository" mock "github.com/stretchr/testify/mock" ) diff --git a/internal/util/ChartDeploymentService.go b/internal/util/ChartDeploymentService.go deleted file mode 100644 index 53dd03deb19..00000000000 --- a/internal/util/ChartDeploymentService.go +++ /dev/null @@ -1,38 +0,0 @@ -package util - -import ( - "context" - repository3 "github.com/argoproj/argo-cd/v2/pkg/apiclient/repository" - "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" - repository4 "github.com/devtron-labs/devtron/client/argocdServer/repository" - "go.uber.org/zap" -) - -type ChartDeploymentService interface { - RegisterInArgo(chartGitAttribute *ChartGitAttribute, ctx context.Context) error -} - -type ChartDeploymentServiceImpl struct { - logger *zap.SugaredLogger - repositoryService repository4.ServiceClient -} - -func NewChartDeploymentServiceImpl(logger *zap.SugaredLogger, repositoryService repository4.ServiceClient) *ChartDeploymentServiceImpl { - return &ChartDeploymentServiceImpl{ - logger: logger, - repositoryService: repositoryService, - } -} - -func (impl *ChartDeploymentServiceImpl) RegisterInArgo(chartGitAttribute *ChartGitAttribute, ctx context.Context) error { - repo := &v1alpha1.Repository{ - Repo: chartGitAttribute.RepoUrl, - } - repo, err := impl.repositoryService.Create(ctx, &repository3.RepoCreateRequest{Repo: repo, Upsert: true}) - if err != nil { - impl.logger.Errorw("error in creating argo Repository ", "err", err) - return err - } - impl.logger.Infow("repo registered in argo", "name", chartGitAttribute.RepoUrl) - return err -} diff --git a/internal/util/ChartService.go b/internal/util/ChartService.go deleted file mode 100644 index cea74c92a5a..00000000000 --- a/internal/util/ChartService.go +++ /dev/null @@ -1,823 +0,0 @@ -/* - * Copyright (c) 2020 Devtron Labs - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package util - -import ( - "compress/gzip" - "context" - "fmt" - "io/ioutil" - "math/rand" - "net/http" - "os" - "path/filepath" - "regexp" - "strconv" - "strings" - "time" - - dockerRegistryRepository "github.com/devtron-labs/devtron/internal/sql/repository/dockerRegistry" - repository2 "github.com/devtron-labs/devtron/pkg/auth/user/repository" - - "github.com/devtron-labs/devtron/api/bean" - "github.com/devtron-labs/devtron/internal/sql/repository" - appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" - chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository" - "github.com/devtron-labs/devtron/util" - "github.com/go-pg/pg" - dirCopy "github.com/otiai10/copy" - "go.opentelemetry.io/otel" - "go.uber.org/zap" - "k8s.io/helm/pkg/chartutil" - "k8s.io/helm/pkg/proto/hapi/chart" - "sigs.k8s.io/yaml" -) - -type ChartWorkingDir string - -const PIPELINE_DEPLOYMENT_TYPE_ACD string = "argo_cd" -const PIPELINE_DEPLOYMENT_TYPE_HELM string = "helm" -const PIPELINE_DEPLOYMENT_TYPE_MANIFEST_DOWNLOAD string = "manifest_download" - -type ChartCreateRequest struct { - ChartMetaData *chart.Metadata - ChartPath string -} - -type ChartCreateResponse struct { - BuiltChartPath string - valuesYaml string -} - -type ChartTemplateService interface { - FetchValuesFromReferenceChart(chartMetaData *chart.Metadata, refChartLocation string, templateName string, userId int32, pipelineStrategyPath string) (*ChartValues, *ChartGitAttribute, error) - GetChartVersion(location string) (string, error) - CreateChartProxy(chartMetaData *chart.Metadata, refChartLocation string, envName string, installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (string, *ChartGitAttribute, error) - BuildChart(ctx context.Context, chartMetaData *chart.Metadata, referenceTemplatePath string) (string, error) - BuildChartProxyForHelmApps(chartCreateRequest *ChartCreateRequest) (chartCreateResponse *ChartCreateResponse, err error) - GitPull(clonedDir string, repoUrl string, appStoreName string) error - GetDir() string - CleanDir(dir string) - GetUserEmailIdAndNameForGitOpsCommit(userId int32) (emailId, name string) - GetGitOpsRepoName(appName string) string - GetGitOpsRepoNameFromUrl(gitRepoUrl string) string - CreateGitRepositoryForApp(gitOpsRepoName, baseTemplateName, version string, userId int32) (chartGitAttribute *ChartGitAttribute, err error) - PushChartToGitRepo(gitOpsRepoName, referenceTemplate, version, tempReferenceTemplateDir string, repoUrl string, userId int32) (err error) - GetByteArrayRefChart(chartMetaData *chart.Metadata, referenceTemplatePath string) ([]byte, error) - CreateReadmeInGitRepo(gitOpsRepoName string, userId int32) error - UpdateGitRepoUrlInCharts(appId int, chartGitAttribute *ChartGitAttribute, userId int32) error - CreateAndPushToGitChartProxy(appStoreName, tmpChartLocation string, envName string, installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (chartGitAttribute *ChartGitAttribute, err error) - LoadChartInBytes(ChartPath string, deleteChart bool) ([]byte, error) - LoadChartFromDir(dir string) (*chart.Chart, error) - CreateZipFileForChart(chart *chart.Chart, outputChartPathDir string) ([]byte, error) -} -type ChartTemplateServiceImpl struct { - randSource rand.Source - logger *zap.SugaredLogger - chartWorkingDir ChartWorkingDir - gitFactory *GitFactory - client *http.Client - globalEnvVariables *util.GlobalEnvVariables - gitOpsConfigRepository repository.GitOpsConfigRepository - userRepository repository2.UserRepository - chartRepository chartRepoRepository.ChartRepository -} - -type ChartValues struct { - Values string `json:"values"` //yaml - AppOverrides string `json:"appOverrides"` //json - EnvOverrides string `json:"envOverrides"` //json - ReleaseOverrides string `json:"releaseOverrides"` //json - PipelineOverrides string `json:"pipelineOverrides"` //json - ImageDescriptorTemplate string `json:"-"` -} - -func NewChartTemplateServiceImpl(logger *zap.SugaredLogger, - chartWorkingDir ChartWorkingDir, - client *http.Client, - gitFactory *GitFactory, globalEnvVariables *util.GlobalEnvVariables, - gitOpsConfigRepository repository.GitOpsConfigRepository, - userRepository repository2.UserRepository, chartRepository chartRepoRepository.ChartRepository) *ChartTemplateServiceImpl { - return &ChartTemplateServiceImpl{ - randSource: rand.NewSource(time.Now().UnixNano()), - logger: logger, - chartWorkingDir: chartWorkingDir, - client: client, - gitFactory: gitFactory, - globalEnvVariables: globalEnvVariables, - gitOpsConfigRepository: gitOpsConfigRepository, - userRepository: userRepository, - chartRepository: chartRepository, - } -} - -func (impl ChartTemplateServiceImpl) GetChartVersion(location string) (string, error) { - if fi, err := os.Stat(location); err != nil { - return "", err - } else if !fi.IsDir() { - return "", fmt.Errorf("%q is not a directory", location) - } - - chartYaml := filepath.Join(location, "Chart.yaml") - if _, err := os.Stat(chartYaml); os.IsNotExist(err) { - return "", fmt.Errorf("Chart.yaml file not present in the directory %q", location) - } - //chartYaml = filepath.Join(chartYaml,filepath.Clean(chartYaml)) - chartYamlContent, err := ioutil.ReadFile(filepath.Clean(chartYaml)) - if err != nil { - return "", fmt.Errorf("cannot read Chart.Yaml in directory %q", location) - } - - chartContent, err := chartutil.UnmarshalChartfile(chartYamlContent) - if err != nil { - return "", fmt.Errorf("cannot read Chart.Yaml in directory %q", location) - } - - return chartContent.Version, nil -} - -func (impl ChartTemplateServiceImpl) FetchValuesFromReferenceChart(chartMetaData *chart.Metadata, refChartLocation string, templateName string, userId int32, pipelineStrategyPath string) (*ChartValues, *ChartGitAttribute, error) { - chartMetaData.ApiVersion = "v1" // ensure always v1 - dir := impl.GetDir() - chartDir := filepath.Join(string(impl.chartWorkingDir), dir) - impl.logger.Debugw("chart dir ", "chart", chartMetaData.Name, "dir", chartDir) - err := os.MkdirAll(chartDir, os.ModePerm) //hack for concurrency handling - if err != nil { - impl.logger.Errorw("err in creating dir", "dir", chartDir, "err", err) - return nil, nil, err - } - - defer impl.CleanDir(chartDir) - err = dirCopy.Copy(refChartLocation, chartDir) - - if err != nil { - impl.logger.Errorw("error in copying chart for app", "app", chartMetaData.Name, "error", err) - return nil, nil, err - } - archivePath, valuesYaml, err := impl.packageChart(chartDir, chartMetaData) - if err != nil { - impl.logger.Errorw("error in creating archive", "err", err) - return nil, nil, err - } - values, err := impl.getValues(chartDir, pipelineStrategyPath) - if err != nil { - impl.logger.Errorw("error in pushing chart", "path", archivePath, "err", err) - return nil, nil, err - } - values.Values = valuesYaml - descriptor, err := ioutil.ReadFile(filepath.Clean(filepath.Join(chartDir, ".image_descriptor_template.json"))) - if err != nil { - impl.logger.Errorw("error in reading descriptor", "path", chartDir, "err", err) - return nil, nil, err - } - values.ImageDescriptorTemplate = string(descriptor) - chartGitAttr := &ChartGitAttribute{} - return values, chartGitAttr, nil -} - -// TODO: convert BuildChart and BuildChartProxyForHelmApps into one function -func (impl ChartTemplateServiceImpl) BuildChart(ctx context.Context, chartMetaData *chart.Metadata, referenceTemplatePath string) (string, error) { - chartMetaData.ApiVersion = "v1" // ensure always v1 - dir := impl.GetDir() - tempReferenceTemplateDir := filepath.Join(string(impl.chartWorkingDir), dir) - impl.logger.Debugw("chart dir ", "chart", chartMetaData.Name, "dir", tempReferenceTemplateDir) - err := os.MkdirAll(tempReferenceTemplateDir, os.ModePerm) //hack for concurrency handling - if err != nil { - impl.logger.Errorw("err in creating dir", "dir", tempReferenceTemplateDir, "err", err) - return "", err - } - err = dirCopy.Copy(referenceTemplatePath, tempReferenceTemplateDir) - - if err != nil { - impl.logger.Errorw("error in copying chart for app", "app", chartMetaData.Name, "error", err) - return "", err - } - _, span := otel.Tracer("orchestrator").Start(ctx, "impl.packageChart") - _, _, err = impl.packageChart(tempReferenceTemplateDir, chartMetaData) - span.End() - if err != nil { - impl.logger.Errorw("error in creating archive", "err", err) - return "", err - } - return tempReferenceTemplateDir, nil -} - -func (impl ChartTemplateServiceImpl) BuildChartProxyForHelmApps(chartCreateRequest *ChartCreateRequest) (*ChartCreateResponse, error) { - chartCreateResponse := &ChartCreateResponse{} - chartMetaData := chartCreateRequest.ChartMetaData - chartMetaData.ApiVersion = "v2" // ensure always v2 - dir := impl.GetDir() - chartDir := filepath.Join(string(impl.chartWorkingDir), dir) - impl.logger.Debugw("chart dir ", "chart", chartMetaData.Name, "dir", chartDir) - err := os.MkdirAll(chartDir, os.ModePerm) //hack for concurrency handling - if err != nil { - impl.logger.Errorw("err in creating dir", "dir", chartDir, "err", err) - return chartCreateResponse, err - } - err = dirCopy.Copy(chartCreateRequest.ChartPath, chartDir) - - if err != nil { - impl.logger.Errorw("error in copying chart for app", "app", chartMetaData.Name, "error", err) - return chartCreateResponse, err - } - _, valuesYaml, err := impl.packageChart(chartDir, chartMetaData) - if err != nil { - impl.logger.Errorw("error in creating archive", "err", err) - return chartCreateResponse, err - } - chartCreateResponse.valuesYaml = valuesYaml - chartCreateResponse.BuiltChartPath = chartDir - return chartCreateResponse, nil -} - -type ChartGitAttribute struct { - RepoUrl, ChartLocation string -} - -func (impl ChartTemplateServiceImpl) CreateGitRepositoryForApp(gitOpsRepoName, baseTemplateName, version string, userId int32) (chartGitAttribute *ChartGitAttribute, err error) { - //baseTemplateName replace whitespace - space := regexp.MustCompile(`\s+`) - gitOpsRepoName = space.ReplaceAllString(gitOpsRepoName, "-") - - gitOpsConfigBitbucket, err := impl.gitOpsConfigRepository.GetGitOpsConfigByProvider(BITBUCKET_PROVIDER) - if err != nil { - if err == pg.ErrNoRows { - gitOpsConfigBitbucket.BitBucketWorkspaceId = "" - } else { - return nil, err - } - } - //getting user name & emailId for commit author data - userEmailId, userName := impl.GetUserEmailIdAndNameForGitOpsCommit(userId) - gitRepoRequest := &bean.GitOpsConfigDto{ - GitRepoName: gitOpsRepoName, - Description: fmt.Sprintf("helm chart for " + gitOpsRepoName), - Username: userName, - UserEmailId: userEmailId, - BitBucketWorkspaceId: gitOpsConfigBitbucket.BitBucketWorkspaceId, - BitBucketProjectKey: gitOpsConfigBitbucket.BitBucketProjectKey, - } - repoUrl, _, detailedError := impl.gitFactory.Client.CreateRepository(gitRepoRequest) - for _, err := range detailedError.StageErrorMap { - if err != nil { - impl.logger.Errorw("error in creating git project", "name", gitOpsRepoName, "err", err) - return nil, err - } - } - return &ChartGitAttribute{RepoUrl: repoUrl, ChartLocation: filepath.Join(baseTemplateName, version)}, nil -} - -func (impl ChartTemplateServiceImpl) PushChartToGitRepo(gitOpsRepoName, referenceTemplate, version, tempReferenceTemplateDir string, repoUrl string, userId int32) (err error) { - chartDir := fmt.Sprintf("%s-%s", gitOpsRepoName, impl.GetDir()) - clonedDir := impl.gitFactory.GitService.GetCloneDirectory(chartDir) - if _, err := os.Stat(clonedDir); os.IsNotExist(err) { - clonedDir, err = impl.gitFactory.GitService.Clone(repoUrl, chartDir) - if err != nil { - impl.logger.Errorw("error in cloning repo", "url", repoUrl, "err", err) - return err - } - } else { - err = impl.GitPull(clonedDir, repoUrl, gitOpsRepoName) - if err != nil { - impl.logger.Errorw("error in pulling git repo", "url", repoUrl, "err", err) - return err - } - } - - dir := filepath.Join(clonedDir, referenceTemplate, version) - pushChartToGit := true - - //if chart already exists don't overrides it by reference template - if _, err := os.Stat(dir); os.IsNotExist(err) { - err = os.MkdirAll(dir, os.ModePerm) - if err != nil { - impl.logger.Errorw("error in making dir", "err", err) - return err - } - err = dirCopy.Copy(tempReferenceTemplateDir, dir) - if err != nil { - impl.logger.Errorw("error copying dir", "err", err) - return err - } - } else { - // auto-healing : data corruption fix - sometimes reference chart contents are not pushed in git-ops repo. - // copying content from reference template dir to cloned dir (if Chart.yaml file is not found) - // if Chart.yaml file is not found, we are assuming here that reference chart contents are not pushed in git-ops repo - if _, err := os.Stat(filepath.Join(dir, "Chart.yaml")); os.IsNotExist(err) { - impl.logger.Infow("auto-healing: Chart.yaml not found in cloned repo from git-ops. copying content", "from", tempReferenceTemplateDir, "to", dir) - err = dirCopy.Copy(tempReferenceTemplateDir, dir) - if err != nil { - impl.logger.Errorw("error copying content in auto-healing", "err", err) - return err - } - } else { - // chart exists on git, hence not performing first commit - pushChartToGit = false - } - } - - // if push needed, then only push - if pushChartToGit { - userEmailId, userName := impl.GetUserEmailIdAndNameForGitOpsCommit(userId) - commit, err := impl.gitFactory.GitService.CommitAndPushAllChanges(clonedDir, "first commit", userName, userEmailId) - if err != nil { - impl.logger.Errorw("error in pushing git", "err", err) - impl.logger.Warn("re-trying, taking pull and then push again") - err = impl.GitPull(clonedDir, repoUrl, gitOpsRepoName) - if err != nil { - return err - } - err = dirCopy.Copy(tempReferenceTemplateDir, dir) - if err != nil { - impl.logger.Errorw("error copying dir", "err", err) - return err - } - commit, err = impl.gitFactory.GitService.CommitAndPushAllChanges(clonedDir, "first commit", userName, userEmailId) - if err != nil { - impl.logger.Errorw("error in pushing git", "err", err) - return err - } - } - impl.logger.Debugw("template committed", "url", repoUrl, "commit", commit) - } - - defer impl.CleanDir(clonedDir) - return nil -} - -func (impl ChartTemplateServiceImpl) getValues(directory, pipelineStrategyPath string) (values *ChartValues, err error) { - - if fi, err := os.Stat(directory); err != nil { - return nil, err - } else if !fi.IsDir() { - return nil, fmt.Errorf("%q is not a directory", directory) - } - - files, err := ioutil.ReadDir(directory) - if err != nil { - impl.logger.Errorw("failed reading directory", "err", err) - return nil, fmt.Errorf(" Couldn't read the %q", directory) - } - - var appOverrideByte, envOverrideByte, releaseOverrideByte, pipelineOverrideByte []byte - - for _, file := range files { - if !file.IsDir() { - name := strings.ToLower(file.Name()) - if name == "app-values.yaml" || name == "app-values.yml" { - appOverrideByte, err = ioutil.ReadFile(filepath.Clean(filepath.Join(directory, file.Name()))) - if err != nil { - impl.logger.Errorw("failed reading data from file", "err", err) - } else { - appOverrideByte, err = yaml.YAMLToJSON(appOverrideByte) - if err != nil { - return nil, err - } - } - } - if name == "env-values.yaml" || name == "env-values.yml" { - envOverrideByte, err = ioutil.ReadFile(filepath.Clean(filepath.Join(directory, file.Name()))) - if err != nil { - impl.logger.Errorw("failed reading data from file", "err", err) - } else { - envOverrideByte, err = yaml.YAMLToJSON(envOverrideByte) - if err != nil { - return nil, err - } - } - } - if name == "release-values.yaml" || name == "release-values.yml" { - releaseOverrideByte, err = ioutil.ReadFile(filepath.Clean(filepath.Join(directory, file.Name()))) - if err != nil { - impl.logger.Errorw("failed reading data from file", "err", err) - } else { - releaseOverrideByte, err = yaml.YAMLToJSON(releaseOverrideByte) - if err != nil { - return nil, err - } - } - } - } - } - pipelineOverrideByte, err = ioutil.ReadFile(filepath.Clean(filepath.Join(directory, pipelineStrategyPath))) - if err != nil { - impl.logger.Errorw("failed reading data from file", "err", err) - } else { - pipelineOverrideByte, err = yaml.YAMLToJSON(pipelineOverrideByte) - if err != nil { - return nil, err - } - } - - val := &ChartValues{ - AppOverrides: string(appOverrideByte), - EnvOverrides: string(envOverrideByte), - ReleaseOverrides: string(releaseOverrideByte), - PipelineOverrides: string(pipelineOverrideByte), - } - return val, nil - -} - -func (impl ChartTemplateServiceImpl) packageChart(tempReferenceTemplateDir string, chartMetaData *chart.Metadata) (*string, string, error) { - valid, err := chartutil.IsChartDir(tempReferenceTemplateDir) - if err != nil { - impl.logger.Errorw("error in validating base chart", "dir", tempReferenceTemplateDir, "err", err) - return nil, "", err - } - if !valid { - impl.logger.Errorw("invalid chart at ", "dir", tempReferenceTemplateDir) - return nil, "", fmt.Errorf("invalid base chart") - } - - b, err := yaml.Marshal(chartMetaData) - if err != nil { - impl.logger.Errorw("error in marshaling chartMetadata", "err", err) - return nil, "", err - } - err = ioutil.WriteFile(filepath.Join(tempReferenceTemplateDir, "Chart.yaml"), b, 0600) - if err != nil { - impl.logger.Errorw("err in writing Chart.yaml", "err", err) - return nil, "", err - } - chart, err := chartutil.LoadDir(tempReferenceTemplateDir) - if err != nil { - impl.logger.Errorw("error in loading chart dir", "err", err, "dir", tempReferenceTemplateDir) - return nil, "", err - } - - archivePath, err := chartutil.Save(chart, tempReferenceTemplateDir) - if err != nil { - impl.logger.Errorw("error in saving", "err", err, "dir", tempReferenceTemplateDir) - return nil, "", err - } - impl.logger.Debugw("chart archive path", "path", archivePath) - var valuesYaml string - if chart.Values != nil { - valuesYaml = chart.Values.Raw - } else { - impl.logger.Warnw("values.yaml not found in helm chart", "dir", tempReferenceTemplateDir) - } - return &archivePath, valuesYaml, nil -} - -func (impl ChartTemplateServiceImpl) CleanDir(dir string) { - err := os.RemoveAll(dir) - if err != nil { - impl.logger.Warnw("error in deleting dir ", "dir", dir) - } -} - -func (impl ChartTemplateServiceImpl) GetDir() string { - /* #nosec */ - r1 := rand.New(impl.randSource).Int63() - return strconv.FormatInt(r1, 10) -} - -func (impl ChartTemplateServiceImpl) CreateChartProxy(chartMetaData *chart.Metadata, refChartLocation string, envName string, installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (string, *ChartGitAttribute, error) { - chartMetaData.ApiVersion = "v2" // ensure always v2 - dir := impl.GetDir() - chartDir := filepath.Join(string(impl.chartWorkingDir), dir) - impl.logger.Debugw("chart dir ", "chart", chartMetaData.Name, "dir", chartDir) - err := os.MkdirAll(chartDir, os.ModePerm) //hack for concurrency handling - if err != nil { - impl.logger.Errorw("err in creating dir", "dir", chartDir, "err", err) - return "", nil, err - } - defer impl.CleanDir(chartDir) - err = dirCopy.Copy(refChartLocation, chartDir) - - if err != nil { - impl.logger.Errorw("error in copying chart for app", "app", chartMetaData.Name, "error", err) - return "", nil, err - } - archivePath, valuesYaml, err := impl.packageChart(chartDir, chartMetaData) - if err != nil { - impl.logger.Errorw("error in creating archive", "err", err) - return "", nil, err - } - - chartGitAttr, err := impl.CreateAndPushToGitChartProxy(chartMetaData.Name, chartDir, envName, installAppVersionRequest) - if err != nil { - impl.logger.Errorw("error in pushing chart to git ", "path", archivePath, "err", err) - return "", nil, err - } - if valuesYaml == "" { - valuesYaml = "{}" - } else { - valuesYamlByte, err := yaml.YAMLToJSON([]byte(valuesYaml)) - if err != nil { - return "", nil, err - } - valuesYaml = string(valuesYamlByte) - } - return valuesYaml, chartGitAttr, nil -} - -func (impl ChartTemplateServiceImpl) CreateAndPushToGitChartProxy(appStoreName, tmpChartLocation string, envName string, installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (chartGitAttribute *ChartGitAttribute, err error) { - //baseTemplateName replace whitespace - space := regexp.MustCompile(`\s+`) - appStoreName = space.ReplaceAllString(appStoreName, "-") - - if len(installAppVersionRequest.GitOpsRepoName) == 0 { - //here git ops repo will be the app name, to breaking the mono repo structure - gitOpsRepoName := impl.GetGitOpsRepoName(installAppVersionRequest.AppName) - installAppVersionRequest.GitOpsRepoName = gitOpsRepoName - } - gitOpsConfigBitbucket, err := impl.gitOpsConfigRepository.GetGitOpsConfigByProvider(BITBUCKET_PROVIDER) - if err != nil { - if err == pg.ErrNoRows { - gitOpsConfigBitbucket.BitBucketWorkspaceId = "" - } else { - return nil, err - } - } - //getting user name & emailId for commit author data - userEmailId, userName := impl.GetUserEmailIdAndNameForGitOpsCommit(installAppVersionRequest.UserId) - gitRepoRequest := &bean.GitOpsConfigDto{ - GitRepoName: installAppVersionRequest.GitOpsRepoName, - Description: "helm chart for " + installAppVersionRequest.GitOpsRepoName, - Username: userName, - UserEmailId: userEmailId, - BitBucketWorkspaceId: gitOpsConfigBitbucket.BitBucketWorkspaceId, - BitBucketProjectKey: gitOpsConfigBitbucket.BitBucketProjectKey, - } - repoUrl, _, detailedError := impl.gitFactory.Client.CreateRepository(gitRepoRequest) - for _, err := range detailedError.StageErrorMap { - if err != nil { - impl.logger.Errorw("error in creating git project", "name", installAppVersionRequest.GitOpsRepoName, "err", err) - return nil, err - } - } - - chartDir := fmt.Sprintf("%s-%s", installAppVersionRequest.AppName, impl.GetDir()) - clonedDir := impl.gitFactory.GitService.GetCloneDirectory(chartDir) - if _, err := os.Stat(clonedDir); os.IsNotExist(err) { - clonedDir, err = impl.gitFactory.GitService.Clone(repoUrl, chartDir) - if err != nil { - impl.logger.Errorw("error in cloning repo", "url", repoUrl, "err", err) - return nil, err - } - } else { - err = impl.GitPull(clonedDir, repoUrl, appStoreName) - if err != nil { - return nil, err - } - } - - acdAppName := fmt.Sprintf("%s-%s", installAppVersionRequest.AppName, envName) - dir := filepath.Join(clonedDir, acdAppName) - err = os.MkdirAll(dir, os.ModePerm) - if err != nil { - impl.logger.Errorw("error in making dir", "err", err) - return nil, err - } - err = dirCopy.Copy(tmpChartLocation, dir) - if err != nil { - impl.logger.Errorw("error copying dir", "err", err) - return nil, err - } - commit, err := impl.gitFactory.GitService.CommitAndPushAllChanges(clonedDir, "first commit", userName, userEmailId) - if err != nil { - impl.logger.Errorw("error in pushing git", "err", err) - impl.logger.Warn("re-trying, taking pull and then push again") - err = impl.GitPull(clonedDir, repoUrl, acdAppName) - if err != nil { - return nil, err - } - err = dirCopy.Copy(tmpChartLocation, dir) - if err != nil { - impl.logger.Errorw("error copying dir", "err", err) - return nil, err - } - commit, err = impl.gitFactory.GitService.CommitAndPushAllChanges(clonedDir, "first commit", userName, userEmailId) - if err != nil { - impl.logger.Errorw("error in pushing git", "err", err) - return nil, err - } - } - impl.logger.Debugw("template committed", "url", repoUrl, "commit", commit) - defer impl.CleanDir(clonedDir) - return &ChartGitAttribute{RepoUrl: repoUrl, ChartLocation: filepath.Join("", acdAppName)}, nil -} - -func (impl ChartTemplateServiceImpl) GitPull(clonedDir string, repoUrl string, appStoreName string) error { - err := impl.gitFactory.GitService.Pull(clonedDir) //TODO check for local repo exists before clone - if err != nil { - impl.logger.Errorw("error in pulling git", "clonedDir", clonedDir, "err", err) - _, err := impl.gitFactory.GitService.Clone(repoUrl, appStoreName) - if err != nil { - impl.logger.Errorw("error in cloning repo", "url", repoUrl, "err", err) - return err - } - return nil - } - return nil -} - -func (impl *ChartTemplateServiceImpl) GetUserEmailIdAndNameForGitOpsCommit(userId int32) (string, string) { - emailId := "devtron-bot@devtron.ai" - name := "devtron bot" - //getting emailId associated with user - userDetail, _ := impl.userRepository.GetById(userId) - if userDetail != nil && userDetail.EmailId != "admin" && userDetail.EmailId != "system" && len(userDetail.EmailId) > 0 { - emailId = userDetail.EmailId - } else { - emailIdGitOps, err := impl.gitOpsConfigRepository.GetEmailIdFromActiveGitOpsConfig() - if err != nil { - impl.logger.Errorw("error in getting emailId from active gitOps config", "err", err) - } else if len(emailIdGitOps) > 0 { - emailId = emailIdGitOps - } - } - //we are getting name from emailId(replacing special characters in with space) - emailComponents := strings.Split(emailId, "@") - regex, _ := regexp.Compile(`[^\w]`) - if regex != nil { - name = regex.ReplaceAllString(emailComponents[0], " ") - } - return emailId, name -} - -func (impl ChartTemplateServiceImpl) GetGitOpsRepoName(appName string) string { - var repoName string - if len(impl.globalEnvVariables.GitOpsRepoPrefix) == 0 { - repoName = appName - } else { - repoName = fmt.Sprintf("%s-%s", impl.globalEnvVariables.GitOpsRepoPrefix, appName) - } - return repoName -} - -func (impl ChartTemplateServiceImpl) GetGitOpsRepoNameFromUrl(gitRepoUrl string) string { - gitRepoUrl = gitRepoUrl[strings.LastIndex(gitRepoUrl, "/")+1:] - gitRepoUrl = strings.ReplaceAll(gitRepoUrl, ".git", "") - return gitRepoUrl -} - -// GetByteArrayRefChart this method will be used for getting byte array from reference chart to store in db -func (impl ChartTemplateServiceImpl) GetByteArrayRefChart(chartMetaData *chart.Metadata, referenceTemplatePath string) ([]byte, error) { - chartMetaData.ApiVersion = "v1" // ensure always v1 - dir := impl.GetDir() - tempReferenceTemplateDir := filepath.Join(string(impl.chartWorkingDir), dir) - impl.logger.Debugw("chart dir ", "chart", chartMetaData.Name, "dir", tempReferenceTemplateDir) - err := os.MkdirAll(tempReferenceTemplateDir, os.ModePerm) //hack for concurrency handling - if err != nil { - impl.logger.Errorw("err in creating dir", "dir", tempReferenceTemplateDir, "err", err) - return nil, err - } - defer impl.CleanDir(tempReferenceTemplateDir) - err = dirCopy.Copy(referenceTemplatePath, tempReferenceTemplateDir) - if err != nil { - impl.logger.Errorw("error in copying chart for app", "app", chartMetaData.Name, "error", err) - return nil, err - } - activePath, _, err := impl.packageChart(tempReferenceTemplateDir, chartMetaData) - if err != nil { - impl.logger.Errorw("error in creating archive", "err", err) - return nil, err - } - file, err := os.Open(*activePath) - reader, err := gzip.NewReader(file) - if err != nil { - impl.logger.Errorw("There is a problem with os.Open", "err", err) - return nil, err - } - // read the complete content of the file h.Name into the bs []byte - bs, err := ioutil.ReadAll(reader) - if err != nil { - impl.logger.Errorw("There is a problem with readAll", "err", err) - return nil, err - } - return bs, nil -} - -func (impl ChartTemplateServiceImpl) CreateReadmeInGitRepo(gitOpsRepoName string, userId int32) error { - userEmailId, userName := impl.GetUserEmailIdAndNameForGitOpsCommit(userId) - gitOpsConfig, err := impl.gitOpsConfigRepository.GetGitOpsConfigActive() - config := &bean.GitOpsConfigDto{ - Username: userName, - UserEmailId: userEmailId, - GitRepoName: gitOpsRepoName, - BitBucketWorkspaceId: gitOpsConfig.BitBucketWorkspaceId, - } - _, err = impl.gitFactory.Client.CreateReadme(config) - if err != nil { - return err - } - return nil -} - -func (impl ChartTemplateServiceImpl) UpdateGitRepoUrlInCharts(appId int, chartGitAttribute *ChartGitAttribute, userId int32) error { - charts, err := impl.chartRepository.FindActiveChartsByAppId(appId) - if err != nil && pg.ErrNoRows != err { - return err - } - for _, ch := range charts { - if len(ch.GitRepoUrl) == 0 { - ch.GitRepoUrl = chartGitAttribute.RepoUrl - ch.ChartLocation = chartGitAttribute.ChartLocation - ch.UpdatedOn = time.Now() - ch.UpdatedBy = userId - err = impl.chartRepository.Update(ch) - if err != nil { - return err - } - } - } - return nil -} - -func (impl ChartTemplateServiceImpl) LoadChartInBytes(ChartPath string, deleteChart bool) ([]byte, error) { - - var chartBytesArr []byte - //this function is removed in latest helm release and is replaced by Loader in loader package - chart, err := chartutil.LoadDir(ChartPath) - if err != nil { - impl.logger.Errorw("error in loading chart dir", "err", err, "dir") - return chartBytesArr, err - } - chartBytesArr, err = impl.CreateZipFileForChart(chart, ChartPath) - if err != nil { - impl.logger.Errorw("error in saving", "err", err, "dir") - return chartBytesArr, err - } - - if deleteChart { - defer impl.CleanDir(ChartPath) - } - - return chartBytesArr, err -} - -func (impl ChartTemplateServiceImpl) LoadChartFromDir(dir string) (*chart.Chart, error) { - //this function is removed in latest helm release and is replaced by Loader in loader package - chart, err := chartutil.LoadDir(dir) - if err != nil { - impl.logger.Errorw("error in loading chart dir", "err", err, "dir") - return chart, err - } - return chart, nil -} - -func (impl ChartTemplateServiceImpl) CreateZipFileForChart(chart *chart.Chart, outputChartPathDir string) ([]byte, error) { - var chartBytesArr []byte - chartZipPath, err := chartutil.Save(chart, outputChartPathDir) - if err != nil { - impl.logger.Errorw("error in saving", "err", err, "dir") - return chartBytesArr, err - } - - chartBytesArr, err = ioutil.ReadFile(chartZipPath) - if err != nil { - impl.logger.Errorw("There is a problem with os.Open", "err", err) - return nil, err - } - return chartBytesArr, nil -} - -func IsHelmApp(deploymentAppType string) bool { - return deploymentAppType == PIPELINE_DEPLOYMENT_TYPE_HELM -} - -func IsAcdApp(deploymentAppType string) bool { - return deploymentAppType == PIPELINE_DEPLOYMENT_TYPE_ACD -} - -func IsManifestDownload(deploymentAppType string) bool { - return deploymentAppType == PIPELINE_DEPLOYMENT_TYPE_MANIFEST_DOWNLOAD -} - -func IsOCIRegistryChartProvider(ociRegistry dockerRegistryRepository.DockerArtifactStore) bool { - if ociRegistry.OCIRegistryConfig == nil || - len(ociRegistry.OCIRegistryConfig) != 1 || - !IsOCIConfigChartProvider(ociRegistry.OCIRegistryConfig[0]) { - return false - } - return true -} - -func IsOCIConfigChartProvider(ociRegistryConfig *dockerRegistryRepository.OCIRegistryConfig) bool { - if ociRegistryConfig.RepositoryType == dockerRegistryRepository.OCI_REGISRTY_REPO_TYPE_CHART && - (ociRegistryConfig.RepositoryAction == dockerRegistryRepository.STORAGE_ACTION_TYPE_PULL || - ociRegistryConfig.RepositoryAction == dockerRegistryRepository.STORAGE_ACTION_TYPE_PULL_AND_PUSH) && - ociRegistryConfig.RepositoryList != "" { - return true - } - return false -} diff --git a/internal/util/ChartTemplateService.go b/internal/util/ChartTemplateService.go new file mode 100644 index 00000000000..926af8335a2 --- /dev/null +++ b/internal/util/ChartTemplateService.go @@ -0,0 +1,453 @@ +/* + * Copyright (c) 2020 Devtron Labs + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package util + +import ( + "compress/gzip" + "context" + "fmt" + "io/ioutil" + "math/rand" + "os" + "path/filepath" + "strconv" + "strings" + "time" + + dockerRegistryRepository "github.com/devtron-labs/devtron/internal/sql/repository/dockerRegistry" + dirCopy "github.com/otiai10/copy" + "go.opentelemetry.io/otel" + "go.uber.org/zap" + "k8s.io/helm/pkg/chartutil" + "k8s.io/helm/pkg/proto/hapi/chart" + "sigs.k8s.io/yaml" +) + +const ( + PIPELINE_DEPLOYMENT_TYPE_ACD = "argo_cd" + PIPELINE_DEPLOYMENT_TYPE_HELM = "helm" + PIPELINE_DEPLOYMENT_TYPE_MANIFEST_DOWNLOAD = "manifest_download" + CHART_WORKING_DIR_PATH = "/tmp/charts/" +) + +type ChartCreateRequest struct { + ChartMetaData *chart.Metadata + ChartPath string +} + +type ChartCreateResponse struct { + BuiltChartPath string + valuesYaml string +} + +type ChartTemplateService interface { + FetchValuesFromReferenceChart(chartMetaData *chart.Metadata, refChartLocation string, templateName string, userId int32, pipelineStrategyPath string) (*ChartValues, error) + GetChartVersion(location string) (string, error) + BuildChart(ctx context.Context, chartMetaData *chart.Metadata, referenceTemplatePath string) (string, error) + BuildChartProxyForHelmApps(chartCreateRequest *ChartCreateRequest) (chartCreateResponse *ChartCreateResponse, err error) + GetDir() string + CleanDir(dir string) + GetByteArrayRefChart(chartMetaData *chart.Metadata, referenceTemplatePath string) ([]byte, error) + LoadChartInBytes(ChartPath string, deleteChart bool) ([]byte, error) + LoadChartFromDir(dir string) (*chart.Chart, error) + CreateZipFileForChart(chart *chart.Chart, outputChartPathDir string) ([]byte, error) + PackageChart(tempReferenceTemplateDir string, chartMetaData *chart.Metadata) (*string, string, error) +} +type ChartTemplateServiceImpl struct { + randSource rand.Source + logger *zap.SugaredLogger +} + +type ChartValues struct { + Values string `json:"values"` //yaml + AppOverrides string `json:"appOverrides"` //json + EnvOverrides string `json:"envOverrides"` //json + ReleaseOverrides string `json:"releaseOverrides"` //json + PipelineOverrides string `json:"pipelineOverrides"` //json + ImageDescriptorTemplate string `json:"-"` +} + +func NewChartTemplateServiceImpl(logger *zap.SugaredLogger) *ChartTemplateServiceImpl { + return &ChartTemplateServiceImpl{ + randSource: rand.NewSource(time.Now().UnixNano()), + logger: logger, + } +} + +func (impl ChartTemplateServiceImpl) GetChartVersion(location string) (string, error) { + if fi, err := os.Stat(location); err != nil { + return "", err + } else if !fi.IsDir() { + return "", fmt.Errorf("%q is not a directory", location) + } + + chartYaml := filepath.Join(location, "Chart.yaml") + if _, err := os.Stat(chartYaml); os.IsNotExist(err) { + return "", fmt.Errorf("Chart.yaml file not present in the directory %q", location) + } + //chartYaml = filepath.Join(chartYaml,filepath.Clean(chartYaml)) + chartYamlContent, err := ioutil.ReadFile(filepath.Clean(chartYaml)) + if err != nil { + return "", fmt.Errorf("cannot read Chart.Yaml in directory %q", location) + } + + chartContent, err := chartutil.UnmarshalChartfile(chartYamlContent) + if err != nil { + return "", fmt.Errorf("cannot read Chart.Yaml in directory %q", location) + } + + return chartContent.Version, nil +} + +func (impl ChartTemplateServiceImpl) FetchValuesFromReferenceChart(chartMetaData *chart.Metadata, refChartLocation string, templateName string, userId int32, pipelineStrategyPath string) (*ChartValues, error) { + chartMetaData.ApiVersion = "v1" // ensure always v1 + dir := impl.GetDir() + chartDir := filepath.Join(CHART_WORKING_DIR_PATH, dir) + impl.logger.Debugw("chart dir ", "chart", chartMetaData.Name, "dir", chartDir) + err := os.MkdirAll(chartDir, os.ModePerm) //hack for concurrency handling + if err != nil { + impl.logger.Errorw("err in creating dir", "dir", chartDir, "err", err) + return nil, err + } + + defer impl.CleanDir(chartDir) + err = dirCopy.Copy(refChartLocation, chartDir) + + if err != nil { + impl.logger.Errorw("error in copying chart for app", "app", chartMetaData.Name, "error", err) + return nil, err + } + archivePath, valuesYaml, err := impl.PackageChart(chartDir, chartMetaData) + if err != nil { + impl.logger.Errorw("error in creating archive", "err", err) + return nil, err + } + values, err := impl.getValues(chartDir, pipelineStrategyPath) + if err != nil { + impl.logger.Errorw("error in pushing chart", "path", archivePath, "err", err) + return nil, err + } + values.Values = valuesYaml + descriptor, err := ioutil.ReadFile(filepath.Clean(filepath.Join(chartDir, ".image_descriptor_template.json"))) + if err != nil { + impl.logger.Errorw("error in reading descriptor", "path", chartDir, "err", err) + return nil, err + } + values.ImageDescriptorTemplate = string(descriptor) + return values, nil +} + +// TODO: convert BuildChart and BuildChartProxyForHelmApps into one function +func (impl ChartTemplateServiceImpl) BuildChart(ctx context.Context, chartMetaData *chart.Metadata, referenceTemplatePath string) (string, error) { + chartMetaData.ApiVersion = "v1" // ensure always v1 + dir := impl.GetDir() + tempReferenceTemplateDir := filepath.Join(CHART_WORKING_DIR_PATH, dir) + impl.logger.Debugw("chart dir ", "chart", chartMetaData.Name, "dir", tempReferenceTemplateDir) + err := os.MkdirAll(tempReferenceTemplateDir, os.ModePerm) //hack for concurrency handling + if err != nil { + impl.logger.Errorw("err in creating dir", "dir", tempReferenceTemplateDir, "err", err) + return "", err + } + err = dirCopy.Copy(referenceTemplatePath, tempReferenceTemplateDir) + + if err != nil { + impl.logger.Errorw("error in copying chart for app", "app", chartMetaData.Name, "error", err) + return "", err + } + _, span := otel.Tracer("orchestrator").Start(ctx, "impl.PackageChart") + _, _, err = impl.PackageChart(tempReferenceTemplateDir, chartMetaData) + span.End() + if err != nil { + impl.logger.Errorw("error in creating archive", "err", err) + return "", err + } + return tempReferenceTemplateDir, nil +} + +func (impl ChartTemplateServiceImpl) BuildChartProxyForHelmApps(chartCreateRequest *ChartCreateRequest) (*ChartCreateResponse, error) { + chartCreateResponse := &ChartCreateResponse{} + chartMetaData := chartCreateRequest.ChartMetaData + chartMetaData.ApiVersion = "v2" // ensure always v2 + dir := impl.GetDir() + chartDir := filepath.Join(CHART_WORKING_DIR_PATH, dir) + impl.logger.Debugw("chart dir ", "chart", chartMetaData.Name, "dir", chartDir) + err := os.MkdirAll(chartDir, os.ModePerm) //hack for concurrency handling + if err != nil { + impl.logger.Errorw("err in creating dir", "dir", chartDir, "err", err) + return chartCreateResponse, err + } + err = dirCopy.Copy(chartCreateRequest.ChartPath, chartDir) + + if err != nil { + impl.logger.Errorw("error in copying chart for app", "app", chartMetaData.Name, "error", err) + return chartCreateResponse, err + } + _, valuesYaml, err := impl.PackageChart(chartDir, chartMetaData) + if err != nil { + impl.logger.Errorw("error in creating archive", "err", err) + return chartCreateResponse, err + } + chartCreateResponse.valuesYaml = valuesYaml + chartCreateResponse.BuiltChartPath = chartDir + return chartCreateResponse, nil +} + +func (impl ChartTemplateServiceImpl) getValues(directory, pipelineStrategyPath string) (values *ChartValues, err error) { + + if fi, err := os.Stat(directory); err != nil { + return nil, err + } else if !fi.IsDir() { + return nil, fmt.Errorf("%q is not a directory", directory) + } + + files, err := ioutil.ReadDir(directory) + if err != nil { + impl.logger.Errorw("failed reading directory", "err", err) + return nil, fmt.Errorf(" Couldn't read the %q", directory) + } + + var appOverrideByte, envOverrideByte, releaseOverrideByte, pipelineOverrideByte []byte + + for _, file := range files { + if !file.IsDir() { + name := strings.ToLower(file.Name()) + if name == "app-values.yaml" || name == "app-values.yml" { + appOverrideByte, err = ioutil.ReadFile(filepath.Clean(filepath.Join(directory, file.Name()))) + if err != nil { + impl.logger.Errorw("failed reading data from file", "err", err) + } else { + appOverrideByte, err = yaml.YAMLToJSON(appOverrideByte) + if err != nil { + return nil, err + } + } + } + if name == "env-values.yaml" || name == "env-values.yml" { + envOverrideByte, err = ioutil.ReadFile(filepath.Clean(filepath.Join(directory, file.Name()))) + if err != nil { + impl.logger.Errorw("failed reading data from file", "err", err) + } else { + envOverrideByte, err = yaml.YAMLToJSON(envOverrideByte) + if err != nil { + return nil, err + } + } + } + if name == "release-values.yaml" || name == "release-values.yml" { + releaseOverrideByte, err = ioutil.ReadFile(filepath.Clean(filepath.Join(directory, file.Name()))) + if err != nil { + impl.logger.Errorw("failed reading data from file", "err", err) + } else { + releaseOverrideByte, err = yaml.YAMLToJSON(releaseOverrideByte) + if err != nil { + return nil, err + } + } + } + } + } + pipelineOverrideByte, err = ioutil.ReadFile(filepath.Clean(filepath.Join(directory, pipelineStrategyPath))) + if err != nil { + impl.logger.Errorw("failed reading data from file", "err", err) + } else { + pipelineOverrideByte, err = yaml.YAMLToJSON(pipelineOverrideByte) + if err != nil { + return nil, err + } + } + + val := &ChartValues{ + AppOverrides: string(appOverrideByte), + EnvOverrides: string(envOverrideByte), + ReleaseOverrides: string(releaseOverrideByte), + PipelineOverrides: string(pipelineOverrideByte), + } + return val, nil + +} + +func (impl ChartTemplateServiceImpl) PackageChart(tempReferenceTemplateDir string, chartMetaData *chart.Metadata) (*string, string, error) { + valid, err := chartutil.IsChartDir(tempReferenceTemplateDir) + if err != nil { + impl.logger.Errorw("error in validating base chart", "dir", tempReferenceTemplateDir, "err", err) + return nil, "", err + } + if !valid { + impl.logger.Errorw("invalid chart at ", "dir", tempReferenceTemplateDir) + return nil, "", fmt.Errorf("invalid base chart") + } + + b, err := yaml.Marshal(chartMetaData) + if err != nil { + impl.logger.Errorw("error in marshaling chartMetadata", "err", err) + return nil, "", err + } + err = ioutil.WriteFile(filepath.Join(tempReferenceTemplateDir, "Chart.yaml"), b, 0600) + if err != nil { + impl.logger.Errorw("err in writing Chart.yaml", "err", err) + return nil, "", err + } + chart, err := chartutil.LoadDir(tempReferenceTemplateDir) + if err != nil { + impl.logger.Errorw("error in loading chart dir", "err", err, "dir", tempReferenceTemplateDir) + return nil, "", err + } + + archivePath, err := chartutil.Save(chart, tempReferenceTemplateDir) + if err != nil { + impl.logger.Errorw("error in saving", "err", err, "dir", tempReferenceTemplateDir) + return nil, "", err + } + impl.logger.Debugw("chart archive path", "path", archivePath) + var valuesYaml string + if chart.Values != nil { + valuesYaml = chart.Values.Raw + } else { + impl.logger.Warnw("values.yaml not found in helm chart", "dir", tempReferenceTemplateDir) + } + return &archivePath, valuesYaml, nil +} + +func (impl ChartTemplateServiceImpl) CleanDir(dir string) { + err := os.RemoveAll(dir) + if err != nil { + impl.logger.Warnw("error in deleting dir ", "dir", dir) + } +} + +func (impl ChartTemplateServiceImpl) GetDir() string { + /* #nosec */ + r1 := rand.New(impl.randSource).Int63() + return strconv.FormatInt(r1, 10) +} + +// GetByteArrayRefChart this method will be used for getting byte array from reference chart to store in db +func (impl ChartTemplateServiceImpl) GetByteArrayRefChart(chartMetaData *chart.Metadata, referenceTemplatePath string) ([]byte, error) { + chartMetaData.ApiVersion = "v1" // ensure always v1 + dir := impl.GetDir() + tempReferenceTemplateDir := filepath.Join(CHART_WORKING_DIR_PATH, dir) + impl.logger.Debugw("chart dir ", "chart", chartMetaData.Name, "dir", tempReferenceTemplateDir) + err := os.MkdirAll(tempReferenceTemplateDir, os.ModePerm) //hack for concurrency handling + if err != nil { + impl.logger.Errorw("err in creating dir", "dir", tempReferenceTemplateDir, "err", err) + return nil, err + } + defer impl.CleanDir(tempReferenceTemplateDir) + err = dirCopy.Copy(referenceTemplatePath, tempReferenceTemplateDir) + if err != nil { + impl.logger.Errorw("error in copying chart for app", "app", chartMetaData.Name, "error", err) + return nil, err + } + activePath, _, err := impl.PackageChart(tempReferenceTemplateDir, chartMetaData) + if err != nil { + impl.logger.Errorw("error in creating archive", "err", err) + return nil, err + } + file, err := os.Open(*activePath) + reader, err := gzip.NewReader(file) + if err != nil { + impl.logger.Errorw("There is a problem with os.Open", "err", err) + return nil, err + } + // read the complete content of the file h.Name into the bs []byte + bs, err := ioutil.ReadAll(reader) + if err != nil { + impl.logger.Errorw("There is a problem with readAll", "err", err) + return nil, err + } + return bs, nil +} + +func (impl ChartTemplateServiceImpl) LoadChartInBytes(ChartPath string, deleteChart bool) ([]byte, error) { + + var chartBytesArr []byte + //this function is removed in latest helm release and is replaced by Loader in loader package + chart, err := chartutil.LoadDir(ChartPath) + if err != nil { + impl.logger.Errorw("error in loading chart dir", "err", err, "dir") + return chartBytesArr, err + } + chartBytesArr, err = impl.CreateZipFileForChart(chart, ChartPath) + if err != nil { + impl.logger.Errorw("error in saving", "err", err, "dir") + return chartBytesArr, err + } + + if deleteChart { + defer impl.CleanDir(ChartPath) + } + + return chartBytesArr, err +} + +func (impl ChartTemplateServiceImpl) LoadChartFromDir(dir string) (*chart.Chart, error) { + //this function is removed in latest helm release and is replaced by Loader in loader package + chart, err := chartutil.LoadDir(dir) + if err != nil { + impl.logger.Errorw("error in loading chart dir", "err", err, "dir") + return chart, err + } + return chart, nil +} + +func (impl ChartTemplateServiceImpl) CreateZipFileForChart(chart *chart.Chart, outputChartPathDir string) ([]byte, error) { + var chartBytesArr []byte + chartZipPath, err := chartutil.Save(chart, outputChartPathDir) + if err != nil { + impl.logger.Errorw("error in saving", "err", err, "dir") + return chartBytesArr, err + } + + chartBytesArr, err = ioutil.ReadFile(chartZipPath) + if err != nil { + impl.logger.Errorw("There is a problem with os.Open", "err", err) + return nil, err + } + return chartBytesArr, nil +} + +func IsHelmApp(deploymentAppType string) bool { + return deploymentAppType == PIPELINE_DEPLOYMENT_TYPE_HELM +} + +func IsAcdApp(deploymentAppType string) bool { + return deploymentAppType == PIPELINE_DEPLOYMENT_TYPE_ACD +} + +func IsManifestDownload(deploymentAppType string) bool { + return deploymentAppType == PIPELINE_DEPLOYMENT_TYPE_MANIFEST_DOWNLOAD +} + +func IsOCIRegistryChartProvider(ociRegistry dockerRegistryRepository.DockerArtifactStore) bool { + if ociRegistry.OCIRegistryConfig == nil || + len(ociRegistry.OCIRegistryConfig) != 1 || + !IsOCIConfigChartProvider(ociRegistry.OCIRegistryConfig[0]) { + return false + } + return true +} + +func IsOCIConfigChartProvider(ociRegistryConfig *dockerRegistryRepository.OCIRegistryConfig) bool { + if ociRegistryConfig.RepositoryType == dockerRegistryRepository.OCI_REGISRTY_REPO_TYPE_CHART && + (ociRegistryConfig.RepositoryAction == dockerRegistryRepository.STORAGE_ACTION_TYPE_PULL || + ociRegistryConfig.RepositoryAction == dockerRegistryRepository.STORAGE_ACTION_TYPE_PULL_AND_PUSH) && + ociRegistryConfig.RepositoryList != "" { + return true + } + return false +} diff --git a/internal/util/ChartService_test.go b/internal/util/ChartTemplateService_test.go similarity index 100% rename from internal/util/ChartService_test.go rename to internal/util/ChartTemplateService_test.go diff --git a/pkg/app/AppListingService.go b/pkg/app/AppListingService.go index f93bd4408af..0f67f2bad04 100644 --- a/pkg/app/AppListingService.go +++ b/pkg/app/AppListingService.go @@ -21,6 +21,7 @@ import ( "context" "encoding/json" "fmt" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deployedAppMetrics" "net/http" "strconv" "strings" @@ -159,8 +160,6 @@ type AppListingServiceImpl struct { pipelineRepository pipelineConfig.PipelineRepository cdWorkflowRepository pipelineConfig.CdWorkflowRepository linkoutsRepository repository.LinkoutsRepository - appLevelMetricsRepository repository.AppLevelMetricsRepository - envLevelMetricsRepository repository.EnvLevelAppMetricsRepository pipelineOverrideRepository chartConfig.PipelineOverrideRepository environmentRepository repository2.EnvironmentRepository argoUserService argo.ArgoUserService @@ -169,17 +168,18 @@ type AppListingServiceImpl struct { ciPipelineRepository pipelineConfig.CiPipelineRepository dockerRegistryIpsConfigService dockerRegistry.DockerRegistryIpsConfigService userRepository userrepository.UserRepository + deployedAppMetricsService deployedAppMetrics.DeployedAppMetricsService } func NewAppListingServiceImpl(Logger *zap.SugaredLogger, appListingRepository repository.AppListingRepository, application application2.ServiceClient, appRepository app.AppRepository, appListingViewBuilder AppListingViewBuilder, pipelineRepository pipelineConfig.PipelineRepository, - linkoutsRepository repository.LinkoutsRepository, appLevelMetricsRepository repository.AppLevelMetricsRepository, - envLevelMetricsRepository repository.EnvLevelAppMetricsRepository, cdWorkflowRepository pipelineConfig.CdWorkflowRepository, + linkoutsRepository repository.LinkoutsRepository, cdWorkflowRepository pipelineConfig.CdWorkflowRepository, pipelineOverrideRepository chartConfig.PipelineOverrideRepository, environmentRepository repository2.EnvironmentRepository, argoUserService argo.ArgoUserService, envOverrideRepository chartConfig.EnvConfigOverrideRepository, chartRepository chartRepoRepository.ChartRepository, ciPipelineRepository pipelineConfig.CiPipelineRepository, - dockerRegistryIpsConfigService dockerRegistry.DockerRegistryIpsConfigService, userRepository userrepository.UserRepository) *AppListingServiceImpl { + dockerRegistryIpsConfigService dockerRegistry.DockerRegistryIpsConfigService, userRepository userrepository.UserRepository, + deployedAppMetricsService deployedAppMetrics.DeployedAppMetricsService) *AppListingServiceImpl { serviceImpl := &AppListingServiceImpl{ Logger: Logger, appListingRepository: appListingRepository, @@ -188,8 +188,6 @@ func NewAppListingServiceImpl(Logger *zap.SugaredLogger, appListingRepository re appListingViewBuilder: appListingViewBuilder, pipelineRepository: pipelineRepository, linkoutsRepository: linkoutsRepository, - appLevelMetricsRepository: appLevelMetricsRepository, - envLevelMetricsRepository: envLevelMetricsRepository, cdWorkflowRepository: cdWorkflowRepository, pipelineOverrideRepository: pipelineOverrideRepository, environmentRepository: environmentRepository, @@ -199,6 +197,7 @@ func NewAppListingServiceImpl(Logger *zap.SugaredLogger, appListingRepository re ciPipelineRepository: ciPipelineRepository, dockerRegistryIpsConfigService: dockerRegistryIpsConfigService, userRepository: userRepository, + deployedAppMetricsService: deployedAppMetricsService, } return serviceImpl } @@ -885,52 +884,6 @@ func (impl AppListingServiceImpl) FetchAppDetails(ctx context.Context, appId int return appDetailContainer, nil } -func (impl AppListingServiceImpl) fetchAppAndEnvLevelMatrics(ctx context.Context, appId int, appDetailContainer bean.AppDetailContainer) (bean.AppDetailContainer, error) { - var appMetrics bool - var infraMetrics bool - _, span := otel.Tracer("orchestrator").Start(ctx, "appLevelMetricsRepository.FindByAppId") - appLevelMetrics, err := impl.appLevelMetricsRepository.FindByAppId(appId) - span.End() - if err != nil && err != pg.ErrNoRows { - impl.Logger.Errorw("error in app metrics app level flag", "error", err) - return bean.AppDetailContainer{}, err - } else if appLevelMetrics != nil { - appMetrics = appLevelMetrics.AppMetrics - infraMetrics = appLevelMetrics.InfraMetrics - } - i := 0 - var envIds []int - for _, env := range appDetailContainer.Environments { - envIds = append(envIds, env.EnvironmentId) - } - envLevelAppMetricsMap := make(map[int]*repository.EnvLevelAppMetrics) - _, span = otel.Tracer("orchestrator").Start(ctx, "appLevelMetricsRepository.FindByAppIdAndEnvIds") - envLevelAppMetrics, err := impl.envLevelMetricsRepository.FindByAppIdAndEnvIds(appId, envIds) - span.End() - for _, envLevelAppMetric := range envLevelAppMetrics { - envLevelAppMetricsMap[envLevelAppMetric.EnvId] = envLevelAppMetric - } - for _, env := range appDetailContainer.Environments { - var envLevelMetrics *bool - var envLevelInfraMetrics *bool - envLevelAppMetrics := envLevelAppMetricsMap[env.EnvironmentId] - if envLevelAppMetrics != nil && envLevelAppMetrics.Id != 0 && envLevelAppMetrics.AppMetrics != nil { - envLevelMetrics = envLevelAppMetrics.AppMetrics - } else { - envLevelMetrics = &appMetrics - } - if envLevelAppMetrics != nil && envLevelAppMetrics.Id != 0 && envLevelAppMetrics.InfraMetrics != nil { - envLevelInfraMetrics = envLevelAppMetrics.InfraMetrics - } else { - envLevelInfraMetrics = &infraMetrics - } - appDetailContainer.Environments[i].AppMetrics = envLevelMetrics - appDetailContainer.Environments[i].InfraMetrics = envLevelInfraMetrics - i++ - } - return appDetailContainer, nil -} - func (impl AppListingServiceImpl) setIpAccessProvidedData(ctx context.Context, appDetailContainer bean.AppDetailContainer, clusterId int, isVirtualEnv bool) (bean.AppDetailContainer, error) { ciPipelineId := appDetailContainer.CiPipelineId if ciPipelineId > 0 { @@ -1718,21 +1671,13 @@ func (impl AppListingServiceImpl) FetchOtherEnvironment(ctx context.Context, app impl.Logger.Errorw("err", err) return envs, err } - appLevelAppMetrics := false //default value - appLevelInfraMetrics := true //default val - newCtx, span = otel.Tracer("appLevelMetricsRepository").Start(newCtx, "FindByAppId") - appLevelMetrics, err := impl.appLevelMetricsRepository.FindByAppId(appId) + appLevelInfraMetrics := true //default val, not being derived from DB. TODO: remove this from FE since this is derived from prometheus config at cluster level and this logic is already present at FE + newCtx, span = otel.Tracer("deployedAppMetricsService").Start(newCtx, "GetMetricsFlagByAppId") + appLevelAppMetrics, err := impl.deployedAppMetricsService.GetMetricsFlagByAppId(appId) span.End() - if err != nil && !util.IsErrNoRows(err) { - impl.Logger.Errorw("error in fetching app metrics", "err", err) + if err != nil { + impl.Logger.Errorw("error, GetMetricsFlagByAppId", "err", err, "appId", appId) return envs, err - } else if util.IsErrNoRows(err) { - //populate default val - appLevelAppMetrics = false //default value - appLevelInfraMetrics = true //default val - } else { - appLevelAppMetrics = appLevelMetrics.AppMetrics - appLevelInfraMetrics = appLevelMetrics.InfraMetrics } newCtx, span = otel.Tracer("chartRepository").Start(newCtx, "FindLatestChartForAppByAppId") chart, err := impl.chartRepository.FindLatestChartForAppByAppId(appId) @@ -1757,9 +1702,7 @@ func (impl AppListingServiceImpl) FetchOtherEnvironment(ctx context.Context, app if env.AppMetrics == nil { env.AppMetrics = &appLevelAppMetrics } - if env.InfraMetrics == nil { - env.InfraMetrics = &appLevelInfraMetrics - } + env.InfraMetrics = &appLevelInfraMetrics //using default value, discarding value got from query } return envs, nil } @@ -1770,19 +1713,11 @@ func (impl AppListingServiceImpl) FetchMinDetailOtherEnvironment(appId int) ([]* impl.Logger.Errorw("err", err) return envs, err } - appLevelAppMetrics := false //default value - appLevelInfraMetrics := true //default val - appLevelMetrics, err := impl.appLevelMetricsRepository.FindByAppId(appId) - if err != nil && !util.IsErrNoRows(err) { - impl.Logger.Errorw("error in fetching app metrics", "err", err) - return envs, err - } else if util.IsErrNoRows(err) { - //populate default val - appLevelAppMetrics = false //default value - appLevelInfraMetrics = true //default val - } else { - appLevelAppMetrics = appLevelMetrics.AppMetrics - appLevelInfraMetrics = appLevelMetrics.InfraMetrics + appLevelInfraMetrics := true //default val, not being derived from DB. TODO: remove this from FE since this is derived from prometheus config at cluster level and this logic is already present at FE + appLevelAppMetrics, err := impl.deployedAppMetricsService.GetMetricsFlagByAppId(appId) + if err != nil { + impl.Logger.Errorw("error, GetMetricsFlagByAppId", "err", err, "appId", appId) + return nil, err } chartRefId, err := impl.chartRepository.FindChartRefIdForLatestChartForAppByAppId(appId) @@ -1812,9 +1747,7 @@ func (impl AppListingServiceImpl) FetchMinDetailOtherEnvironment(appId int) ([]* if env.AppMetrics == nil { env.AppMetrics = &appLevelAppMetrics } - if env.InfraMetrics == nil { - env.InfraMetrics = &appLevelInfraMetrics - } + env.InfraMetrics = &appLevelInfraMetrics //using default value, discarding value got from query } return envs, nil } diff --git a/pkg/app/AppService.go b/pkg/app/AppService.go index 05c7ddf332b..62a158d4af6 100644 --- a/pkg/app/AppService.go +++ b/pkg/app/AppService.go @@ -21,6 +21,11 @@ import ( "context" "encoding/json" "fmt" + commonBean "github.com/devtron-labs/devtron/pkg/deployment/gitOps/common/bean" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/chartRef" + bean3 "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/chartRef/bean" "io/ioutil" "net/url" "os" @@ -33,18 +38,9 @@ import ( "github.com/caarlos0/env" k8sCommonBean "github.com/devtron-labs/common-lib/utils/k8s/commonBean" "github.com/devtron-labs/common-lib/utils/k8s/health" - client2 "github.com/devtron-labs/devtron/api/helm-app" status2 "github.com/devtron-labs/devtron/pkg/app/status" repository4 "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" - "github.com/devtron-labs/devtron/pkg/appStore/deployment/service" - "github.com/devtron-labs/devtron/pkg/auth/authorisation/casbin" - "github.com/devtron-labs/devtron/pkg/auth/user" bean2 "github.com/devtron-labs/devtron/pkg/bean" - "github.com/devtron-labs/devtron/pkg/chart" - "github.com/devtron-labs/devtron/pkg/dockerRegistry" - "github.com/devtron-labs/devtron/pkg/k8s" - repository3 "github.com/devtron-labs/devtron/pkg/pipeline/history/repository" - repository5 "github.com/devtron-labs/devtron/pkg/pipeline/repository" "github.com/devtron-labs/devtron/pkg/resourceQualifiers" "github.com/devtron-labs/devtron/pkg/variables" _ "github.com/devtron-labs/devtron/pkg/variables/repository" @@ -53,14 +49,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" chart2 "k8s.io/helm/pkg/proto/hapi/chart" - "github.com/devtron-labs/devtron/internal/sql/repository/app" - "github.com/devtron-labs/devtron/pkg/appStatus" - chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository" - repository2 "github.com/devtron-labs/devtron/pkg/cluster/repository" - history2 "github.com/devtron-labs/devtron/pkg/pipeline/history" - "github.com/devtron-labs/devtron/pkg/sql" - util3 "github.com/devtron-labs/devtron/pkg/util" - application2 "github.com/argoproj/argo-cd/v2/pkg/apiclient/application" "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" "github.com/devtron-labs/devtron/api/bean" @@ -68,14 +56,16 @@ import ( "github.com/devtron-labs/devtron/client/argocdServer/application" client "github.com/devtron-labs/devtron/client/events" "github.com/devtron-labs/devtron/internal/sql/repository" + "github.com/devtron-labs/devtron/internal/sql/repository/app" "github.com/devtron-labs/devtron/internal/sql/repository/chartConfig" "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig" - "github.com/devtron-labs/devtron/internal/sql/repository/security" . "github.com/devtron-labs/devtron/internal/util" + "github.com/devtron-labs/devtron/pkg/appStatus" + chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository" "github.com/devtron-labs/devtron/pkg/commonService" + "github.com/devtron-labs/devtron/pkg/sql" util2 "github.com/devtron-labs/devtron/util" util "github.com/devtron-labs/devtron/util/event" - "github.com/devtron-labs/devtron/util/rbac" "github.com/go-pg/pg" "go.uber.org/zap" ) @@ -108,64 +98,31 @@ type AppServiceImpl struct { pipelineOverrideRepository chartConfig.PipelineOverrideRepository mergeUtil *MergeUtil logger *zap.SugaredLogger - ciArtifactRepository repository.CiArtifactRepository pipelineRepository pipelineConfig.PipelineRepository - gitFactory *GitFactory eventClient client.EventClient eventFactory client.EventFactory acdClient application.ServiceClient - tokenCache *util3.TokenCache - acdAuthConfig *util3.ACDAuthConfig - enforcer casbin.Enforcer - enforcerUtil rbac.EnforcerUtil - user user.UserService - appListingRepository repository.AppListingRepository appRepository app.AppRepository - envRepository repository2.EnvironmentRepository - pipelineConfigRepository chartConfig.PipelineConfigRepository configMapRepository chartConfig.ConfigMapRepository chartRepository chartRepoRepository.ChartRepository - appRepo app.AppRepository - appLevelMetricsRepository repository.AppLevelMetricsRepository - envLevelMetricsRepository repository.EnvLevelAppMetricsRepository - ciPipelineMaterialRepository pipelineConfig.CiPipelineMaterialRepository cdWorkflowRepository pipelineConfig.CdWorkflowRepository commonService commonService.CommonService - imageScanDeployInfoRepository security.ImageScanDeployInfoRepository - imageScanHistoryRepository security.ImageScanHistoryRepository - ArgoK8sClient argocdServer.ArgoK8sClient - pipelineStrategyHistoryService history2.PipelineStrategyHistoryService - configMapHistoryService history2.ConfigMapHistoryService - deploymentTemplateHistoryService history2.DeploymentTemplateHistoryService chartTemplateService ChartTemplateService - refChartDir chartRepoRepository.RefChartDir - helmAppClient client2.HelmAppClient - helmAppService client2.HelmAppService - chartRefRepository chartRepoRepository.ChartRefRepository - chartService chart.ChartService argoUserService argo.ArgoUserService pipelineStatusTimelineRepository pipelineConfig.PipelineStatusTimelineRepository - appCrudOperationService AppCrudOperationService - configMapHistoryRepository repository3.ConfigMapHistoryRepository - strategyHistoryRepository repository3.PipelineStrategyHistoryRepository - deploymentTemplateHistoryRepository repository3.DeploymentTemplateHistoryRepository - dockerRegistryIpsConfigService dockerRegistry.DockerRegistryIpsConfigService pipelineStatusTimelineResourcesService status2.PipelineStatusTimelineResourcesService pipelineStatusSyncDetailService status2.PipelineStatusSyncDetailService pipelineStatusTimelineService status2.PipelineStatusTimelineService appStatusConfig *AppServiceConfig - gitOpsConfigRepository repository.GitOpsConfigRepository appStatusService appStatus.AppStatusService installedAppRepository repository4.InstalledAppRepository - AppStoreDeploymentService service.AppStoreDeploymentService - K8sCommonService k8s.K8sCommonService installedAppVersionHistoryRepository repository4.InstalledAppVersionHistoryRepository globalEnvVariables *util2.GlobalEnvVariables - manifestPushConfigRepository repository5.ManifestPushConfigRepository - GitOpsManifestPushService GitOpsPushService scopedVariableManager variables.ScopedVariableCMCSManager - argoClientWrapperService argocdServer.ArgoClientWrapperService acdConfig *argocdServer.ACDConfig + chartRefService chartRef.ChartRefService + gitOpsConfigReadService config.GitOpsConfigReadService + gitOperationService git.GitOperationService } type AppService interface { @@ -185,7 +142,7 @@ type AppService interface { //GetEnvOverrideByTriggerType(overrideRequest *bean.ValuesOverrideRequest, triggeredAt time.Time, ctx context.Context) (*chartConfig.EnvConfigOverride, error) //GetAppMetricsByTriggerType(overrideRequest *bean.ValuesOverrideRequest, ctx context.Context) (bool, error) //GetDeploymentStrategyByTriggerType(overrideRequest *bean.ValuesOverrideRequest, ctx context.Context) (*chartConfig.PipelineStrategy, error) - CreateGitopsRepo(app *app.App, userId int32) (gitopsRepoName string, chartGitAttr *ChartGitAttribute, err error) + CreateGitopsRepo(app *app.App, userId int32) (gitopsRepoName string, chartGitAttr *commonBean.ChartGitAttribute, err error) GetDeployedManifestByPipelineIdAndCDWorkflowId(appId int, envId int, cdWorkflowId int, ctx context.Context) ([]byte, error) //SetPipelineFieldsInOverrideRequest(overrideRequest *bean.ValuesOverrideRequest, pipeline *pipelineConfig.Pipeline) @@ -198,121 +155,59 @@ func NewAppService( pipelineOverrideRepository chartConfig.PipelineOverrideRepository, mergeUtil *MergeUtil, logger *zap.SugaredLogger, - ciArtifactRepository repository.CiArtifactRepository, pipelineRepository pipelineConfig.PipelineRepository, eventClient client.EventClient, eventFactory client.EventFactory, acdClient application.ServiceClient, - cache *util3.TokenCache, authConfig *util3.ACDAuthConfig, - enforcer casbin.Enforcer, enforcerUtil rbac.EnforcerUtil, user user.UserService, - appListingRepository repository.AppListingRepository, appRepository app.AppRepository, - envRepository repository2.EnvironmentRepository, - pipelineConfigRepository chartConfig.PipelineConfigRepository, configMapRepository chartConfig.ConfigMapRepository, - appLevelMetricsRepository repository.AppLevelMetricsRepository, - envLevelMetricsRepository repository.EnvLevelAppMetricsRepository, chartRepository chartRepoRepository.ChartRepository, - ciPipelineMaterialRepository pipelineConfig.CiPipelineMaterialRepository, cdWorkflowRepository pipelineConfig.CdWorkflowRepository, commonService commonService.CommonService, - imageScanDeployInfoRepository security.ImageScanDeployInfoRepository, - imageScanHistoryRepository security.ImageScanHistoryRepository, - ArgoK8sClient argocdServer.ArgoK8sClient, - gitFactory *GitFactory, - pipelineStrategyHistoryService history2.PipelineStrategyHistoryService, - configMapHistoryService history2.ConfigMapHistoryService, - deploymentTemplateHistoryService history2.DeploymentTemplateHistoryService, chartTemplateService ChartTemplateService, - refChartDir chartRepoRepository.RefChartDir, - chartRefRepository chartRepoRepository.ChartRefRepository, - chartService chart.ChartService, - helmAppClient client2.HelmAppClient, argoUserService argo.ArgoUserService, cdPipelineStatusTimelineRepo pipelineConfig.PipelineStatusTimelineRepository, - appCrudOperationService AppCrudOperationService, - configMapHistoryRepository repository3.ConfigMapHistoryRepository, - strategyHistoryRepository repository3.PipelineStrategyHistoryRepository, - deploymentTemplateHistoryRepository repository3.DeploymentTemplateHistoryRepository, - dockerRegistryIpsConfigService dockerRegistry.DockerRegistryIpsConfigService, pipelineStatusTimelineResourcesService status2.PipelineStatusTimelineResourcesService, pipelineStatusSyncDetailService status2.PipelineStatusSyncDetailService, pipelineStatusTimelineService status2.PipelineStatusTimelineService, appStatusConfig *AppServiceConfig, - gitOpsConfigRepository repository.GitOpsConfigRepository, appStatusService appStatus.AppStatusService, installedAppRepository repository4.InstalledAppRepository, - AppStoreDeploymentService service.AppStoreDeploymentService, - k8sCommonService k8s.K8sCommonService, installedAppVersionHistoryRepository repository4.InstalledAppVersionHistoryRepository, - globalEnvVariables *util2.GlobalEnvVariables, helmAppService client2.HelmAppService, - manifestPushConfigRepository repository5.ManifestPushConfigRepository, - GitOpsManifestPushService GitOpsPushService, - argoClientWrapperService argocdServer.ArgoClientWrapperService, + globalEnvVariables *util2.GlobalEnvVariables, scopedVariableManager variables.ScopedVariableCMCSManager, - acdConfig *argocdServer.ACDConfig, -) *AppServiceImpl { + acdConfig *argocdServer.ACDConfig, chartRefService chartRef.ChartRefService, + gitOpsConfigReadService config.GitOpsConfigReadService, + gitOperationService git.GitOperationService) *AppServiceImpl { appServiceImpl := &AppServiceImpl{ environmentConfigRepository: environmentConfigRepository, mergeUtil: mergeUtil, pipelineOverrideRepository: pipelineOverrideRepository, logger: logger, - ciArtifactRepository: ciArtifactRepository, pipelineRepository: pipelineRepository, eventClient: eventClient, eventFactory: eventFactory, acdClient: acdClient, - tokenCache: cache, - acdAuthConfig: authConfig, - enforcer: enforcer, - enforcerUtil: enforcerUtil, - user: user, - appListingRepository: appListingRepository, appRepository: appRepository, - envRepository: envRepository, - pipelineConfigRepository: pipelineConfigRepository, configMapRepository: configMapRepository, chartRepository: chartRepository, - appLevelMetricsRepository: appLevelMetricsRepository, - envLevelMetricsRepository: envLevelMetricsRepository, - ciPipelineMaterialRepository: ciPipelineMaterialRepository, cdWorkflowRepository: cdWorkflowRepository, commonService: commonService, - imageScanDeployInfoRepository: imageScanDeployInfoRepository, - imageScanHistoryRepository: imageScanHistoryRepository, - ArgoK8sClient: ArgoK8sClient, - gitFactory: gitFactory, - pipelineStrategyHistoryService: pipelineStrategyHistoryService, - configMapHistoryService: configMapHistoryService, - deploymentTemplateHistoryService: deploymentTemplateHistoryService, chartTemplateService: chartTemplateService, - refChartDir: refChartDir, - chartRefRepository: chartRefRepository, - chartService: chartService, - helmAppClient: helmAppClient, argoUserService: argoUserService, pipelineStatusTimelineRepository: cdPipelineStatusTimelineRepo, - appCrudOperationService: appCrudOperationService, - configMapHistoryRepository: configMapHistoryRepository, - strategyHistoryRepository: strategyHistoryRepository, - deploymentTemplateHistoryRepository: deploymentTemplateHistoryRepository, - dockerRegistryIpsConfigService: dockerRegistryIpsConfigService, pipelineStatusTimelineResourcesService: pipelineStatusTimelineResourcesService, pipelineStatusSyncDetailService: pipelineStatusSyncDetailService, pipelineStatusTimelineService: pipelineStatusTimelineService, appStatusConfig: appStatusConfig, - gitOpsConfigRepository: gitOpsConfigRepository, appStatusService: appStatusService, installedAppRepository: installedAppRepository, - AppStoreDeploymentService: AppStoreDeploymentService, - K8sCommonService: k8sCommonService, installedAppVersionHistoryRepository: installedAppVersionHistoryRepository, globalEnvVariables: globalEnvVariables, - helmAppService: helmAppService, - manifestPushConfigRepository: manifestPushConfigRepository, - GitOpsManifestPushService: GitOpsManifestPushService, - argoClientWrapperService: argoClientWrapperService, scopedVariableManager: scopedVariableManager, acdConfig: acdConfig, + chartRefService: chartRefService, + gitOpsConfigReadService: gitOpsConfigReadService, + gitOperationService: gitOperationService, } return appServiceImpl } @@ -988,16 +883,16 @@ func (impl *AppServiceImpl) BuildChartAndGetPath(appName string, envOverride *ch Name: appName, Version: envOverride.Chart.ChartVersion, } - referenceTemplatePath := path.Join(string(impl.refChartDir), envOverride.Chart.ReferenceTemplate) + referenceTemplatePath := path.Join(bean3.RefChartDirPath, envOverride.Chart.ReferenceTemplate) // Load custom charts to referenceTemplatePath if not exists if _, err := os.Stat(referenceTemplatePath); os.IsNotExist(err) { - chartRefValue, err := impl.chartRefRepository.FindById(envOverride.Chart.ChartRefId) + chartRefValue, err := impl.chartRefService.FindById(envOverride.Chart.ChartRefId) if err != nil { impl.logger.Errorw("error in fetching ChartRef data", "err", err) return "", err } if chartRefValue.ChartData != nil { - chartInfo, err := impl.chartService.ExtractChartIfMissing(chartRefValue.ChartData, string(impl.refChartDir), chartRefValue.Location) + chartInfo, err := impl.chartRefService.ExtractChartIfMissing(chartRefValue.ChartData, bean3.RefChartDirPath, chartRefValue.Location) if chartInfo != nil && chartInfo.TemporaryFolder != "" { err1 := os.RemoveAll(chartInfo.TemporaryFolder) if err1 != nil { @@ -1016,13 +911,13 @@ func (impl *AppServiceImpl) BuildChartAndGetPath(appName string, envOverride *ch return tempReferenceTemplateDir, nil } -func (impl *AppServiceImpl) CreateGitopsRepo(app *app.App, userId int32) (gitopsRepoName string, chartGitAttr *ChartGitAttribute, err error) { +func (impl *AppServiceImpl) CreateGitopsRepo(app *app.App, userId int32) (gitopsRepoName string, chartGitAttr *commonBean.ChartGitAttribute, err error) { chart, err := impl.chartRepository.FindLatestChartForAppByAppId(app.Id) if err != nil && pg.ErrNoRows != err { return "", nil, err } - gitOpsRepoName := impl.chartTemplateService.GetGitOpsRepoName(app.AppName) - chartGitAttr, err = impl.chartTemplateService.CreateGitRepositoryForApp(gitOpsRepoName, chart.ReferenceTemplate, chart.ChartVersion, userId) + gitOpsRepoName := impl.gitOpsConfigReadService.GetGitOpsRepoName(app.AppName) + chartGitAttr, err = impl.gitOperationService.CreateGitRepositoryForApp(gitOpsRepoName, chart.ReferenceTemplate, chart.ChartVersion, userId) if err != nil { impl.logger.Errorw("error in pushing chart to git ", "gitOpsRepoName", gitOpsRepoName, "err", err) return "", nil, err @@ -1069,7 +964,7 @@ func (impl *AppServiceImpl) autoHealChartLocationInChart(ctx context.Context, en // get chart ref from DB (to get location) chartRefId := chart.ChartRefId _, span = otel.Tracer("orchestrator").Start(ctx, "chartRefRepository.FindById") - chartRef, err := impl.chartRefRepository.FindById(chartRefId) + chartRefDto, err := impl.chartRefService.FindById(chartRefId) span.End() if err != nil { impl.logger.Errorw("error occurred while fetching chartRef from DB", "chartRefId", chartRefId, "err", err) @@ -1077,7 +972,7 @@ func (impl *AppServiceImpl) autoHealChartLocationInChart(ctx context.Context, en } // build new chart location - newChartLocation := filepath.Join(chartRef.Location, envOverride.Chart.ChartVersion) + newChartLocation := filepath.Join(chartRefDto.Location, envOverride.Chart.ChartVersion) impl.logger.Infow("new chart location build", "chartId", chartId, "newChartLocation", newChartLocation) // update chart in DB diff --git a/pkg/app/ManifestPushService.go b/pkg/app/ManifestPushService.go index 7f370435e4e..6502a797d8c 100644 --- a/pkg/app/ManifestPushService.go +++ b/pkg/app/ManifestPushService.go @@ -3,16 +3,13 @@ package app import ( "context" "fmt" - bean2 "github.com/devtron-labs/devtron/api/bean" "github.com/devtron-labs/devtron/client/argocdServer" - "github.com/devtron-labs/devtron/internal/sql/repository" "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig" - "github.com/devtron-labs/devtron/internal/util" - . "github.com/devtron-labs/devtron/internal/util" "github.com/devtron-labs/devtron/pkg/app/bean" status2 "github.com/devtron-labs/devtron/pkg/app/status" - chartService "github.com/devtron-labs/devtron/pkg/chart" - "github.com/go-pg/pg" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/chartRef" "go.opentelemetry.io/otel" "go.uber.org/zap" "time" @@ -28,34 +25,28 @@ type GitOpsPushService interface { type GitOpsManifestPushServiceImpl struct { logger *zap.SugaredLogger - chartTemplateService util.ChartTemplateService - chartService chartService.ChartService - gitOpsConfigRepository repository.GitOpsConfigRepository - gitFactory *GitFactory pipelineStatusTimelineService status2.PipelineStatusTimelineService pipelineStatusTimelineRepository pipelineConfig.PipelineStatusTimelineRepository acdConfig *argocdServer.ACDConfig + chartRefService chartRef.ChartRefService + gitOpsConfigReadService config.GitOpsConfigReadService + gitOperationService git.GitOperationService } -func NewGitOpsManifestPushServiceImpl( - logger *zap.SugaredLogger, - chartTemplateService util.ChartTemplateService, - chartService chartService.ChartService, - gitOpsConfigRepository repository.GitOpsConfigRepository, - gitFactory *GitFactory, +func NewGitOpsManifestPushServiceImpl(logger *zap.SugaredLogger, pipelineStatusTimelineService status2.PipelineStatusTimelineService, pipelineStatusTimelineRepository pipelineConfig.PipelineStatusTimelineRepository, - acdConfig *argocdServer.ACDConfig, -) *GitOpsManifestPushServiceImpl { + acdConfig *argocdServer.ACDConfig, chartRefService chartRef.ChartRefService, + gitOpsConfigReadService config.GitOpsConfigReadService, + gitOperationService git.GitOperationService) *GitOpsManifestPushServiceImpl { return &GitOpsManifestPushServiceImpl{ logger: logger, - chartTemplateService: chartTemplateService, - chartService: chartService, - gitOpsConfigRepository: gitOpsConfigRepository, - gitFactory: gitFactory, pipelineStatusTimelineService: pipelineStatusTimelineService, pipelineStatusTimelineRepository: pipelineStatusTimelineRepository, acdConfig: acdConfig, + chartRefService: chartRefService, + gitOpsConfigReadService: gitOpsConfigReadService, + gitOperationService: gitOperationService, } } @@ -107,16 +98,16 @@ func (impl *GitOpsManifestPushServiceImpl) PushChartToGitRepo(manifestPushTempla _, span := otel.Tracer("orchestrator").Start(ctx, "chartTemplateService.GetGitOpsRepoName") // CHART COMMIT and PUSH STARTS HERE, it will push latest version, if found modified on deployment template and overrides - gitOpsRepoName := impl.chartTemplateService.GetGitOpsRepoName(manifestPushTemplate.AppName) + gitOpsRepoName := impl.gitOpsConfigReadService.GetGitOpsRepoName(manifestPushTemplate.AppName) span.End() _, span = otel.Tracer("orchestrator").Start(ctx, "chartService.CheckChartExists") - err := impl.chartService.CheckChartExists(manifestPushTemplate.ChartRefId) + err := impl.chartRefService.CheckChartExists(manifestPushTemplate.ChartRefId) span.End() if err != nil { impl.logger.Errorw("err in getting chart info", "err", err) return err } - err = impl.chartTemplateService.PushChartToGitRepo(gitOpsRepoName, manifestPushTemplate.ChartReferenceTemplate, manifestPushTemplate.ChartVersion, manifestPushTemplate.BuiltChartPath, manifestPushTemplate.RepoUrl, manifestPushTemplate.UserId) + err = impl.gitOperationService.PushChartToGitRepo(gitOpsRepoName, manifestPushTemplate.ChartReferenceTemplate, manifestPushTemplate.ChartVersion, manifestPushTemplate.BuiltChartPath, manifestPushTemplate.RepoUrl, manifestPushTemplate.UserId) if err != nil { impl.logger.Errorw("error in pushing chart to git", "err", err) return err @@ -127,12 +118,12 @@ func (impl *GitOpsManifestPushServiceImpl) PushChartToGitRepo(manifestPushTempla func (impl *GitOpsManifestPushServiceImpl) CommitValuesToGit(manifestPushTemplate *bean.ManifestPushTemplate, ctx context.Context) (commitHash string, commitTime time.Time, err error) { commitHash = "" commitTime = time.Time{} - chartRepoName := impl.chartTemplateService.GetGitOpsRepoNameFromUrl(manifestPushTemplate.RepoUrl) + chartRepoName := impl.gitOpsConfigReadService.GetGitOpsRepoNameFromUrl(manifestPushTemplate.RepoUrl) _, span := otel.Tracer("orchestrator").Start(ctx, "chartTemplateService.GetUserEmailIdAndNameForGitOpsCommit") //getting username & emailId for commit author data - userEmailId, userName := impl.chartTemplateService.GetUserEmailIdAndNameForGitOpsCommit(manifestPushTemplate.UserId) + userEmailId, userName := impl.gitOpsConfigReadService.GetUserEmailIdAndNameForGitOpsCommit(manifestPushTemplate.UserId) span.End() - chartGitAttr := &util.ChartConfig{ + chartGitAttr := &git.ChartConfig{ FileName: fmt.Sprintf("_%d-values.yaml", manifestPushTemplate.TargetEnvironmentName), FileContent: string(manifestPushTemplate.MergedValues), ChartName: manifestPushTemplate.ChartName, @@ -142,29 +133,14 @@ func (impl *GitOpsManifestPushServiceImpl) CommitValuesToGit(manifestPushTemplat UserName: userName, UserEmailId: userEmailId, } - gitOpsConfigBitbucket, err := impl.gitOpsConfigRepository.GetGitOpsConfigByProvider(util.BITBUCKET_PROVIDER) - if err != nil { - if err == pg.ErrNoRows { - gitOpsConfigBitbucket.BitBucketWorkspaceId = "" - } else { - return commitHash, commitTime, err - } - } - gitOpsConfig := &bean2.GitOpsConfigDto{BitBucketWorkspaceId: gitOpsConfigBitbucket.BitBucketWorkspaceId} - _, span = otel.Tracer("orchestrator").Start(ctx, "gitFactory.Client.CommitValues") - commitHash, commitTime, err = impl.gitFactory.Client.CommitValues(chartGitAttr, gitOpsConfig) + + _, span = otel.Tracer("orchestrator").Start(ctx, "gitOperationService.CommitValues") + commitHash, commitTime, err = impl.gitOperationService.CommitValues(chartGitAttr) span.End() if err != nil { impl.logger.Errorw("error in git commit", "err", err) return commitHash, commitTime, err } - if commitTime.IsZero() { - commitTime = time.Now() - } - span.End() - if err != nil { - return commitHash, commitTime, err - } return commitHash, commitTime, nil } diff --git a/pkg/app/integrationTest/AppServiceDeployment_test.go b/pkg/app/integrationTest/AppServiceDeployment_test.go index b849021a99d..a05fb7ce07c 100644 --- a/pkg/app/integrationTest/AppServiceDeployment_test.go +++ b/pkg/app/integrationTest/AppServiceDeployment_test.go @@ -4,7 +4,6 @@ import ( "context" "github.com/devtron-labs/devtron/api/bean" "github.com/devtron-labs/devtron/internal/sql/models" - repository3 "github.com/devtron-labs/devtron/internal/sql/repository" "github.com/devtron-labs/devtron/internal/sql/repository/chartConfig" mocks3 "github.com/devtron-labs/devtron/internal/sql/repository/chartConfig/mocks" mocks5 "github.com/devtron-labs/devtron/internal/sql/repository/mocks" @@ -14,6 +13,7 @@ import ( mocks2 "github.com/devtron-labs/devtron/pkg/chartRepo/repository/mocks" repository2 "github.com/devtron-labs/devtron/pkg/cluster/repository" mocks4 "github.com/devtron-labs/devtron/pkg/cluster/repository/mocks" + repository4 "github.com/devtron-labs/devtron/pkg/deployment/manifest/deployedAppMetrics/repository" "github.com/devtron-labs/devtron/pkg/pipeline/history/repository" "github.com/devtron-labs/devtron/pkg/pipeline/history/repository/mocks" "github.com/devtron-labs/devtron/pkg/sql" @@ -438,7 +438,7 @@ func TestDeploymentTemplateHistoryService(t *testing.T) { mockedAppLevelMetricsRepository := mocks5.NewAppLevelMetricsRepository(t) - appLevelMetricsDBObject := &repository3.AppLevelMetrics{ + appLevelMetricsDBObject := &repository4.AppLevelMetrics{ Id: 1, AppId: 1, AppMetrics: false, @@ -452,7 +452,7 @@ func TestDeploymentTemplateHistoryService(t *testing.T) { appMetrics := true - mockedEnvLevelMetricsDBObject := &repository3.EnvLevelAppMetrics{ + mockedEnvLevelMetricsDBObject := &repository4.EnvLevelAppMetrics{ Id: 1, AppId: 1, EnvId: 1, @@ -521,7 +521,7 @@ func TestDeploymentTemplateHistoryService(t *testing.T) { mockedAppLevelMetricsRepository := mocks5.NewAppLevelMetricsRepository(t) - appLevelMetricsDBObject := &repository3.AppLevelMetrics{ + appLevelMetricsDBObject := &repository4.AppLevelMetrics{ Id: 1, AppId: 1, AppMetrics: false, @@ -533,7 +533,7 @@ func TestDeploymentTemplateHistoryService(t *testing.T) { mockedEnvLevelMetricsRepository := mocks5.NewEnvLevelAppMetricsRepository(t) - mockedEnvLevelMetricsDBObject := &repository3.EnvLevelAppMetrics{ + mockedEnvLevelMetricsDBObject := &repository4.EnvLevelAppMetrics{ Id: 0, AppId: 0, EnvId: 0, diff --git a/pkg/app/integrationTest/AppService_test.go b/pkg/app/integrationTest/AppService_test.go index 9c78b5b7832..03ed6b64232 100644 --- a/pkg/app/integrationTest/AppService_test.go +++ b/pkg/app/integrationTest/AppService_test.go @@ -155,12 +155,11 @@ func InitAppService() *app2.AppServiceImpl { pipelineStatusSyncDetailRepository := pipelineConfig.NewPipelineStatusSyncDetailRepositoryImpl(dbConnection, logger) pipelineStatusSyncDetailService := status.NewPipelineStatusSyncDetailServiceImpl(logger, pipelineStatusSyncDetailRepository) pipelineStatusTimelineService := status.NewPipelineStatusTimelineServiceImpl(logger, pipelineStatusTimelineRepository, cdWorkflowRepository, nil, pipelineStatusTimelineResourcesService, pipelineStatusSyncDetailService, nil, nil) - refChartDir := chartRepoRepository.RefChartDir("scripts/devtron-reference-helm-charts") appService := app2.NewAppService(nil, pipelineOverrideRepository, nil, logger, nil, pipelineRepository, nil, eventClient, eventFactory, nil, nil, nil, nil, nil, nil, appListingRepository, appRepository, nil, nil, nil, nil, nil, chartRepository, nil, cdWorkflowRepository, nil, nil, nil, nil, - nil, nil, nil, nil, nil, refChartDir, nil, + nil, nil, nil, nil, nil, nil, nil, nil, nil, pipelineStatusTimelineRepository, nil, nil, nil, nil, nil, pipelineStatusTimelineResourcesService, pipelineStatusSyncDetailService, pipelineStatusTimelineService, nil, nil, nil, nil, nil, nil, nil, diff --git a/pkg/appClone/AppCloneService.go b/pkg/appClone/AppCloneService.go index 803cfe8b6ed..651ba84efb5 100644 --- a/pkg/appClone/AppCloneService.go +++ b/pkg/appClone/AppCloneService.go @@ -31,6 +31,7 @@ import ( "github.com/devtron-labs/devtron/pkg/appWorkflow" "github.com/devtron-labs/devtron/pkg/bean" "github.com/devtron-labs/devtron/pkg/chart" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config" "github.com/devtron-labs/devtron/pkg/pipeline" bean3 "github.com/devtron-labs/devtron/pkg/pipeline/bean" "github.com/go-pg/pg" @@ -44,7 +45,6 @@ type AppCloneService interface { type AppCloneServiceImpl struct { logger *zap.SugaredLogger pipelineBuilder pipeline.PipelineBuilder - materialRepository pipelineConfig.MaterialRepository chartService chart.ChartService configMapService pipeline.ConfigMapService appWorkflowService appWorkflow.AppWorkflowService @@ -55,27 +55,25 @@ type AppCloneServiceImpl struct { appRepository app2.AppRepository ciPipelineRepository pipelineConfig.CiPipelineRepository pipelineRepository pipelineConfig.PipelineRepository - appWorkflowRepository appWorkflow2.AppWorkflowRepository ciPipelineConfigService pipeline.CiPipelineConfigService + gitOpsConfigReadService config.GitOpsConfigReadService } func NewAppCloneServiceImpl(logger *zap.SugaredLogger, pipelineBuilder pipeline.PipelineBuilder, - materialRepository pipelineConfig.MaterialRepository, chartService chart.ChartService, configMapService pipeline.ConfigMapService, appWorkflowService appWorkflow.AppWorkflowService, appListingService app.AppListingService, propertiesConfigService pipeline.PropertiesConfigService, - ciTemplateOverrideRepository pipelineConfig.CiTemplateOverrideRepository, pipelineStageService pipeline.PipelineStageService, ciTemplateService pipeline.CiTemplateService, appRepository app2.AppRepository, ciPipelineRepository pipelineConfig.CiPipelineRepository, - pipelineRepository pipelineConfig.PipelineRepository, appWorkflowRepository appWorkflow2.AppWorkflowRepository, - ciPipelineConfigService pipeline.CiPipelineConfigService) *AppCloneServiceImpl { + pipelineRepository pipelineConfig.PipelineRepository, + ciPipelineConfigService pipeline.CiPipelineConfigService, + gitOpsConfigReadService config.GitOpsConfigReadService) *AppCloneServiceImpl { return &AppCloneServiceImpl{ logger: logger, pipelineBuilder: pipelineBuilder, - materialRepository: materialRepository, chartService: chartService, configMapService: configMapService, appWorkflowService: appWorkflowService, @@ -86,8 +84,8 @@ func NewAppCloneServiceImpl(logger *zap.SugaredLogger, appRepository: appRepository, ciPipelineRepository: ciPipelineRepository, pipelineRepository: pipelineRepository, - appWorkflowRepository: appWorkflowRepository, ciPipelineConfigService: ciPipelineConfigService, + gitOpsConfigReadService: gitOpsConfigReadService, } } @@ -985,7 +983,7 @@ func (impl *AppCloneServiceImpl) CreateCdPipeline(req *cloneCdPipelineRequest, c for deploymentType, allowed := range DeploymentAppConfigForEnvironment { AllowedDeploymentAppTypes[deploymentType] = allowed } - isGitopsConfigured, err := impl.pipelineBuilder.IsGitopsConfigured() + isGitopsConfigured, err := impl.gitOpsConfigReadService.IsGitOpsConfigured() if err != nil { impl.logger.Errorw("error in checking if gitOps configured", "err", err) return nil, err diff --git a/pkg/appStore/bean/bean.go b/pkg/appStore/bean/bean.go index 314e0fd7f6c..017741415ee 100644 --- a/pkg/appStore/bean/bean.go +++ b/pkg/appStore/bean/bean.go @@ -129,6 +129,10 @@ type InstallAppVersionChartRepoDTO struct { // / type RefChartProxyDir string +const ( + RefChartProxyDirPath = "scripts/devtron-reference-helm-charts" +) + var CHART_PROXY_TEMPLATE = "reference-chart-proxy" var REQUIREMENTS_YAML_FILE = "requirements.yaml" var VALUES_YAML_FILE = "values.yaml" diff --git a/pkg/appStore/deployment/common/AppStoreDeploymentCommonService.go b/pkg/appStore/deployment/common/AppStoreDeploymentCommonService.go index 44ca59836e0..a62122f0712 100644 --- a/pkg/appStore/deployment/common/AppStoreDeploymentCommonService.go +++ b/pkg/appStore/deployment/common/AppStoreDeploymentCommonService.go @@ -21,13 +21,15 @@ import ( "encoding/json" "fmt" "github.com/devtron-labs/devtron/api/bean" - repository3 "github.com/devtron-labs/devtron/internal/sql/repository" "github.com/devtron-labs/devtron/internal/util" appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" appStoreDiscoverRepository "github.com/devtron-labs/devtron/pkg/appStore/discover/repository" util2 "github.com/devtron-labs/devtron/pkg/appStore/util" repository2 "github.com/devtron-labs/devtron/pkg/cluster/repository" + commonBean "github.com/devtron-labs/devtron/pkg/deployment/gitOps/common/bean" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git" "github.com/go-pg/pg" "github.com/google/go-github/github" "github.com/microsoft/azure-devops-go-api/azuredevops" @@ -48,11 +50,10 @@ type AppStoreDeploymentCommonService interface { GetInstalledAppByClusterNamespaceAndName(clusterId int, namespace string, appName string) (*appStoreBean.InstallAppVersionDTO, error) GetInstalledAppByInstalledAppId(installedAppId int) (*appStoreBean.InstallAppVersionDTO, error) ParseGitRepoErrorResponse(err error) (bool, error) - GetValuesAndRequirementGitConfig(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*util.ChartConfig, *util.ChartConfig, error) + GetValuesAndRequirementGitConfig(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*git.ChartConfig, *git.ChartConfig, error) CreateChartProxyAndGetPath(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*util.ChartCreateResponse, error) - CreateGitOpsRepoAndPushChart(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, builtChartPath string, requirementsConfig *util.ChartConfig, valuesConfig *util.ChartConfig) (*util.ChartGitAttribute, bool, string, error) - CommitConfigToGit(chartConfig *util.ChartConfig) (gitHash string, err error) - GetGitCommitConfig(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, fileString string, filename string) (*util.ChartConfig, error) + CreateGitOpsRepoAndPushChart(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, builtChartPath string, requirementsConfig *git.ChartConfig, valuesConfig *git.ChartConfig) (*commonBean.ChartGitAttribute, bool, string, error) + GetGitCommitConfig(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, fileString string, filename string) (*git.ChartConfig, error) GetValuesString(chartName, valuesOverrideYaml string) (string, error) GetRequirementsString(appStoreVersionId int) (string, error) GenerateManifest(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (manifestResponse *AppStoreManifestResponse, err error) @@ -66,9 +67,9 @@ type AppStoreDeploymentCommonServiceImpl struct { appStoreApplicationVersionRepository appStoreDiscoverRepository.AppStoreApplicationVersionRepository environmentRepository repository2.EnvironmentRepository chartTemplateService util.ChartTemplateService - refChartDir appStoreBean.RefChartProxyDir - gitFactory *util.GitFactory - gitOpsConfigRepository repository3.GitOpsConfigRepository + gitFactory *git.GitFactory + gitOpsConfigReadService config.GitOpsConfigReadService + gitOperationService git.GitOperationService } func NewAppStoreDeploymentCommonServiceImpl( @@ -77,19 +78,18 @@ func NewAppStoreDeploymentCommonServiceImpl( appStoreApplicationVersionRepository appStoreDiscoverRepository.AppStoreApplicationVersionRepository, environmentRepository repository2.EnvironmentRepository, chartTemplateService util.ChartTemplateService, - refChartDir appStoreBean.RefChartProxyDir, - gitFactory *util.GitFactory, - gitOpsConfigRepository repository3.GitOpsConfigRepository, -) *AppStoreDeploymentCommonServiceImpl { + gitFactory *git.GitFactory, + gitOpsConfigReadService config.GitOpsConfigReadService, + gitOperationService git.GitOperationService) *AppStoreDeploymentCommonServiceImpl { return &AppStoreDeploymentCommonServiceImpl{ logger: logger, installedAppRepository: installedAppRepository, appStoreApplicationVersionRepository: appStoreApplicationVersionRepository, environmentRepository: environmentRepository, chartTemplateService: chartTemplateService, - refChartDir: refChartDir, gitFactory: gitFactory, - gitOpsConfigRepository: gitOpsConfigRepository, + gitOpsConfigReadService: gitOpsConfigReadService, + gitOperationService: gitOperationService, } } @@ -115,12 +115,12 @@ func ParseChartGitPushRequest(installAppRequestDTO *appStoreBean.InstallAppVersi type AppStoreManifestResponse struct { ChartResponse *util.ChartCreateResponse - ValuesConfig *util.ChartConfig - RequirementsConfig *util.ChartConfig + ValuesConfig *git.ChartConfig + RequirementsConfig *git.ChartConfig } type AppStoreGitOpsResponse struct { - ChartGitAttribute *util.ChartGitAttribute + ChartGitAttribute *commonBean.ChartGitAttribute GitHash string } @@ -228,7 +228,7 @@ func (impl AppStoreDeploymentCommonServiceImpl) ParseGitRepoErrorResponse(err er impl.logger.Errorw("no content found while updating git repo gitlab, do auto fix", "error", err) noTargetFound = true } - if err.Error() == util.BITBUCKET_REPO_NOT_FOUND_ERROR { + if err.Error() == git.BITBUCKET_REPO_NOT_FOUND_ERROR { impl.logger.Errorw("no content found while updating git repo bitbucket, do auto fix", "error", err) noTargetFound = true } @@ -289,7 +289,7 @@ func (impl AppStoreDeploymentCommonServiceImpl) GetRequirementsString(appStoreVe return string(requirementDependenciesByte), nil } -func (impl AppStoreDeploymentCommonServiceImpl) GetGitCommitConfig(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, fileString string, filename string) (*util.ChartConfig, error) { +func (impl AppStoreDeploymentCommonServiceImpl) GetGitCommitConfig(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, fileString string, filename string) (*git.ChartConfig, error) { appStoreAppVersion, err := impl.appStoreApplicationVersionRepository.FindById(installAppVersionRequest.AppStoreVersion) if err != nil { impl.logger.Errorw("fetching error", "err", err) @@ -302,9 +302,9 @@ func (impl AppStoreDeploymentCommonServiceImpl) GetGitCommitConfig(installAppVer } argocdAppName := installAppVersionRequest.AppName + "-" + environment.Name - gitOpsRepoName := impl.chartTemplateService.GetGitOpsRepoName(installAppVersionRequest.AppName) - userEmailId, userName := impl.chartTemplateService.GetUserEmailIdAndNameForGitOpsCommit(installAppVersionRequest.UserId) - YamlConfig := &util.ChartConfig{ + gitOpsRepoName := impl.gitOpsConfigReadService.GetGitOpsRepoName(installAppVersionRequest.AppName) + userEmailId, userName := impl.gitOpsConfigReadService.GetUserEmailIdAndNameForGitOpsCommit(installAppVersionRequest.UserId) + YamlConfig := &git.ChartConfig{ FileName: filename, FileContent: fileString, ChartName: installAppVersionRequest.AppName, @@ -317,7 +317,7 @@ func (impl AppStoreDeploymentCommonServiceImpl) GetGitCommitConfig(installAppVer return YamlConfig, nil } -func (impl AppStoreDeploymentCommonServiceImpl) GetValuesAndRequirementGitConfig(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*util.ChartConfig, *util.ChartConfig, error) { +func (impl AppStoreDeploymentCommonServiceImpl) GetValuesAndRequirementGitConfig(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*git.ChartConfig, *git.ChartConfig, error) { appStoreAppVersion, err := impl.appStoreApplicationVersionRepository.FindById(installAppVersionRequest.AppStoreVersion) if err != nil { @@ -352,7 +352,7 @@ func (impl AppStoreDeploymentCommonServiceImpl) CreateChartProxyAndGetPath(insta ChartCreateResponse := &util.ChartCreateResponse{} template := appStoreBean.CHART_PROXY_TEMPLATE - chartPath := path.Join(string(impl.refChartDir), template) + chartPath := path.Join(appStoreBean.RefChartProxyDirPath, template) valid, err := chartutil.IsChartDir(chartPath) if err != nil || !valid { impl.logger.Errorw("invalid base chart", "dir", chartPath, "err", err) @@ -403,62 +403,49 @@ func (impl AppStoreDeploymentCommonServiceImpl) GenerateManifest(installAppVersi // CreateGitOpsRepo creates a gitOps repo with readme func (impl AppStoreDeploymentCommonServiceImpl) CreateGitOpsRepo(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (string, bool, error) { - if len(installAppVersionRequest.GitOpsRepoName) == 0 { //here gitops repo will be the app name, to breaking the mono repo structure - gitOpsRepoName := impl.chartTemplateService.GetGitOpsRepoName(installAppVersionRequest.AppName) + gitOpsRepoName := impl.gitOpsConfigReadService.GetGitOpsRepoName(installAppVersionRequest.AppName) installAppVersionRequest.GitOpsRepoName = gitOpsRepoName } - gitOpsConfigBitbucket, err := impl.gitOpsConfigRepository.GetGitOpsConfigByProvider(util.BITBUCKET_PROVIDER) + bitbucketMetadata, err := impl.gitOpsConfigReadService.GetBitbucketMetadata() if err != nil { - if err == pg.ErrNoRows { - err = nil - gitOpsConfigBitbucket.BitBucketWorkspaceId = "" - } else { - return "", false, err - } + impl.logger.Errorw("error in getting bitbucket metadata", "err", err) + return "", false, err } //getting user name & emailId for commit author data - userEmailId, userName := impl.chartTemplateService.GetUserEmailIdAndNameForGitOpsCommit(installAppVersionRequest.UserId) gitRepoRequest := &bean.GitOpsConfigDto{ GitRepoName: installAppVersionRequest.GitOpsRepoName, Description: "helm chart for " + installAppVersionRequest.GitOpsRepoName, - Username: userName, - UserEmailId: userEmailId, - BitBucketWorkspaceId: gitOpsConfigBitbucket.BitBucketWorkspaceId, - BitBucketProjectKey: gitOpsConfigBitbucket.BitBucketProjectKey, + BitBucketWorkspaceId: bitbucketMetadata.BitBucketWorkspaceId, + BitBucketProjectKey: bitbucketMetadata.BitBucketProjectKey, } - repoUrl, isNew, detailedError := impl.gitFactory.Client.CreateRepository(gitRepoRequest) - for _, err := range detailedError.StageErrorMap { - if err != nil { - impl.logger.Errorw("error in creating git project", "name", installAppVersionRequest.GitOpsRepoName, "err", err) - return "", false, err - } + repoUrl, isNew, err := impl.gitOperationService.CreateRepository(gitRepoRequest, installAppVersionRequest.UserId) + if err != nil { + impl.logger.Errorw("error in creating git project", "name", installAppVersionRequest.GitOpsRepoName, "err", err) + return "", false, err } return repoUrl, isNew, err } // PushChartToGitopsRepo pushes built chart to gitOps repo -func (impl AppStoreDeploymentCommonServiceImpl) PushChartToGitopsRepo(PushChartToGitRequest *appStoreBean.PushChartToGitRequestDTO, requirementsConfig *util.ChartConfig, valuesConfig *util.ChartConfig) (*util.ChartGitAttribute, string, error) { +func (impl AppStoreDeploymentCommonServiceImpl) PushChartToGitopsRepo(PushChartToGitRequest *appStoreBean.PushChartToGitRequestDTO, requirementsConfig *git.ChartConfig, valuesConfig *git.ChartConfig) (*commonBean.ChartGitAttribute, string, error) { space := regexp.MustCompile(`\s+`) appStoreName := space.ReplaceAllString(PushChartToGitRequest.ChartAppStoreName, "-") chartDir := fmt.Sprintf("%s-%s", PushChartToGitRequest.AppName, impl.chartTemplateService.GetDir()) - clonedDir := impl.gitFactory.GitService.GetCloneDirectory(chartDir) - if _, err := os.Stat(clonedDir); os.IsNotExist(err) { - clonedDir, err = impl.gitFactory.GitService.Clone(PushChartToGitRequest.RepoURL, chartDir) - if err != nil { - impl.logger.Errorw("error in cloning repo", "url", PushChartToGitRequest.RepoURL, "err", err) - return nil, "", err - } - } else { - err = impl.chartTemplateService.GitPull(clonedDir, PushChartToGitRequest.RepoURL, appStoreName) - if err != nil { - return nil, "", err - } + clonedDir, err := impl.gitOperationService.GetClonedDir(chartDir, PushChartToGitRequest.RepoURL) + if err != nil { + impl.logger.Errorw("error in cloning repo", "url", PushChartToGitRequest.RepoURL, "err", err) + return nil, "", err + } + err = impl.gitOperationService.GitPull(clonedDir, PushChartToGitRequest.RepoURL, appStoreName) + if err != nil { + return nil, "", err } + acdAppName := fmt.Sprintf("%s-%s", PushChartToGitRequest.AppName, PushChartToGitRequest.EnvName) dir := filepath.Join(clonedDir, acdAppName) - err := os.MkdirAll(dir, os.ModePerm) + err = os.MkdirAll(dir, os.ModePerm) if err != nil { impl.logger.Errorw("error in making dir", "err", err) return nil, "", err @@ -478,12 +465,12 @@ func (impl AppStoreDeploymentCommonServiceImpl) PushChartToGitopsRepo(PushChartT impl.logger.Errorw("error in adding values.yaml to chart", "err", err, "appName", PushChartToGitRequest.AppName) return nil, "", err } - userEmailId, userName := impl.chartTemplateService.GetUserEmailIdAndNameForGitOpsCommit(PushChartToGitRequest.UserId) - commit, err := impl.gitFactory.GitService.CommitAndPushAllChanges(clonedDir, "first commit", userName, userEmailId) + userEmailId, userName := impl.gitOpsConfigReadService.GetUserEmailIdAndNameForGitOpsCommit(PushChartToGitRequest.UserId) + commit, err := impl.gitOperationService.CommitAndPushAllChanges(clonedDir, "first commit", userName, userEmailId) if err != nil { impl.logger.Errorw("error in pushing git", "err", err) impl.logger.Warn("re-trying, taking pull and then push again") - err = impl.chartTemplateService.GitPull(clonedDir, PushChartToGitRequest.RepoURL, acdAppName) + err = impl.gitOperationService.GitPull(clonedDir, PushChartToGitRequest.RepoURL, acdAppName) if err != nil { impl.logger.Errorw("error in git pull", "err", err, "appName", acdAppName) return nil, "", err @@ -493,7 +480,7 @@ func (impl AppStoreDeploymentCommonServiceImpl) PushChartToGitopsRepo(PushChartT impl.logger.Errorw("error copying dir", "err", err) return nil, "", err } - commit, err = impl.gitFactory.GitService.CommitAndPushAllChanges(clonedDir, "first commit", userName, userEmailId) + commit, err = impl.gitOperationService.CommitAndPushAllChanges(clonedDir, "first commit", userName, userEmailId) if err != nil { impl.logger.Errorw("error in pushing git", "err", err) return nil, "", err @@ -501,11 +488,11 @@ func (impl AppStoreDeploymentCommonServiceImpl) PushChartToGitopsRepo(PushChartT } impl.logger.Debugw("template committed", "url", PushChartToGitRequest.RepoURL, "commit", commit) defer impl.chartTemplateService.CleanDir(clonedDir) - return &util.ChartGitAttribute{RepoUrl: PushChartToGitRequest.RepoURL, ChartLocation: acdAppName}, commit, err + return &commonBean.ChartGitAttribute{RepoUrl: PushChartToGitRequest.RepoURL, ChartLocation: acdAppName}, commit, err } // AddConfigFileToChart will override requirements.yaml file in chart -func (impl AppStoreDeploymentCommonServiceImpl) AddConfigFileToChart(config *util.ChartConfig, dir string, clonedDir string) error { +func (impl AppStoreDeploymentCommonServiceImpl) AddConfigFileToChart(config *git.ChartConfig, dir string, clonedDir string) error { filePath := filepath.Join(clonedDir, config.FileName) file, err := os.Create(filePath) if err != nil { @@ -528,7 +515,7 @@ func (impl AppStoreDeploymentCommonServiceImpl) AddConfigFileToChart(config *uti } // CreateGitOpsRepoAndPushChart is a wrapper for creating gitops repo and pushing chart to created repo -func (impl AppStoreDeploymentCommonServiceImpl) CreateGitOpsRepoAndPushChart(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, builtChartPath string, requirementsConfig *util.ChartConfig, valuesConfig *util.ChartConfig) (*util.ChartGitAttribute, bool, string, error) { +func (impl AppStoreDeploymentCommonServiceImpl) CreateGitOpsRepoAndPushChart(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, builtChartPath string, requirementsConfig *git.ChartConfig, valuesConfig *git.ChartConfig) (*commonBean.ChartGitAttribute, bool, string, error) { repoURL, isNew, err := impl.CreateGitOpsRepo(installAppVersionRequest) if err != nil { impl.logger.Errorw("Error in creating gitops repo for ", "appName", installAppVersionRequest.AppName, "err", err) @@ -543,25 +530,6 @@ func (impl AppStoreDeploymentCommonServiceImpl) CreateGitOpsRepoAndPushChart(ins return chartGitAttribute, isNew, commitHash, err } -// CommitConfigToGit is used for committing values.yaml and requirements.yaml file config -func (impl AppStoreDeploymentCommonServiceImpl) CommitConfigToGit(chartConfig *util.ChartConfig) (string, error) { - gitOpsConfigBitbucket, err := impl.gitOpsConfigRepository.GetGitOpsConfigByProvider(util.BITBUCKET_PROVIDER) - if err != nil { - if err == pg.ErrNoRows { - gitOpsConfigBitbucket.BitBucketWorkspaceId = "" - } else { - return "", err - } - } - gitOpsConfig := &bean.GitOpsConfigDto{BitBucketWorkspaceId: gitOpsConfigBitbucket.BitBucketWorkspaceId} - gitHash, _, err := impl.gitFactory.Client.CommitValues(chartConfig, gitOpsConfig) - if err != nil { - impl.logger.Errorw("error in git commit", "err", err) - return "", err - } - return gitHash, nil -} - func (impl AppStoreDeploymentCommonServiceImpl) GitOpsOperations(manifestResponse *AppStoreManifestResponse, installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*AppStoreGitOpsResponse, error) { appStoreGitOpsResponse := &AppStoreGitOpsResponse{} chartGitAttribute, isNew, githash, err := impl.CreateGitOpsRepoAndPushChart(installAppVersionRequest, manifestResponse.ChartResponse.BuiltChartPath, manifestResponse.RequirementsConfig, manifestResponse.ValuesConfig) @@ -571,28 +539,28 @@ func (impl AppStoreDeploymentCommonServiceImpl) GitOpsOperations(manifestRespons } space := regexp.MustCompile(`\s+`) appStoreName := space.ReplaceAllString(installAppVersionRequest.AppName, "-") - clonedDir := impl.gitFactory.GitWorkingDir + "" + appStoreName + clonedDir := git.GIT_WORKING_DIR + "" + appStoreName // Checking this is the first time chart has been pushed , if yes requirements.yaml has been already pushed with chart as there was sync-delay with github api. // step-2 commit dependencies and values in git if !isNew { - _, err = impl.CommitConfigToGit(manifestResponse.RequirementsConfig) + _, _, err = impl.gitOperationService.CommitValues(manifestResponse.RequirementsConfig) if err != nil { impl.logger.Errorw("error in committing dependency config to git", "err", err) return appStoreGitOpsResponse, err } - err = impl.chartTemplateService.GitPull(clonedDir, chartGitAttribute.RepoUrl, appStoreName) + err = impl.gitOperationService.GitPull(clonedDir, chartGitAttribute.RepoUrl, appStoreName) if err != nil { impl.logger.Errorw("error in git pull", "err", err) return appStoreGitOpsResponse, err } - githash, err = impl.CommitConfigToGit(manifestResponse.ValuesConfig) + githash, _, err = impl.gitOperationService.CommitValues(manifestResponse.ValuesConfig) if err != nil { impl.logger.Errorw("error in committing values config to git", "err", err) return appStoreGitOpsResponse, err } - err = impl.chartTemplateService.GitPull(clonedDir, chartGitAttribute.RepoUrl, appStoreName) + err = impl.gitOperationService.GitPull(clonedDir, chartGitAttribute.RepoUrl, appStoreName) if err != nil { impl.logger.Errorw("error in git pull", "err", err) return appStoreGitOpsResponse, err diff --git a/pkg/appStore/deployment/fullMode/AppStoreDeploymentFullModeService.go b/pkg/appStore/deployment/fullMode/AppStoreDeploymentFullModeService.go index 2e06017de8c..ad2242066f3 100644 --- a/pkg/appStore/deployment/fullMode/AppStoreDeploymentFullModeService.go +++ b/pkg/appStore/deployment/fullMode/AppStoreDeploymentFullModeService.go @@ -24,6 +24,9 @@ import ( "fmt" "github.com/devtron-labs/common-lib/pubsub-lib" "github.com/devtron-labs/common-lib/pubsub-lib/model" + commonBean "github.com/devtron-labs/devtron/pkg/deployment/gitOps/common/bean" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git" "time" "github.com/devtron-labs/devtron/client/argocdServer" @@ -40,11 +43,7 @@ import ( "github.com/go-pg/pg" "github.com/argoproj/argo-cd/v2/pkg/apiclient/application" - repository2 "github.com/argoproj/argo-cd/v2/pkg/apiclient/repository" - "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" application2 "github.com/devtron-labs/devtron/client/argocdServer/application" - "github.com/devtron-labs/devtron/client/argocdServer/repository" - "github.com/devtron-labs/devtron/internal/util" "go.uber.org/zap" ) @@ -55,9 +54,7 @@ const ( // ACD operation and git operation type AppStoreDeploymentFullModeService interface { - AppStoreDeployOperationACD(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, chartGitAttr *util.ChartGitAttribute, ctx context.Context, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, error) - //TRACE usages and delete if unused - RegisterInArgo(chartGitAttribute *util.ChartGitAttribute, ctx context.Context) error + AppStoreDeployOperationACD(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, chartGitAttr *commonBean.ChartGitAttribute, ctx context.Context, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, error) UpdateValuesYaml(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, error) UpdateRequirementYaml(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, appStoreAppVersion *appStoreDiscoverRepository.AppStoreApplicationVersion) error GetGitOpsRepoName(appName string, environmentName string) (string, error) @@ -65,8 +62,6 @@ type AppStoreDeploymentFullModeService interface { type AppStoreDeploymentFullModeServiceImpl struct { logger *zap.SugaredLogger - chartTemplateService util.ChartTemplateService - repositoryService repository.ServiceClient acdClient application2.ServiceClient ArgoK8sClient argocdServer.ArgoK8sClient aCDAuthConfig *util2.ACDAuthConfig @@ -77,26 +72,23 @@ type AppStoreDeploymentFullModeServiceImpl struct { pubSubClient *pubsub_lib.PubSubClientServiceImpl installedAppRepositoryHistory repository4.InstalledAppVersionHistoryRepository ACDConfig *argocdServer.ACDConfig + gitOpsConfigReadService config.GitOpsConfigReadService + gitOperationService git.GitOperationService } func NewAppStoreDeploymentFullModeServiceImpl(logger *zap.SugaredLogger, - chartTemplateService util.ChartTemplateService, - repositoryService repository.ServiceClient, acdClient application2.ServiceClient, - argoK8sClient argocdServer.ArgoK8sClient, - aCDAuthConfig *util2.ACDAuthConfig, - argoUserService argo.ArgoUserService, - pipelineStatusTimelineService status.PipelineStatusTimelineService, + argoK8sClient argocdServer.ArgoK8sClient, aCDAuthConfig *util2.ACDAuthConfig, + argoUserService argo.ArgoUserService, pipelineStatusTimelineService status.PipelineStatusTimelineService, appStoreDeploymentCommonService appStoreDeploymentCommon.AppStoreDeploymentCommonService, argoClientWrapperService argocdServer.ArgoClientWrapperService, pubSubClient *pubsub_lib.PubSubClientServiceImpl, installedAppRepositoryHistory repository4.InstalledAppVersionHistoryRepository, ACDConfig *argocdServer.ACDConfig, -) *AppStoreDeploymentFullModeServiceImpl { + gitOpsConfigReadService config.GitOpsConfigReadService, + gitOperationService git.GitOperationService) *AppStoreDeploymentFullModeServiceImpl { appStoreDeploymentFullModeServiceImpl := &AppStoreDeploymentFullModeServiceImpl{ logger: logger, - chartTemplateService: chartTemplateService, - repositoryService: repositoryService, acdClient: acdClient, ArgoK8sClient: argoK8sClient, aCDAuthConfig: aCDAuthConfig, @@ -107,6 +99,8 @@ func NewAppStoreDeploymentFullModeServiceImpl(logger *zap.SugaredLogger, pubSubClient: pubSubClient, installedAppRepositoryHistory: installedAppRepositoryHistory, ACDConfig: ACDConfig, + gitOpsConfigReadService: gitOpsConfigReadService, + gitOperationService: gitOperationService, } err := appStoreDeploymentFullModeServiceImpl.subscribeHelmInstallStatus() if err != nil { @@ -115,11 +109,11 @@ func NewAppStoreDeploymentFullModeServiceImpl(logger *zap.SugaredLogger, return appStoreDeploymentFullModeServiceImpl } -func (impl AppStoreDeploymentFullModeServiceImpl) AppStoreDeployOperationACD(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, chartGitAttr *util.ChartGitAttribute, ctx context.Context, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, error) { +func (impl AppStoreDeploymentFullModeServiceImpl) AppStoreDeployOperationACD(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, chartGitAttr *commonBean.ChartGitAttribute, ctx context.Context, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, error) { ctx, cancel := context.WithTimeout(ctx, 1*time.Minute) defer cancel() //STEP 4: registerInArgo - err := impl.RegisterInArgo(chartGitAttr, ctx) + err := impl.argoClientWrapperService.RegisterGitOpsRepoInArgo(ctx, chartGitAttr.RepoUrl) if err != nil { impl.logger.Errorw("error in argo registry", "err", err) return nil, err @@ -162,19 +156,7 @@ func (impl AppStoreDeploymentFullModeServiceImpl) AppStoreDeployOperationACD(ins return installAppVersionRequest, nil } -func (impl AppStoreDeploymentFullModeServiceImpl) RegisterInArgo(chartGitAttribute *util.ChartGitAttribute, ctx context.Context) error { - repo := &v1alpha1.Repository{ - Repo: chartGitAttribute.RepoUrl, - } - repo, err := impl.repositoryService.Create(ctx, &repository2.RepoCreateRequest{Repo: repo, Upsert: true}) - if err != nil { - impl.logger.Errorw("error in creating argo Repository ", "err", err) - } - impl.logger.Debugw("repo registered in argo", "name", chartGitAttribute.RepoUrl) - return err -} - -func (impl AppStoreDeploymentFullModeServiceImpl) createInArgo(chartGitAttribute *util.ChartGitAttribute, ctx context.Context, envModel repository5.Environment, argocdAppName string) error { +func (impl AppStoreDeploymentFullModeServiceImpl) createInArgo(chartGitAttribute *commonBean.ChartGitAttribute, ctx context.Context, envModel repository5.Environment, argocdAppName string) error { appNamespace := envModel.Namespace if appNamespace == "" { appNamespace = "default" @@ -217,7 +199,7 @@ func (impl AppStoreDeploymentFullModeServiceImpl) GetGitOpsRepoName(appName stri } if application != nil { gitOpsRepoUrl := application.Spec.Source.RepoURL - gitOpsRepoName = impl.chartTemplateService.GetGitOpsRepoNameFromUrl(gitOpsRepoUrl) + gitOpsRepoName = impl.gitOpsConfigReadService.GetGitOpsRepoNameFromUrl(gitOpsRepoUrl) } return gitOpsRepoName, nil } @@ -235,7 +217,7 @@ func (impl AppStoreDeploymentFullModeServiceImpl) UpdateValuesYaml(installAppVer impl.logger.Errorw("error in getting git commit config", "err", err) } - commitHash, err := impl.appStoreDeploymentCommonService.CommitConfigToGit(valuesGitConfig) + commitHash, _, err := impl.gitOperationService.CommitValues(valuesGitConfig) if err != nil { impl.logger.Errorw("error in git commit", "err", err) return installAppVersionRequest, errors.New(pipelineConfig.TIMELINE_STATUS_GIT_COMMIT_FAILED) @@ -259,7 +241,7 @@ func (impl AppStoreDeploymentFullModeServiceImpl) UpdateRequirementYaml(installA return err } - _, err = impl.appStoreDeploymentCommonService.CommitConfigToGit(requirementsGitConfig) + _, _, err = impl.gitOperationService.CommitValues(requirementsGitConfig) if err != nil { impl.logger.Errorw("error in values commit", "err", err) return errors.New(pipelineConfig.TIMELINE_STATUS_GIT_COMMIT_FAILED) diff --git a/pkg/appStore/deployment/service/AppStoreDeploymentService.go b/pkg/appStore/deployment/service/AppStoreDeploymentService.go index 54303e7be15..203933a51d3 100644 --- a/pkg/appStore/deployment/service/AppStoreDeploymentService.go +++ b/pkg/appStore/deployment/service/AppStoreDeploymentService.go @@ -28,7 +28,6 @@ import ( openapi2 "github.com/devtron-labs/devtron/api/openapi/openapiClient" "github.com/devtron-labs/devtron/client/argocdServer" "github.com/devtron-labs/devtron/internal/constants" - repository2 "github.com/devtron-labs/devtron/internal/sql/repository" "github.com/devtron-labs/devtron/internal/sql/repository/app" "github.com/devtron-labs/devtron/internal/sql/repository/helper" "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig" @@ -39,11 +38,12 @@ import ( "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" appStoreDeploymentTool "github.com/devtron-labs/devtron/pkg/appStore/deployment/tool" appStoreDiscoverRepository "github.com/devtron-labs/devtron/pkg/appStore/discover/repository" - "github.com/devtron-labs/devtron/pkg/attributes" "github.com/devtron-labs/devtron/pkg/bean" "github.com/devtron-labs/devtron/pkg/cluster" cluster2 "github.com/devtron-labs/devtron/pkg/cluster" clusterRepository "github.com/devtron-labs/devtron/pkg/cluster/repository" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git" "github.com/devtron-labs/devtron/pkg/sql" util2 "github.com/devtron-labs/devtron/util" "github.com/go-pg/pg" @@ -103,10 +103,10 @@ type AppStoreDeploymentServiceImpl struct { helmAppService client.HelmAppService appStoreDeploymentCommonService appStoreDeploymentCommon.AppStoreDeploymentCommonService installedAppRepositoryHistory repository.InstalledAppVersionHistoryRepository - gitOpsRepository repository2.GitOpsConfigRepository deploymentTypeConfig *DeploymentServiceTypeConfig - ChartTemplateService util.ChartTemplateService aCDConfig *argocdServer.ACDConfig + gitOpsConfigReadService config.GitOpsConfigReadService + gitOperationService git.GitOperationService } func NewAppStoreDeploymentServiceImpl(logger *zap.SugaredLogger, installedAppRepository repository.InstalledAppRepository, @@ -115,8 +115,10 @@ func NewAppStoreDeploymentServiceImpl(logger *zap.SugaredLogger, installedAppRep appStoreDeploymentHelmService appStoreDeploymentTool.AppStoreDeploymentHelmService, appStoreDeploymentArgoCdService appStoreDeploymentTool.AppStoreDeploymentArgoCdService, environmentService cluster.EnvironmentService, clusterService cluster.ClusterService, helmAppService client.HelmAppService, appStoreDeploymentCommonService appStoreDeploymentCommon.AppStoreDeploymentCommonService, - installedAppRepositoryHistory repository.InstalledAppVersionHistoryRepository, gitOpsRepository repository2.GitOpsConfigRepository, attributesService attributes.AttributesService, - deploymentTypeConfig *DeploymentServiceTypeConfig, ChartTemplateService util.ChartTemplateService, aCDConfig *argocdServer.ACDConfig) *AppStoreDeploymentServiceImpl { + installedAppRepositoryHistory repository.InstalledAppVersionHistoryRepository, + deploymentTypeConfig *DeploymentServiceTypeConfig, aCDConfig *argocdServer.ACDConfig, + gitOpsConfigReadService config.GitOpsConfigReadService, + gitOperationService git.GitOperationService) *AppStoreDeploymentServiceImpl { appStoreDeploymentServiceImpl := &AppStoreDeploymentServiceImpl{ logger: logger, @@ -133,10 +135,10 @@ func NewAppStoreDeploymentServiceImpl(logger *zap.SugaredLogger, installedAppRep helmAppService: helmAppService, appStoreDeploymentCommonService: appStoreDeploymentCommonService, installedAppRepositoryHistory: installedAppRepositoryHistory, - gitOpsRepository: gitOpsRepository, deploymentTypeConfig: deploymentTypeConfig, - ChartTemplateService: ChartTemplateService, aCDConfig: aCDConfig, + gitOpsConfigReadService: gitOpsConfigReadService, + gitOperationService: gitOperationService, } return appStoreDeploymentServiceImpl } @@ -144,17 +146,11 @@ func NewAppStoreDeploymentServiceImpl(logger *zap.SugaredLogger, installedAppRep func (impl AppStoreDeploymentServiceImpl) AppStoreDeployOperationDB(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, tx *pg.Tx, skipAppCreation bool) (*appStoreBean.InstallAppVersionDTO, error) { var isInternalUse = impl.deploymentTypeConfig.IsInternalUse - - isGitOpsConfigured := false - gitOpsConfig, err := impl.gitOpsRepository.GetGitOpsConfigActive() - if err != nil && err != pg.ErrNoRows { - impl.logger.Errorw("GetGitOpsConfigActive, error while getting", "err", err) + isGitOpsConfigured, err := impl.gitOpsConfigReadService.IsGitOpsConfigured() + if err != nil { + impl.logger.Errorw("error while checking if gitOps is configured", "err", err) return nil, err } - if gitOpsConfig != nil && gitOpsConfig.Id > 0 { - isGitOpsConfigured = true - } - if isInternalUse && !isGitOpsConfigured && installAppVersionRequest.DeploymentAppType == util.PIPELINE_DEPLOYMENT_TYPE_ACD { impl.logger.Errorw("gitops not configured but selected for CD") err := &util.ApiError{ @@ -244,7 +240,7 @@ func (impl AppStoreDeploymentServiceImpl) AppStoreDeployOperationDB(installAppVe installedAppModel.UpdatedOn = time.Now() installedAppModel.Active = true if util2.IsFullStack() { - installedAppModel.GitOpsRepoName = impl.ChartTemplateService.GetGitOpsRepoName(installAppVersionRequest.AppName) + installedAppModel.GitOpsRepoName = impl.gitOpsConfigReadService.GetGitOpsRepoName(installAppVersionRequest.AppName) installAppVersionRequest.GitOpsRepoName = installedAppModel.GitOpsRepoName } installedApp, err := impl.installedAppRepository.CreateInstalledApp(installedAppModel, tx) @@ -1286,11 +1282,11 @@ func (impl *AppStoreDeploymentServiceImpl) CheckIfMonoRepoMigrationRequired(inst return false } } else { - gitOpsRepoName = impl.ChartTemplateService.GetGitOpsRepoName(installAppVersionRequest.AppName) + gitOpsRepoName = impl.gitOpsConfigReadService.GetGitOpsRepoName(installAppVersionRequest.AppName) } } //here will set new git repo name if required to migrate - newGitOpsRepoName := impl.ChartTemplateService.GetGitOpsRepoName(installedApp.App.AppName) + newGitOpsRepoName := impl.gitOpsConfigReadService.GetGitOpsRepoName(installedApp.App.AppName) //checking weather git repo migration needed or not, if existing git repo and new independent git repo is not same than go ahead with migration if newGitOpsRepoName != gitOpsRepoName { monoRepoMigrationRequired = true @@ -1444,11 +1440,11 @@ func (impl *AppStoreDeploymentServiceImpl) UpdateInstalledApp(ctx context.Contex return nil, err } } else { - gitOpsRepoName = impl.ChartTemplateService.GetGitOpsRepoName(installAppVersionRequest.AppName) + gitOpsRepoName = impl.gitOpsConfigReadService.GetGitOpsRepoName(installAppVersionRequest.AppName) } } //here will set new git repo name if required to migrate - newGitOpsRepoName := impl.ChartTemplateService.GetGitOpsRepoName(installedApp.App.AppName) + newGitOpsRepoName := impl.gitOpsConfigReadService.GetGitOpsRepoName(installedApp.App.AppName) //checking weather git repo migration needed or not, if existing git repo and new independent git repo is not same than go ahead with migration if newGitOpsRepoName != gitOpsRepoName { monoRepoMigrationRequired = true @@ -1470,12 +1466,12 @@ func (impl *AppStoreDeploymentServiceImpl) UpdateInstalledApp(ctx context.Contex } else if isChartChanged || isVersionChanged { // update dependency if chart or chart version is changed - _, requirementsCommitErr = impl.appStoreDeploymentCommonService.CommitConfigToGit(manifest.RequirementsConfig) - gitHash, valuesCommitErr = impl.appStoreDeploymentCommonService.CommitConfigToGit(manifest.ValuesConfig) + _, _, requirementsCommitErr = impl.gitOperationService.CommitValues(manifest.RequirementsConfig) + gitHash, _, valuesCommitErr = impl.gitOperationService.CommitValues(manifest.ValuesConfig) } else { // only values are changed in update, so commit values config - gitHash, valuesCommitErr = impl.appStoreDeploymentCommonService.CommitConfigToGit(manifest.ValuesConfig) + gitHash, _, valuesCommitErr = impl.gitOperationService.CommitValues(manifest.ValuesConfig) } if valuesCommitErr != nil || requirementsCommitErr != nil { diff --git a/pkg/appStore/deployment/service/InstalledAppService.go b/pkg/appStore/deployment/service/InstalledAppService.go index e10ab30e909..438e8adbf1a 100644 --- a/pkg/appStore/deployment/service/InstalledAppService.go +++ b/pkg/appStore/deployment/service/InstalledAppService.go @@ -20,6 +20,10 @@ package service import ( "bytes" "context" + commonBean "github.com/devtron-labs/devtron/pkg/deployment/gitOps/common/bean" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git" + /* #nosec */ "crypto/sha1" "encoding/json" @@ -65,7 +69,6 @@ import ( pubsub "github.com/devtron-labs/common-lib/pubsub-lib" bean2 "github.com/devtron-labs/devtron/api/bean" application2 "github.com/devtron-labs/devtron/client/argocdServer/application" - repository3 "github.com/devtron-labs/devtron/internal/sql/repository" "github.com/devtron-labs/devtron/internal/util" "github.com/devtron-labs/devtron/pkg/bean" cluster2 "github.com/devtron-labs/devtron/pkg/cluster" @@ -103,9 +106,7 @@ type InstalledAppServiceImpl struct { pubsubClient *pubsub.PubSubClientServiceImpl chartGroupDeploymentRepository repository6.ChartGroupDeploymentRepository envService cluster2.EnvironmentService - gitFactory *util.GitFactory aCDAuthConfig *util2.ACDAuthConfig - gitOpsRepository repository3.GitOpsConfigRepository userService user.UserService appStoreDeploymentService AppStoreDeploymentService appStoreDeploymentFullModeService appStoreDeploymentFullMode.AppStoreDeploymentFullModeService @@ -120,19 +121,18 @@ type InstalledAppServiceImpl struct { k8sCommonService k8s.K8sCommonService k8sApplicationService application3.K8sApplicationService acdConfig *argocdServer.ACDConfig + gitOpsConfigReadService config.GitOpsConfigReadService + gitOperationService git.GitOperationService } func NewInstalledAppServiceImpl(logger *zap.SugaredLogger, installedAppRepository repository2.InstalledAppRepository, appStoreApplicationVersionRepository appStoreDiscoverRepository.AppStoreApplicationVersionRepository, environmentRepository repository5.EnvironmentRepository, teamRepository repository4.TeamRepository, - appRepository app.AppRepository, - acdClient application2.ServiceClient, - appStoreValuesService service.AppStoreValuesService, - pubsubClient *pubsub.PubSubClientServiceImpl, + appRepository app.AppRepository, acdClient application2.ServiceClient, + appStoreValuesService service.AppStoreValuesService, pubsubClient *pubsub.PubSubClientServiceImpl, chartGroupDeploymentRepository repository6.ChartGroupDeploymentRepository, - envService cluster2.EnvironmentService, - gitFactory *util.GitFactory, aCDAuthConfig *util2.ACDAuthConfig, gitOpsRepository repository3.GitOpsConfigRepository, userService user.UserService, + envService cluster2.EnvironmentService, aCDAuthConfig *util2.ACDAuthConfig, userService user.UserService, appStoreDeploymentFullModeService appStoreDeploymentFullMode.AppStoreDeploymentFullModeService, appStoreDeploymentService AppStoreDeploymentService, installedAppRepositoryHistory repository2.InstalledAppVersionHistoryRepository, @@ -141,7 +141,8 @@ func NewInstalledAppServiceImpl(logger *zap.SugaredLogger, pipelineStatusTimelineService status.PipelineStatusTimelineService, appStoreDeploymentCommonService appStoreDeploymentCommon.AppStoreDeploymentCommonService, k8sCommonService k8s.K8sCommonService, k8sApplicationService application3.K8sApplicationService, - acdConfig *argocdServer.ACDConfig) (*InstalledAppServiceImpl, error) { + acdConfig *argocdServer.ACDConfig, gitOpsConfigReadService config.GitOpsConfigReadService, + gitOperationService git.GitOperationService) (*InstalledAppServiceImpl, error) { impl := &InstalledAppServiceImpl{ logger: logger, installedAppRepository: installedAppRepository, @@ -154,9 +155,7 @@ func NewInstalledAppServiceImpl(logger *zap.SugaredLogger, pubsubClient: pubsubClient, chartGroupDeploymentRepository: chartGroupDeploymentRepository, envService: envService, - gitFactory: gitFactory, aCDAuthConfig: aCDAuthConfig, - gitOpsRepository: gitOpsRepository, userService: userService, appStoreDeploymentService: appStoreDeploymentService, appStoreDeploymentFullModeService: appStoreDeploymentFullModeService, @@ -171,6 +170,8 @@ func NewInstalledAppServiceImpl(logger *zap.SugaredLogger, k8sCommonService: k8sCommonService, k8sApplicationService: k8sApplicationService, acdConfig: acdConfig, + gitOpsConfigReadService: gitOpsConfigReadService, + gitOperationService: gitOperationService, } err := impl.Subscribe() if err != nil { @@ -349,7 +350,7 @@ func (impl InstalledAppServiceImpl) createChartGroupEntryObject(installAppVersio func (impl InstalledAppServiceImpl) performDeployStageOnAcd(installedAppVersion *appStoreBean.InstallAppVersionDTO, ctx context.Context, userId int32) (*appStoreBean.InstallAppVersionDTO, error) { installedAppVersion.ACDAppName = fmt.Sprintf("%s-%s", installedAppVersion.AppName, installedAppVersion.Environment.Name) - chartGitAttr := &util.ChartGitAttribute{} + chartGitAttr := &commonBean.ChartGitAttribute{} if installedAppVersion.Status == appStoreBean.DEPLOY_INIT || installedAppVersion.Status == appStoreBean.ENQUEUED || installedAppVersion.Status == appStoreBean.QUE_ERROR || @@ -438,25 +439,13 @@ func (impl InstalledAppServiceImpl) performDeployStageOnAcd(installedAppVersion impl.logger.Errorw("fetching error", "err", err) return nil, err } - gitOpsConfigBitbucket, err := impl.gitOpsRepository.GetGitOpsConfigByProvider(util.BITBUCKET_PROVIDER) - if err != nil { - if err == pg.ErrNoRows { - gitOpsConfigBitbucket.BitBucketWorkspaceId = "" - gitOpsConfigBitbucket.BitBucketProjectKey = "" - } else { - return nil, err - } - } - config := &bean2.GitOpsConfigDto{ - GitRepoName: installedAppVersion.GitOpsRepoName, - BitBucketWorkspaceId: gitOpsConfigBitbucket.BitBucketProjectKey, - BitBucketProjectKey: gitOpsConfigBitbucket.BitBucketProjectKey, - } - repoUrl, err := impl.gitFactory.Client.GetRepoUrl(config) + + repoUrl, err := impl.gitOperationService.GetRepoUrlByRepoName(installedAppVersion.GitOpsRepoName) if err != nil { //will allow to continue to persist status on next operation - impl.logger.Errorw("fetching error", "err", err) + impl.logger.Errorw("error, GetRepoUrlByRepoName", "err", err) } + chartGitAttr.RepoUrl = repoUrl chartGitAttr.ChartLocation = fmt.Sprintf("%s-%s", installedAppVersion.AppName, environment.Name) installedAppVersion.ACDAppName = fmt.Sprintf("%s-%s", installedAppVersion.AppName, environment.Name) diff --git a/pkg/appStore/deployment/service/InstalledAppService_test.go b/pkg/appStore/deployment/service/InstalledAppService_test.go index b28d642ec68..7bf2ca08c3a 100644 --- a/pkg/appStore/deployment/service/InstalledAppService_test.go +++ b/pkg/appStore/deployment/service/InstalledAppService_test.go @@ -1,16 +1,15 @@ package service import ( + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git" "testing" pubsub "github.com/devtron-labs/common-lib/pubsub-lib" "github.com/devtron-labs/devtron/client/argocdServer" "github.com/devtron-labs/devtron/client/argocdServer/application" repository2 "github.com/devtron-labs/devtron/client/argocdServer/repository" - repository3 "github.com/devtron-labs/devtron/internal/sql/repository" "github.com/devtron-labs/devtron/internal/sql/repository/app" "github.com/devtron-labs/devtron/internal/util" - appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" repository5 "github.com/devtron-labs/devtron/pkg/appStore/chartGroup/repository" appStoreDeploymentFullMode "github.com/devtron-labs/devtron/pkg/appStore/deployment/fullMode" repository4 "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" @@ -29,7 +28,6 @@ func TestInstalledAppServiceImpl_DeployDefaultChartOnCluster(t *testing.T) { logger *zap.SugaredLogger installedAppRepository repository4.InstalledAppRepository chartTemplateService util.ChartTemplateService - refChartDir appStoreBean.RefChartProxyDir repositoryService repository2.ServiceClient appStoreApplicationVersionRepository appStoreDiscoverRepository.AppStoreApplicationVersionRepository environmentRepository repository.EnvironmentRepository @@ -42,9 +40,8 @@ func TestInstalledAppServiceImpl_DeployDefaultChartOnCluster(t *testing.T) { chartGroupDeploymentRepository repository5.ChartGroupDeploymentRepository envService cluster.EnvironmentService ArgoK8sClient argocdServer.ArgoK8sClient - gitFactory *util.GitFactory + gitFactory *git.GitFactory aCDAuthConfig *util2.ACDAuthConfig - gitOpsRepository repository3.GitOpsConfigRepository userService user.UserService appStoreDeploymentService AppStoreDeploymentService appStoreDeploymentFullModeService appStoreDeploymentFullMode.AppStoreDeploymentFullModeService @@ -67,9 +64,6 @@ func TestInstalledAppServiceImpl_DeployDefaultChartOnCluster(t *testing.T) { impl := &InstalledAppServiceImpl{ logger: tt.fields.logger, installedAppRepository: tt.fields.installedAppRepository, - chartTemplateService: tt.fields.chartTemplateService, - refChartDir: tt.fields.refChartDir, - repositoryService: tt.fields.repositoryService, appStoreApplicationVersionRepository: tt.fields.appStoreApplicationVersionRepository, environmentRepository: tt.fields.environmentRepository, teamRepository: tt.fields.teamRepository, @@ -77,13 +71,9 @@ func TestInstalledAppServiceImpl_DeployDefaultChartOnCluster(t *testing.T) { acdClient: tt.fields.acdClient, appStoreValuesService: tt.fields.appStoreValuesService, pubsubClient: tt.fields.pubsubClient, - tokenCache: tt.fields.tokenCache, chartGroupDeploymentRepository: tt.fields.chartGroupDeploymentRepository, envService: tt.fields.envService, - ArgoK8sClient: tt.fields.ArgoK8sClient, - gitFactory: tt.fields.gitFactory, aCDAuthConfig: tt.fields.aCDAuthConfig, - gitOpsRepository: tt.fields.gitOpsRepository, userService: tt.fields.userService, appStoreDeploymentService: tt.fields.appStoreDeploymentService, appStoreDeploymentFullModeService: tt.fields.appStoreDeploymentFullModeService, diff --git a/pkg/appStore/deployment/tool/AppStoreDeploymentArgoCdService.go b/pkg/appStore/deployment/tool/AppStoreDeploymentArgoCdService.go index a642133b86d..d3873c1aee5 100644 --- a/pkg/appStore/deployment/tool/AppStoreDeploymentArgoCdService.go +++ b/pkg/appStore/deployment/tool/AppStoreDeploymentArgoCdService.go @@ -5,6 +5,8 @@ import ( "encoding/json" "errors" "fmt" + commonBean "github.com/devtron-labs/devtron/pkg/deployment/gitOps/common/bean" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git" "net/http" "strings" "time" @@ -27,7 +29,6 @@ import ( "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" appStoreDiscoverRepository "github.com/devtron-labs/devtron/pkg/appStore/discover/repository" "github.com/devtron-labs/devtron/pkg/auth/user" - clusterRepository "github.com/devtron-labs/devtron/pkg/cluster/repository" "github.com/devtron-labs/devtron/pkg/sql" "github.com/go-pg/pg" "github.com/golang/protobuf/ptypes/timestamp" @@ -40,7 +41,7 @@ import ( type AppStoreDeploymentArgoCdService interface { //InstallApp(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ctx context.Context) (*appStoreBean.InstallAppVersionDTO, error) - InstallApp(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, chartGitAttr *util.ChartGitAttribute, ctx context.Context, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, error) + InstallApp(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, chartGitAttr *commonBean.ChartGitAttribute, ctx context.Context, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, error) DeleteInstalledApp(ctx context.Context, appName string, environmentName string, installAppVersionRequest *appStoreBean.InstallAppVersionDTO, installedApps *repository.InstalledApps, dbTransaction *pg.Tx) error RollbackRelease(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO, deploymentVersion int32, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, bool, error) GetDeploymentHistory(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO) (*client.HelmAppDeploymentHistory, error) @@ -49,7 +50,7 @@ type AppStoreDeploymentArgoCdService interface { DeleteDeploymentApp(ctx context.Context, appName string, environmentName string, installAppVersionRequest *appStoreBean.InstallAppVersionDTO) error UpdateInstalledAppAndPipelineStatusForFailedDeploymentStatus(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, triggeredAt time.Time, err error) error SaveTimelineForACDHelmApps(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, status string, statusDetail string, statusTime time.Time, tx *pg.Tx) error - UpdateAndSyncACDApps(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ChartGitAttribute *util.ChartGitAttribute, isMonoRepoMigrationRequired bool, ctx context.Context, tx *pg.Tx) error + UpdateAndSyncACDApps(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ChartGitAttribute *commonBean.ChartGitAttribute, isMonoRepoMigrationRequired bool, ctx context.Context, tx *pg.Tx) error } type AppStoreDeploymentArgoCdServiceImpl struct { @@ -59,7 +60,6 @@ type AppStoreDeploymentArgoCdServiceImpl struct { chartGroupDeploymentRepository repository2.ChartGroupDeploymentRepository installedAppRepository repository.InstalledAppRepository installedAppRepositoryHistory repository.InstalledAppVersionHistoryRepository - gitFactory *util.GitFactory appStoreDeploymentCommonService appStoreDeploymentCommon.AppStoreDeploymentCommonService helmAppService client.HelmAppService appStatusService appStatus.AppStatusService @@ -69,19 +69,19 @@ type AppStoreDeploymentArgoCdServiceImpl struct { appStoreApplicationVersionRepository appStoreDiscoverRepository.AppStoreApplicationVersionRepository argoClientWrapperService argocdServer.ArgoClientWrapperService acdConfig *argocdServer.ACDConfig + gitOperationService git.GitOperationService } func NewAppStoreDeploymentArgoCdServiceImpl(logger *zap.SugaredLogger, appStoreDeploymentFullModeService appStoreDeploymentFullMode.AppStoreDeploymentFullModeService, acdClient application2.ServiceClient, chartGroupDeploymentRepository repository2.ChartGroupDeploymentRepository, installedAppRepository repository.InstalledAppRepository, installedAppRepositoryHistory repository.InstalledAppVersionHistoryRepository, - gitFactory *util.GitFactory, appStoreDeploymentCommonService appStoreDeploymentCommon.AppStoreDeploymentCommonService, + appStoreDeploymentCommonService appStoreDeploymentCommon.AppStoreDeploymentCommonService, helmAppService client.HelmAppService, appStatusService appStatus.AppStatusService, - pipelineStatusTimelineService status.PipelineStatusTimelineService, + pipelineStatusTimelineService status.PipelineStatusTimelineService, userService user.UserService, pipelineStatusTimelineRepository pipelineConfig.PipelineStatusTimelineRepository, - userService user.UserService, appStoreApplicationVersionRepository appStoreDiscoverRepository.AppStoreApplicationVersionRepository, argoClientWrapperService argocdServer.ArgoClientWrapperService, acdConfig *argocdServer.ACDConfig, -) *AppStoreDeploymentArgoCdServiceImpl { + gitOperationService git.GitOperationService) *AppStoreDeploymentArgoCdServiceImpl { return &AppStoreDeploymentArgoCdServiceImpl{ Logger: logger, appStoreDeploymentFullModeService: appStoreDeploymentFullModeService, @@ -89,7 +89,6 @@ func NewAppStoreDeploymentArgoCdServiceImpl(logger *zap.SugaredLogger, appStoreD chartGroupDeploymentRepository: chartGroupDeploymentRepository, installedAppRepository: installedAppRepository, installedAppRepositoryHistory: installedAppRepositoryHistory, - gitFactory: gitFactory, appStoreDeploymentCommonService: appStoreDeploymentCommonService, helmAppService: helmAppService, appStatusService: appStatusService, @@ -99,11 +98,12 @@ func NewAppStoreDeploymentArgoCdServiceImpl(logger *zap.SugaredLogger, appStoreD appStoreApplicationVersionRepository: appStoreApplicationVersionRepository, argoClientWrapperService: argoClientWrapperService, acdConfig: acdConfig, + gitOperationService: gitOperationService, } } // UpdateAndSyncACDApps this will update chart info in acd app if required in case of mono repo migration and will refresh argo app -func (impl AppStoreDeploymentArgoCdServiceImpl) UpdateAndSyncACDApps(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ChartGitAttribute *util.ChartGitAttribute, isMonoRepoMigrationRequired bool, ctx context.Context, tx *pg.Tx) error { +func (impl AppStoreDeploymentArgoCdServiceImpl) UpdateAndSyncACDApps(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ChartGitAttribute *commonBean.ChartGitAttribute, isMonoRepoMigrationRequired bool, ctx context.Context, tx *pg.Tx) error { if isMonoRepoMigrationRequired { // update repo details on ArgoCD as repo is changed err := impl.UpdateChartInfo(installAppVersionRequest, ChartGitAttribute, 0, ctx) @@ -141,7 +141,7 @@ func (impl AppStoreDeploymentArgoCdServiceImpl) UpdateAndSyncACDApps(installAppV } // UpdateChartInfo this will update chart info in acd app, needed when repo for an app is changed -func (impl AppStoreDeploymentArgoCdServiceImpl) UpdateChartInfo(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ChartGitAttribute *util.ChartGitAttribute, installedAppVersionHistoryId int, ctx context.Context) error { +func (impl AppStoreDeploymentArgoCdServiceImpl) UpdateChartInfo(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ChartGitAttribute *commonBean.ChartGitAttribute, installedAppVersionHistoryId int, ctx context.Context) error { installAppVersionRequest, err := impl.patchAcdApp(ctx, installAppVersionRequest, ChartGitAttribute) if err != nil { return err @@ -174,7 +174,7 @@ func (impl AppStoreDeploymentArgoCdServiceImpl) SaveTimelineForACDHelmApps(insta return timelineErr } -func (impl AppStoreDeploymentArgoCdServiceImpl) InstallApp(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, chartGitAttr *util.ChartGitAttribute, ctx context.Context, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, error) { +func (impl AppStoreDeploymentArgoCdServiceImpl) InstallApp(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, chartGitAttr *commonBean.ChartGitAttribute, ctx context.Context, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, error) { installAppVersionRequest, err := impl.appStoreDeploymentFullModeService.AppStoreDeployOperationACD(installAppVersionRequest, chartGitAttr, ctx, tx) if err != nil { @@ -498,11 +498,11 @@ func (impl AppStoreDeploymentArgoCdServiceImpl) GetGitOpsRepoName(appName string return impl.appStoreDeploymentFullModeService.GetGitOpsRepoName(appName, environmentName) } -func (impl AppStoreDeploymentArgoCdServiceImpl) patchAcdApp(ctx context.Context, installAppVersionRequest *appStoreBean.InstallAppVersionDTO, chartGitAttr *util.ChartGitAttribute) (*appStoreBean.InstallAppVersionDTO, error) { +func (impl AppStoreDeploymentArgoCdServiceImpl) patchAcdApp(ctx context.Context, installAppVersionRequest *appStoreBean.InstallAppVersionDTO, chartGitAttr *commonBean.ChartGitAttribute) (*appStoreBean.InstallAppVersionDTO, error) { ctx, cancel := context.WithTimeout(ctx, 1*time.Minute) defer cancel() //registerInArgo - err := impl.appStoreDeploymentFullModeService.RegisterInArgo(chartGitAttr, ctx) + err := impl.argoClientWrapperService.RegisterGitOpsRepoInArgo(ctx, chartGitAttr.RepoUrl) if err != nil { impl.Logger.Errorw("error in argo registry", "err", err) return nil, err @@ -524,8 +524,7 @@ func (impl AppStoreDeploymentArgoCdServiceImpl) patchAcdApp(ctx context.Context, return installAppVersionRequest, nil } -func (impl AppStoreDeploymentArgoCdServiceImpl) updateValuesYaml(environment *clusterRepository.Environment, installedAppVersion *repository.InstalledAppVersions, - installAppVersionRequest *appStoreBean.InstallAppVersionDTO, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, error) { +func (impl AppStoreDeploymentArgoCdServiceImpl) updateValuesYaml(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, error) { appStoreAppVersion, err := impl.appStoreApplicationVersionRepository.FindById(installAppVersionRequest.AppStoreVersion) if err != nil { @@ -542,7 +541,7 @@ func (impl AppStoreDeploymentArgoCdServiceImpl) updateValuesYaml(environment *cl impl.Logger.Errorw("error in getting git config for helm app", "err", err) return nil, err } - gitHash, err := impl.appStoreDeploymentCommonService.CommitConfigToGit(valuesGitConfig) + gitHash, _, err := impl.gitOperationService.CommitValues(valuesGitConfig) if err != nil { impl.Logger.Errorw("error in git commit", "err", err) _ = impl.SaveTimelineForACDHelmApps(installAppVersionRequest, pipelineConfig.TIMELINE_STATUS_GIT_COMMIT_FAILED, fmt.Sprintf("Git commit failed - %v", err), time.Now(), tx) diff --git a/pkg/appStore/deployment/tool/AppStoreDeploymentHelmService.go b/pkg/appStore/deployment/tool/AppStoreDeploymentHelmService.go index fd94dbad262..e57416218ca 100644 --- a/pkg/appStore/deployment/tool/AppStoreDeploymentHelmService.go +++ b/pkg/appStore/deployment/tool/AppStoreDeploymentHelmService.go @@ -4,6 +4,8 @@ import ( "context" "errors" repository2 "github.com/devtron-labs/devtron/internal/sql/repository/dockerRegistry" + commonBean "github.com/devtron-labs/devtron/pkg/deployment/gitOps/common/bean" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git" "time" client "github.com/devtron-labs/devtron/api/helm-app" @@ -20,13 +22,13 @@ import ( ) type AppStoreDeploymentHelmService interface { - InstallApp(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, chartGitAttr *util.ChartGitAttribute, ctx context.Context, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, error) + InstallApp(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, chartGitAttr *commonBean.ChartGitAttribute, ctx context.Context, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, error) DeleteInstalledApp(ctx context.Context, appName string, environmentName string, installAppVersionRequest *appStoreBean.InstallAppVersionDTO, installedApps *repository.InstalledApps, dbTransaction *pg.Tx) error RollbackRelease(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO, deploymentVersion int32, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, bool, error) GetDeploymentHistory(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO) (*client.HelmAppDeploymentHistory, error) GetDeploymentHistoryInfo(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO, version int32) (*openapi.HelmAppDeploymentManifestDetail, error) DeleteDeploymentApp(ctx context.Context, appName string, environmentName string, installAppVersionRequest *appStoreBean.InstallAppVersionDTO) error - UpdateChartInfo(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ChartGitAttribute *util.ChartGitAttribute, installedAppVersionHistoryId int, ctx context.Context) error + UpdateChartInfo(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ChartGitAttribute *commonBean.ChartGitAttribute, installedAppVersionHistoryId int, ctx context.Context) error } type AppStoreDeploymentHelmServiceImpl struct { @@ -37,10 +39,15 @@ type AppStoreDeploymentHelmServiceImpl struct { installedAppRepository repository.InstalledAppRepository appStoreDeploymentCommonService appStoreDeploymentCommon.AppStoreDeploymentCommonService OCIRegistryConfigRepository repository2.OCIRegistryConfigRepository + gitOperationService git.GitOperationService } -func NewAppStoreDeploymentHelmServiceImpl(logger *zap.SugaredLogger, helmAppService client.HelmAppService, appStoreApplicationVersionRepository appStoreDiscoverRepository.AppStoreApplicationVersionRepository, - helmAppClient client.HelmAppClient, installedAppRepository repository.InstalledAppRepository, appStoreDeploymentCommonService appStoreDeploymentCommon.AppStoreDeploymentCommonService, OCIRegistryConfigRepository repository2.OCIRegistryConfigRepository) *AppStoreDeploymentHelmServiceImpl { +func NewAppStoreDeploymentHelmServiceImpl(logger *zap.SugaredLogger, helmAppService client.HelmAppService, + appStoreApplicationVersionRepository appStoreDiscoverRepository.AppStoreApplicationVersionRepository, + helmAppClient client.HelmAppClient, + installedAppRepository repository.InstalledAppRepository, appStoreDeploymentCommonService appStoreDeploymentCommon.AppStoreDeploymentCommonService, + OCIRegistryConfigRepository repository2.OCIRegistryConfigRepository, + gitOperationService git.GitOperationService) *AppStoreDeploymentHelmServiceImpl { return &AppStoreDeploymentHelmServiceImpl{ Logger: logger, helmAppService: helmAppService, @@ -49,10 +56,11 @@ func NewAppStoreDeploymentHelmServiceImpl(logger *zap.SugaredLogger, helmAppServ installedAppRepository: installedAppRepository, appStoreDeploymentCommonService: appStoreDeploymentCommonService, OCIRegistryConfigRepository: OCIRegistryConfigRepository, + gitOperationService: gitOperationService, } } -func (impl AppStoreDeploymentHelmServiceImpl) UpdateChartInfo(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ChartGitAttribute *util.ChartGitAttribute, installedAppVersionHistoryId int, ctx context.Context) error { +func (impl AppStoreDeploymentHelmServiceImpl) UpdateChartInfo(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ChartGitAttribute *commonBean.ChartGitAttribute, installedAppVersionHistoryId int, ctx context.Context) error { err := impl.updateApplicationWithChartInfo(ctx, installAppVersionRequest.InstalledAppId, installAppVersionRequest.AppStoreVersion, installAppVersionRequest.ValuesOverrideYaml, installedAppVersionHistoryId) if err != nil { impl.Logger.Errorw("error in updating helm app", "err", err) @@ -61,7 +69,7 @@ func (impl AppStoreDeploymentHelmServiceImpl) UpdateChartInfo(installAppVersionR return nil } -func (impl AppStoreDeploymentHelmServiceImpl) InstallApp(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, chartGitAttr *util.ChartGitAttribute, ctx context.Context, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, error) { +func (impl AppStoreDeploymentHelmServiceImpl) InstallApp(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, chartGitAttr *commonBean.ChartGitAttribute, ctx context.Context, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, error) { installAppVersionRequest.DeploymentAppType = util.PIPELINE_DEPLOYMENT_TYPE_HELM appStoreAppVersion, err := impl.appStoreApplicationVersionRepository.FindById(installAppVersionRequest.AppStoreVersion) if err != nil { @@ -266,7 +274,7 @@ func (impl *AppStoreDeploymentHelmServiceImpl) UpdateValuesDependencies(installA impl.Logger.Errorw("error in getting git config for helm app", "err", err) return err } - _, err = impl.appStoreDeploymentCommonService.CommitConfigToGit(valuesGitConfig) + _, _, err = impl.gitOperationService.CommitValues(valuesGitConfig) if err != nil { impl.Logger.Errorw("error in committing config to git for helm app", "err", err) return err @@ -365,6 +373,6 @@ func (impl *AppStoreDeploymentHelmServiceImpl) UpdateInstalledAppAndPipelineStat // TODO: Need to refactor this,refer below reason // This is being done as in ea mode wire argocd service is being binded to helmServiceImpl due to which we are restricted to implement this here. // RefreshAndUpdateACDApp this will update chart info in acd app if required in case of mono repo migration and will refresh argo app -func (impl *AppStoreDeploymentHelmServiceImpl) UpdateAndSyncACDApps(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ChartGitAttribute *util.ChartGitAttribute, isMonoRepoMigrationRequired bool, ctx context.Context, tx *pg.Tx) error { +func (impl *AppStoreDeploymentHelmServiceImpl) UpdateAndSyncACDApps(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ChartGitAttribute *commonBean.ChartGitAttribute, isMonoRepoMigrationRequired bool, ctx context.Context, tx *pg.Tx) error { return errors.New("this is not implemented") } diff --git a/pkg/bulkAction/BulkUpdateService.go b/pkg/bulkAction/BulkUpdateService.go index d696620d5a3..754cd140672 100644 --- a/pkg/bulkAction/BulkUpdateService.go +++ b/pkg/bulkAction/BulkUpdateService.go @@ -12,9 +12,7 @@ import ( client "github.com/devtron-labs/devtron/api/helm-app" openapi "github.com/devtron-labs/devtron/api/helm-app/openapiClient" "github.com/devtron-labs/devtron/client/argocdServer/application" - "github.com/devtron-labs/devtron/client/argocdServer/repository" "github.com/devtron-labs/devtron/internal/sql/models" - repository3 "github.com/devtron-labs/devtron/internal/sql/repository" "github.com/devtron-labs/devtron/internal/sql/repository/app" "github.com/devtron-labs/devtron/internal/sql/repository/appWorkflow" "github.com/devtron-labs/devtron/internal/sql/repository/bulkUpdate" @@ -23,9 +21,11 @@ import ( "github.com/devtron-labs/devtron/internal/util" appWorkflow2 "github.com/devtron-labs/devtron/pkg/appWorkflow" bean2 "github.com/devtron-labs/devtron/pkg/bean" - "github.com/devtron-labs/devtron/pkg/chart" chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository" repository2 "github.com/devtron-labs/devtron/pkg/cluster/repository" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deployedAppMetrics" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/chartRef" + bean3 "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/chartRef/bean" "github.com/devtron-labs/devtron/pkg/pipeline" pipeline1 "github.com/devtron-labs/devtron/pkg/pipeline" "github.com/devtron-labs/devtron/pkg/pipeline/history" @@ -67,29 +67,14 @@ type BulkUpdateServiceImpl struct { bulkUpdateRepository bulkUpdate.BulkUpdateRepository chartRepository chartRepoRepository.ChartRepository logger *zap.SugaredLogger - repoRepository chartRepoRepository.ChartRepoRepository - chartTemplateService util.ChartTemplateService - mergeUtil util.MergeUtil - repositoryService repository.ServiceClient - defaultChart chart.DefaultChart - chartRefRepository chartRepoRepository.ChartRefRepository - envOverrideRepository chartConfig.EnvConfigOverrideRepository - pipelineConfigRepository chartConfig.PipelineConfigRepository - configMapRepository chartConfig.ConfigMapRepository environmentRepository repository2.EnvironmentRepository pipelineRepository pipelineConfig.PipelineRepository - appLevelMetricsRepository repository3.AppLevelMetricsRepository - envLevelAppMetricsRepository repository3.EnvLevelAppMetricsRepository - client *http.Client appRepository app.AppRepository deploymentTemplateHistoryService history.DeploymentTemplateHistoryService configMapHistoryService history.ConfigMapHistoryService workflowDagExecutor pipeline.WorkflowDagExecutor - cdWorkflowRepository pipelineConfig.CdWorkflowRepository pipelineBuilder pipeline.PipelineBuilder - helmAppService client.HelmAppService enforcerUtil rbac.EnforcerUtil - enforcerUtilHelm rbac.EnforcerUtilHelm ciHandler pipeline.CiHandler ciPipelineRepository pipelineConfig.CiPipelineRepository appWorkflowRepository appWorkflow.AppWorkflowRepository @@ -97,65 +82,41 @@ type BulkUpdateServiceImpl struct { pubsubClient *pubsub.PubSubClientServiceImpl argoUserService argo.ArgoUserService scopedVariableManager variables.ScopedVariableManager + deployedAppMetricsService deployedAppMetrics.DeployedAppMetricsService + chartRefService chartRef.ChartRefService } func NewBulkUpdateServiceImpl(bulkUpdateRepository bulkUpdate.BulkUpdateRepository, chartRepository chartRepoRepository.ChartRepository, logger *zap.SugaredLogger, - chartTemplateService util.ChartTemplateService, - repoRepository chartRepoRepository.ChartRepoRepository, - defaultChart chart.DefaultChart, - mergeUtil util.MergeUtil, - repositoryService repository.ServiceClient, - chartRefRepository chartRepoRepository.ChartRefRepository, - envOverrideRepository chartConfig.EnvConfigOverrideRepository, - pipelineConfigRepository chartConfig.PipelineConfigRepository, - configMapRepository chartConfig.ConfigMapRepository, environmentRepository repository2.EnvironmentRepository, pipelineRepository pipelineConfig.PipelineRepository, - appLevelMetricsRepository repository3.AppLevelMetricsRepository, - envLevelAppMetricsRepository repository3.EnvLevelAppMetricsRepository, - client *http.Client, appRepository app.AppRepository, deploymentTemplateHistoryService history.DeploymentTemplateHistoryService, configMapHistoryService history.ConfigMapHistoryService, workflowDagExecutor pipeline.WorkflowDagExecutor, - cdWorkflowRepository pipelineConfig.CdWorkflowRepository, pipelineBuilder pipeline.PipelineBuilder, - helmAppService client.HelmAppService, enforcerUtil rbac.EnforcerUtil, - enforcerUtilHelm rbac.EnforcerUtilHelm, ciHandler pipeline.CiHandler, + pipelineBuilder pipeline.PipelineBuilder, + enforcerUtil rbac.EnforcerUtil, + ciHandler pipeline.CiHandler, ciPipelineRepository pipelineConfig.CiPipelineRepository, appWorkflowRepository appWorkflow.AppWorkflowRepository, appWorkflowService appWorkflow2.AppWorkflowService, pubsubClient *pubsub.PubSubClientServiceImpl, argoUserService argo.ArgoUserService, scopedVariableManager variables.ScopedVariableManager, -) (*BulkUpdateServiceImpl, error) { + deployedAppMetricsService deployedAppMetrics.DeployedAppMetricsService, + chartRefService chartRef.ChartRefService) (*BulkUpdateServiceImpl, error) { impl := &BulkUpdateServiceImpl{ bulkUpdateRepository: bulkUpdateRepository, chartRepository: chartRepository, logger: logger, - chartTemplateService: chartTemplateService, - repoRepository: repoRepository, - mergeUtil: mergeUtil, - defaultChart: defaultChart, - repositoryService: repositoryService, - chartRefRepository: chartRefRepository, - envOverrideRepository: envOverrideRepository, - pipelineConfigRepository: pipelineConfigRepository, - configMapRepository: configMapRepository, environmentRepository: environmentRepository, pipelineRepository: pipelineRepository, - appLevelMetricsRepository: appLevelMetricsRepository, - envLevelAppMetricsRepository: envLevelAppMetricsRepository, - client: client, appRepository: appRepository, deploymentTemplateHistoryService: deploymentTemplateHistoryService, configMapHistoryService: configMapHistoryService, workflowDagExecutor: workflowDagExecutor, - cdWorkflowRepository: cdWorkflowRepository, pipelineBuilder: pipelineBuilder, - helmAppService: helmAppService, enforcerUtil: enforcerUtil, - enforcerUtilHelm: enforcerUtilHelm, ciHandler: ciHandler, ciPipelineRepository: ciPipelineRepository, appWorkflowRepository: appWorkflowRepository, @@ -163,6 +124,8 @@ func NewBulkUpdateServiceImpl(bulkUpdateRepository bulkUpdate.BulkUpdateReposito pubsubClient: pubsubClient, argoUserService: argoUserService, scopedVariableManager: scopedVariableManager, + deployedAppMetricsService: deployedAppMetricsService, + chartRefService: chartRefService, } err := impl.SubscribeToCdBulkTriggerTopic() @@ -458,12 +421,10 @@ func (impl BulkUpdateServiceImpl) BulkUpdateDeploymentTemplate(bulkUpdatePayload deploymentTemplateBulkUpdateResponse.Successful = append(deploymentTemplateBulkUpdateResponse.Successful, bulkUpdateSuccessResponse) //creating history entry for deployment template - appLevelAppMetricsEnabled := false - appLevelMetrics, err := impl.appLevelMetricsRepository.FindByAppId(chart.AppId) - if err != nil && err != pg.ErrNoRows { - impl.logger.Errorw("error in getting app level metrics app level", "error", err) - } else if err == nil { - appLevelAppMetricsEnabled = appLevelMetrics.AppMetrics + appLevelAppMetricsEnabled, err := impl.deployedAppMetricsService.GetMetricsFlagByAppId(chart.AppId) + if err != nil { + impl.logger.Errorw("error in getting app level metrics app level", "error", err, "appId", chart.AppId) + return nil } chart.GlobalOverride = modified chart.Values = modified @@ -526,22 +487,13 @@ func (impl BulkUpdateServiceImpl) BulkUpdateDeploymentTemplate(bulkUpdatePayload deploymentTemplateBulkUpdateResponse.Successful = append(deploymentTemplateBulkUpdateResponse.Successful, bulkUpdateSuccessResponse) //creating history entry for deployment template - envLevelAppMetricsEnabled := false - envLevelAppMetrics, err := impl.envLevelAppMetricsRepository.FindByAppIdAndEnvId(chartEnv.Chart.AppId, chartEnv.TargetEnvironment) - if err != nil && err != pg.ErrNoRows { - impl.logger.Errorw("error in getting env level app metrics", "err", err, "appId", chartEnv.Chart.AppId, "envId", chartEnv.TargetEnvironment) - } else if err == pg.ErrNoRows { - appLevelAppMetrics, err := impl.appLevelMetricsRepository.FindByAppId(chartEnv.Chart.AppId) - if err != nil && err != pg.ErrNoRows { - impl.logger.Errorw("error in getting app level app metrics", "err", err, "appId", chartEnv.Chart.AppId) - } else if err == nil { - envLevelAppMetricsEnabled = appLevelAppMetrics.AppMetrics - } - } else { - envLevelAppMetricsEnabled = *envLevelAppMetrics.AppMetrics + isAppMetricsEnabled, err := impl.deployedAppMetricsService.GetMetricsFlagForAPipelineByAppIdAndEnvId(chartEnv.Chart.AppId, chartEnv.TargetEnvironment) + if err != nil { + impl.logger.Errorw("error, GetMetricsFlagForAPipelineByAppIdAndEnvId", "err", err, "appId", chartEnv.Chart.AppId, "envId", chartEnv.TargetEnvironment) + return nil } chartEnv.EnvOverrideValues = modified - err = impl.deploymentTemplateHistoryService.CreateDeploymentTemplateHistoryFromEnvOverrideTemplate(chartEnv, nil, envLevelAppMetricsEnabled, 0) + err = impl.deploymentTemplateHistoryService.CreateDeploymentTemplateHistoryFromEnvOverrideTemplate(chartEnv, nil, isAppMetricsEnabled, 0) if err != nil { impl.logger.Errorw("error in creating entry for env deployment template history", "err", err, "envOverride", chartEnv) } @@ -1118,14 +1070,14 @@ func (impl BulkUpdateServiceImpl) buildHibernateUnHibernateRequestForHelmPipelin } hibernateRequest := &openapi.HibernateRequest{} - chartInfo, err := impl.chartRefRepository.FetchInfoOfChartConfiguredInApp(pipeline.AppId) + chartInfo, err := impl.chartRefService.FetchInfoOfChartConfiguredInApp(pipeline.AppId) if err != nil { impl.logger.Errorw("error in getting chart info for chart configured in app", "err", err, "appId", pipeline.AppId) return nil, nil, err } var group, kind, version, name string name = fmt.Sprintf("%s-%s", pipeline.App.AppName, pipeline.Environment.Name) - if chartInfo.Name == "" && chartInfo.UserUploaded == false { + if chartInfo.Name == bean3.RolloutChartType && chartInfo.UserUploaded == false { // rollout type chart group = "argoproj.io" kind = "Rollout" @@ -1141,7 +1093,7 @@ func (impl BulkUpdateServiceImpl) buildHibernateUnHibernateRequestForHelmPipelin }, }, } - } else if chartInfo.Name == "Deployment" { + } else if chartInfo.Name == bean3.DeploymentChartType { //deployment type chart group = "apps" kind = "Deployment" diff --git a/pkg/chart/ChartCompatibility_test.go b/pkg/chart/ChartCompatibility_test.go index 95005d19165..5bafe12b0f6 100644 --- a/pkg/chart/ChartCompatibility_test.go +++ b/pkg/chart/ChartCompatibility_test.go @@ -1,6 +1,8 @@ package chart import ( + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/chartRef" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/chartRef/bean" "reflect" "testing" ) @@ -18,8 +20,8 @@ func Test_checkCompatibility(t *testing.T) { { name: "when charts are compatible, it should return true", args: args{ - oldChartType: DeploymentChartType, - newChartType: RolloutChartType, + oldChartType: bean.DeploymentChartType, + newChartType: bean.RolloutChartType, }, want: true, }, @@ -27,14 +29,14 @@ func Test_checkCompatibility(t *testing.T) { name: "when oldChart is not found, it should return false", args: args{ oldChartType: "Sdfasdf", - newChartType: RolloutChartType, + newChartType: bean.RolloutChartType, }, want: false, }, { name: "when newChart is not found, it should return false", args: args{ - oldChartType: DeploymentChartType, + oldChartType: bean.DeploymentChartType, newChartType: "random sdfasdf saldfj", }, want: false, @@ -42,7 +44,7 @@ func Test_checkCompatibility(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := CheckCompatibility(tt.args.oldChartType, tt.args.newChartType); got != tt.want { + if got := chartRef.CheckCompatibility(tt.args.oldChartType, tt.args.newChartType); got != tt.want { t.Errorf("checkCompatibility() = %v, want %v", got, tt.want) } }) @@ -68,14 +70,14 @@ func TestCompatibleChartsWith(t *testing.T) { { name: "when chart is found, it should return a slice of all cpmpatible chartIds", args: args{ - chartType: DeploymentChartType, + chartType: bean.DeploymentChartType, }, - want: []string{RolloutChartType}, + want: []string{bean.RolloutChartType}, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := CompatibleChartsWith(tt.args.chartType); !reflect.DeepEqual(got, tt.want) { + if got := chartRef.CompatibleChartsWith(tt.args.chartType); !reflect.DeepEqual(got, tt.want) { t.Errorf("CompatibleChartsWith() = %v, want %v", got, tt.want) } }) diff --git a/pkg/chart/ChartService.go b/pkg/chart/ChartService.go index a728aef48a2..ee67b5b7708 100644 --- a/pkg/chart/ChartService.go +++ b/pkg/chart/ChartService.go @@ -22,48 +22,34 @@ import ( "context" "encoding/json" "fmt" - "github.com/devtron-labs/devtron/pkg/resourceQualifiers" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deployedAppMetrics" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deployedAppMetrics/bean" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/chartRef" + bean2 "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/chartRef/bean" "github.com/devtron-labs/devtron/pkg/variables" - "github.com/devtron-labs/devtron/pkg/variables/parsers" repository5 "github.com/devtron-labs/devtron/pkg/variables/repository" "go.opentelemetry.io/otel" - "github.com/devtron-labs/devtron/internal/constants" - //"github.com/devtron-labs/devtron/pkg/pipeline" "github.com/devtron-labs/devtron/internal/sql/repository/app" chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository" "github.com/devtron-labs/devtron/pkg/pipeline/history" - "io/ioutil" - "net/http" - "os" - "path" "path/filepath" "strconv" "strings" "time" - repository4 "github.com/devtron-labs/devtron/pkg/cluster/repository" - "github.com/devtron-labs/devtron/pkg/sql" - dirCopy "github.com/otiai10/copy" - - repository2 "github.com/argoproj/argo-cd/v2/pkg/apiclient/repository" - "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" - "github.com/devtron-labs/devtron/client/argocdServer/repository" "github.com/devtron-labs/devtron/internal/sql/models" - repository3 "github.com/devtron-labs/devtron/internal/sql/repository" "github.com/devtron-labs/devtron/internal/sql/repository/chartConfig" - "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig" "github.com/devtron-labs/devtron/internal/util" - util2 "github.com/devtron-labs/devtron/util" + repository4 "github.com/devtron-labs/devtron/pkg/cluster/repository" + "github.com/devtron-labs/devtron/pkg/sql" "github.com/go-pg/pg" "github.com/juju/errors" - "github.com/xeipuuv/gojsonschema" "go.uber.org/zap" - "k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/proto/hapi/chart" "sigs.k8s.io/yaml" ) @@ -73,33 +59,16 @@ type ChartService interface { CreateChartFromEnvOverride(templateRequest TemplateRequest, ctx context.Context) (chart *TemplateRequest, err error) FindLatestChartForAppByAppId(appId int) (chartTemplate *TemplateRequest, err error) GetByAppIdAndChartRefId(appId int, chartRefId int) (chartTemplate *TemplateRequest, err error) - GetAppOverrideForDefaultTemplate(chartRefId int) (map[string]interface{}, string, error) UpdateAppOverride(ctx context.Context, templateRequest *TemplateRequest) (*TemplateRequest, error) IsReadyToTrigger(appId int, envId int, pipelineId int) (IsReady, error) - ChartRefAutocomplete() ([]ChartRef, error) - ChartRefAutocompleteForAppOrEnv(appId int, envId int) (*ChartRefResponse, error) FindPreviousChartByAppId(appId int) (chartTemplate *TemplateRequest, err error) UpgradeForApp(appId int, chartRefId int, newAppOverride map[string]interface{}, userId int32, ctx context.Context) (bool, error) - AppMetricsEnableDisable(appMetricRequest AppMetricEnableDisableRequest) (*AppMetricEnableDisableRequest, error) - DeploymentTemplateValidate(ctx context.Context, templatejson interface{}, chartRefId int, scope resourceQualifiers.Scope) (bool, error) - JsonSchemaExtractFromFile(chartRefId int) (map[string]interface{}, string, error) - GetSchemaAndReadmeForTemplateByChartRefId(chartRefId int) (schema []byte, readme []byte, err error) - ExtractChartIfMissing(chartData []byte, refChartDir string, location string) (*ChartDataInfo, error) - CheckChartExists(chartRefId int) error - CheckIsAppMetricsSupported(chartRefId int) (bool, error) - GetLocationFromChartNameAndVersion(chartName string, chartVersion string) string - FormatChartName(chartName string) string - ValidateUploadedFileFormat(fileName string) error - ReadChartMetaDataForLocation(chartDir string, fileName string) (*ChartYamlStruct, error) - RegisterInArgo(chartGitAttribute *util.ChartGitAttribute, ctx context.Context) error - FetchCustomChartsInfo() ([]*ChartDto, error) - CheckCustomChartByAppId(id int) (bool, error) - CheckCustomChartByChartId(id int) (bool, error) - ChartRefIdsCompatible(oldChartRefId int, newChartRefId int) (bool, string, string) + CheckIfChartRefUserUploadedByAppId(id int) (bool, error) PatchEnvOverrides(values json.RawMessage, oldChartType string, newChartType string) (json.RawMessage, error) - FlaggerCanaryEnabled(values json.RawMessage) (bool, error) - GetCustomChartInBytes(chatRefId int) ([]byte, error) - GetRefChart(templateRequest TemplateRequest) (string, string, error, string, string) + + ChartRefAutocompleteForAppOrEnv(appId int, envId int) (*bean2.ChartRefAutocompleteResponse, error) + + UpdateGitRepoUrlInCharts(appId int, repoUrl, chartLocation string, userId int32) error } type ChartServiceImpl struct { @@ -109,20 +78,13 @@ type ChartServiceImpl struct { chartTemplateService util.ChartTemplateService pipelineGroupRepository app.AppRepository mergeUtil util.MergeUtil - repositoryService repository.ServiceClient - refChartDir chartRepoRepository.RefChartDir - defaultChart DefaultChart - chartRefRepository chartRepoRepository.ChartRefRepository envOverrideRepository chartConfig.EnvConfigOverrideRepository pipelineConfigRepository chartConfig.PipelineConfigRepository - configMapRepository chartConfig.ConfigMapRepository environmentRepository repository4.EnvironmentRepository - pipelineRepository pipelineConfig.PipelineRepository - appLevelMetricsRepository repository3.AppLevelMetricsRepository - envLevelAppMetricsRepository repository3.EnvLevelAppMetricsRepository - client *http.Client deploymentTemplateHistoryService history.DeploymentTemplateHistoryService scopedVariableManager variables.ScopedVariableManager + deployedAppMetricsService deployedAppMetrics.DeployedAppMetricsService + chartRefService chartRef.ChartRefService } func NewChartServiceImpl(chartRepository chartRepoRepository.ChartRepository, @@ -130,27 +92,14 @@ func NewChartServiceImpl(chartRepository chartRepoRepository.ChartRepository, chartTemplateService util.ChartTemplateService, repoRepository chartRepoRepository.ChartRepoRepository, pipelineGroupRepository app.AppRepository, - refChartDir chartRepoRepository.RefChartDir, - defaultChart DefaultChart, mergeUtil util.MergeUtil, - repositoryService repository.ServiceClient, - chartRefRepository chartRepoRepository.ChartRefRepository, envOverrideRepository chartConfig.EnvConfigOverrideRepository, pipelineConfigRepository chartConfig.PipelineConfigRepository, - configMapRepository chartConfig.ConfigMapRepository, environmentRepository repository4.EnvironmentRepository, - pipelineRepository pipelineConfig.PipelineRepository, - appLevelMetricsRepository repository3.AppLevelMetricsRepository, - envLevelAppMetricsRepository repository3.EnvLevelAppMetricsRepository, - client *http.Client, deploymentTemplateHistoryService history.DeploymentTemplateHistoryService, scopedVariableManager variables.ScopedVariableManager, -) *ChartServiceImpl { - - // cache devtron reference charts list - devtronChartList, _ := chartRefRepository.FetchAllChartInfoByUploadFlag(false) - SetReservedChartList(devtronChartList) - + deployedAppMetricsService deployedAppMetrics.DeployedAppMetricsService, + chartRefService chartRef.ChartRefService) *ChartServiceImpl { return &ChartServiceImpl{ chartRepository: chartRepository, logger: logger, @@ -158,149 +107,22 @@ func NewChartServiceImpl(chartRepository chartRepoRepository.ChartRepository, repoRepository: repoRepository, pipelineGroupRepository: pipelineGroupRepository, mergeUtil: mergeUtil, - refChartDir: refChartDir, - defaultChart: defaultChart, - repositoryService: repositoryService, - chartRefRepository: chartRefRepository, envOverrideRepository: envOverrideRepository, pipelineConfigRepository: pipelineConfigRepository, - configMapRepository: configMapRepository, environmentRepository: environmentRepository, - pipelineRepository: pipelineRepository, - appLevelMetricsRepository: appLevelMetricsRepository, - envLevelAppMetricsRepository: envLevelAppMetricsRepository, - client: client, deploymentTemplateHistoryService: deploymentTemplateHistoryService, scopedVariableManager: scopedVariableManager, + deployedAppMetricsService: deployedAppMetricsService, + chartRefService: chartRefService, } } -func (impl ChartServiceImpl) ChartRefIdsCompatible(oldChartRefId int, newChartRefId int) (bool, string, string) { - oldChart, err := impl.chartRefRepository.FindById(oldChartRefId) - if err != nil { - return false, "", "" - } - newChart, err := impl.chartRefRepository.FindById(newChartRefId) - if err != nil { - return false, "", "" - } - if len(oldChart.Name) == 0 { - oldChart.Name = RolloutChartType - } - if len(newChart.Name) == 0 { - newChart.Name = RolloutChartType - } - return CheckCompatibility(oldChart.Name, newChart.Name), oldChart.Name, newChart.Name -} - -func (impl ChartServiceImpl) FlaggerCanaryEnabled(values json.RawMessage) (bool, error) { - var jsonMap map[string]json.RawMessage - if err := json.Unmarshal([]byte(values), &jsonMap); err != nil { - return false, err - } - - flaggerCanary, found := jsonMap["flaggerCanary"] - if !found { - return false, nil - } - var flaggerCanaryUnmarshalled map[string]json.RawMessage - if err := json.Unmarshal([]byte(flaggerCanary), &flaggerCanaryUnmarshalled); err != nil { - return false, err - } - enabled, found := flaggerCanaryUnmarshalled["enabled"] - if !found { - return true, fmt.Errorf("flagger canary enabled field must be set and be equal to false") - } - return string(enabled) == "true", nil -} func (impl ChartServiceImpl) PatchEnvOverrides(values json.RawMessage, oldChartType string, newChartType string) (json.RawMessage, error) { return PatchWinterSoldierConfig(values, newChartType) } -func (impl ChartServiceImpl) GetSchemaAndReadmeForTemplateByChartRefId(chartRefId int) ([]byte, []byte, error) { - refChart, _, err, _, _ := impl.GetRefChart(TemplateRequest{ChartRefId: chartRefId}) - if err != nil { - impl.logger.Errorw("error in getting refChart", "err", err, "chartRefId", chartRefId) - return nil, nil, err - } - var schemaByte []byte - var readmeByte []byte - err = impl.CheckChartExists(chartRefId) - if err != nil { - impl.logger.Errorw("error in getting refChart", "err", err, "chartRefId", chartRefId) - return nil, nil, err - } - schemaByte, err = ioutil.ReadFile(filepath.Clean(filepath.Join(refChart, "schema.json"))) - if err != nil { - impl.logger.Errorw("error in reading schema.json file for refChart", "err", err, "chartRefId", chartRefId) - } - readmeByte, err = ioutil.ReadFile(filepath.Clean(filepath.Join(refChart, "README.md"))) - if err != nil { - impl.logger.Errorw("error in reading readme file for refChart", "err", err, "chartRefId", chartRefId) - } - return schemaByte, readmeByte, nil -} - -func (impl ChartServiceImpl) GetAppOverrideForDefaultTemplate(chartRefId int) (map[string]interface{}, string, error) { - err := impl.CheckChartExists(chartRefId) - if err != nil { - impl.logger.Errorw("error in getting missing chart for chartRefId", "err", err, "chartRefId") - return nil, "", err - } - - refChart, _, err, _, _ := impl.GetRefChart(TemplateRequest{ChartRefId: chartRefId}) - if err != nil { - return nil, "", err - } - var appOverrideByte, envOverrideByte []byte - appOverrideByte, err = ioutil.ReadFile(filepath.Clean(filepath.Join(refChart, "app-values.yaml"))) - if err != nil { - impl.logger.Infow("App values yaml file is missing") - } else { - appOverrideByte, err = yaml.YAMLToJSON(appOverrideByte) - if err != nil { - return nil, "", err - } - } - - envOverrideByte, err = ioutil.ReadFile(filepath.Clean(filepath.Join(refChart, "env-values.yaml"))) - if err != nil { - impl.logger.Infow("Env values yaml file is missing") - } else { - envOverrideByte, err = yaml.YAMLToJSON(envOverrideByte) - if err != nil { - return nil, "", err - } - } - - messages := make(map[string]interface{}) - var merged []byte - if appOverrideByte == nil && envOverrideByte == nil { - return messages, "", nil - } else if appOverrideByte == nil || envOverrideByte == nil { - if appOverrideByte == nil { - merged = envOverrideByte - } else { - merged = appOverrideByte - } - } else { - merged, err = impl.mergeUtil.JsonPatch(appOverrideByte, []byte(envOverrideByte)) - if err != nil { - return nil, "", err - } - } - - appOverride := json.RawMessage(merged) - messages["defaultAppOverride"] = appOverride - return messages, string(merged), nil -} - -type AppMetricsEnabled struct { - AppMetrics bool `json:"app-metrics"` -} - func (impl ChartServiceImpl) Create(templateRequest TemplateRequest, ctx context.Context) (*TemplateRequest, error) { - err := impl.CheckChartExists(templateRequest.ChartRefId) + err := impl.chartRefService.CheckChartExists(templateRequest.ChartRefId) if err != nil { impl.logger.Errorw("error in getting missing chart for chartRefId", "err", err, "chartRefId") return nil, err @@ -318,7 +140,7 @@ func (impl ChartServiceImpl) Create(templateRequest TemplateRequest, ctx context return nil, err } - refChart, templateName, err, _, pipelineStrategyPath := impl.GetRefChart(templateRequest) + refChart, templateName, _, pipelineStrategyPath, err := impl.chartRefService.GetRefChart(templateRequest.ChartRefId) if err != nil { return nil, err } @@ -377,7 +199,7 @@ func (impl ChartServiceImpl) Create(templateRequest TemplateRequest, ctx context if err != nil { return nil, err } - chartValues, _, err := impl.chartTemplateService.FetchValuesFromReferenceChart(chartMeta, refChart, templateName, templateRequest.UserId, pipelineStrategyPath) + chartValues, err := impl.chartTemplateService.FetchValuesFromReferenceChart(chartMeta, refChart, templateName, templateRequest.UserId, pipelineStrategyPath) if err != nil { return nil, err } @@ -446,33 +268,24 @@ func (impl ChartServiceImpl) Create(templateRequest TemplateRequest, ctx context return nil, err } - var appLevelMetrics *repository3.AppLevelMetrics - isAppMetricsSupported, err := impl.CheckIsAppMetricsSupported(templateRequest.ChartRefId) + appLevelMetricsUpdateReq := &bean.DeployedAppMetricsRequest{ + EnableMetrics: templateRequest.IsAppMetricsEnabled, + AppId: templateRequest.AppId, + ChartRefId: templateRequest.ChartRefId, + UserId: templateRequest.UserId, + } + err = impl.deployedAppMetricsService.CreateOrUpdateAppOrEnvLevelMetrics(ctx, appLevelMetricsUpdateReq) if err != nil { + impl.logger.Errorw("error, CheckAndUpdateAppOrEnvLevelMetrics", "err", err, "req", appLevelMetricsUpdateReq) return nil, err } - if !(isAppMetricsSupported) { - appMetricsRequest := AppMetricEnableDisableRequest{UserId: templateRequest.UserId, AppId: templateRequest.AppId, IsAppMetricsEnabled: false} - appLevelMetrics, err = impl.updateAppLevelMetrics(&appMetricsRequest) - if err != nil { - impl.logger.Errorw("err while disable app metrics for lower versions", "err", err) - return nil, err - } - } else { - appMetricsRequest := AppMetricEnableDisableRequest{UserId: templateRequest.UserId, AppId: templateRequest.AppId, IsAppMetricsEnabled: templateRequest.IsAppMetricsEnabled} - appLevelMetrics, err = impl.updateAppLevelMetrics(&appMetricsRequest) - if err != nil { - impl.logger.Errorw("err while updating app metrics", "err", err) - return nil, err - } - } - chartVal, err := impl.chartAdaptor(chart, appLevelMetrics) + chartVal, err := impl.chartAdaptor(chart, appLevelMetricsUpdateReq.EnableMetrics) return chartVal, err } func (impl ChartServiceImpl) CreateChartFromEnvOverride(templateRequest TemplateRequest, ctx context.Context) (*TemplateRequest, error) { - err := impl.CheckChartExists(templateRequest.ChartRefId) + err := impl.chartRefService.CheckChartExists(templateRequest.ChartRefId) if err != nil { impl.logger.Errorw("error in getting missing chart for chartRefId", "err", err, "chartRefId") return nil, err @@ -493,7 +306,7 @@ func (impl ChartServiceImpl) CreateChartFromEnvOverride(templateRequest Template return nil, err } - refChart, templateName, err, _, pipelineStrategyPath := impl.GetRefChart(templateRequest) + refChart, templateName, _, pipelineStrategyPath, err := impl.chartRefService.GetRefChart(templateRequest.ChartRefId) if err != nil { return nil, err } @@ -509,7 +322,7 @@ func (impl ChartServiceImpl) CreateChartFromEnvOverride(templateRequest Template if err != nil { return nil, err } - chartValues, _, err := impl.chartTemplateService.FetchValuesFromReferenceChart(chartMeta, refChart, templateName, templateRequest.UserId, pipelineStrategyPath) + chartValues, err := impl.chartTemplateService.FetchValuesFromReferenceChart(chartMeta, refChart, templateName, templateRequest.UserId, pipelineStrategyPath) if err != nil { return nil, err } @@ -583,31 +396,15 @@ func (impl ChartServiceImpl) CreateChartFromEnvOverride(templateRequest Template return nil, err } - chartVal, err := impl.chartAdaptor(chart, nil) + chartVal, err := impl.chartAdaptor(chart, false) return chartVal, err } -func (impl ChartServiceImpl) RegisterInArgo(chartGitAttribute *util.ChartGitAttribute, ctx context.Context) error { - repo := &v1alpha1.Repository{ - Repo: chartGitAttribute.RepoUrl, - } - repo, err := impl.repositoryService.Create(ctx, &repository2.RepoCreateRequest{Repo: repo, Upsert: true}) - if err != nil { - impl.logger.Errorw("error in creating argo Repository ", "err", err) - } - impl.logger.Infow("repo registered in argo", "name", chartGitAttribute.RepoUrl) - return err -} - // converts db object to bean -func (impl ChartServiceImpl) chartAdaptor(chart *chartRepoRepository.Chart, appLevelMetrics *repository3.AppLevelMetrics) (*TemplateRequest, error) { - var appMetrics bool +func (impl ChartServiceImpl) chartAdaptor(chart *chartRepoRepository.Chart, isAppMetricsEnabled bool) (*TemplateRequest, error) { if chart == nil || chart.Id == 0 { return &TemplateRequest{}, &util.ApiError{UserMessage: "no chart found"} } - if appLevelMetrics != nil { - appMetrics = appLevelMetrics.AppMetrics - } return &TemplateRequest{ RefChartTemplate: chart.ReferenceTemplate, Id: chart.Id, @@ -617,7 +414,7 @@ func (impl ChartServiceImpl) chartAdaptor(chart *chartRepoRepository.Chart, appL RefChartTemplateVersion: impl.getParentChartVersion(chart.ChartVersion), Latest: chart.Latest, ChartRefId: chart.ChartRefId, - IsAppMetricsEnabled: appMetrics, + IsAppMetricsEnabled: isAppMetricsEnabled, IsBasicViewLocked: chart.IsBasicViewLocked, CurrentViewEditor: chart.CurrentViewEditor, }, nil @@ -633,78 +430,6 @@ func (impl ChartServiceImpl) getChartMetaData(templateRequest TemplateRequest) ( } return metadata, err } -func (impl ChartServiceImpl) GetRefChart(templateRequest TemplateRequest) (string, string, error, string, string) { - var template string - var version string - //path of file in chart from where strategy config is to be taken - var pipelineStrategyPath string - if templateRequest.ChartRefId > 0 { - chartRef, err := impl.chartRefRepository.FindById(templateRequest.ChartRefId) - if err != nil { - chartRef, err = impl.chartRefRepository.GetDefault() - if err != nil { - return "", "", err, "", "" - } - } else if chartRef.UserUploaded { - refChartLocation := filepath.Join(string(impl.refChartDir), chartRef.Location) - if _, err := os.Stat(refChartLocation); os.IsNotExist(err) { - chartInfo, err := impl.ExtractChartIfMissing(chartRef.ChartData, string(impl.refChartDir), chartRef.Location) - if chartInfo != nil && chartInfo.TemporaryFolder != "" { - err1 := os.RemoveAll(chartInfo.TemporaryFolder) - if err1 != nil { - impl.logger.Errorw("error in deleting temp dir ", "err", err) - } - } - if err != nil { - impl.logger.Errorw("Error regarding uploaded chart", "err", err) - return "", "", err, "", "" - } - - } - } - template = chartRef.Location - version = chartRef.Version - pipelineStrategyPath = chartRef.DeploymentStrategyPath - } else { - chartRef, err := impl.chartRefRepository.GetDefault() - if err != nil { - return "", "", err, "", "" - } - template = chartRef.Location - version = chartRef.Version - pipelineStrategyPath = chartRef.DeploymentStrategyPath - } - - //TODO VIKI- fetch from chart ref table - chartPath := path.Join(string(impl.refChartDir), template) - valid, err := chartutil.IsChartDir(chartPath) - if err != nil || !valid { - impl.logger.Errorw("invalid base chart", "dir", chartPath, "err", err) - return "", "", err, "", "" - } - return chartPath, template, nil, version, pipelineStrategyPath -} - -func (impl ChartServiceImpl) getRefChartVersion(templateRequest TemplateRequest) (string, error) { - var version string - if templateRequest.ChartRefId > 0 { - chartRef, err := impl.chartRefRepository.FindById(templateRequest.ChartRefId) - if err != nil { - chartRef, err = impl.chartRefRepository.GetDefault() - if err != nil { - return "", err - } - } - version = chartRef.Version - } else { - chartRef, err := impl.chartRefRepository.GetDefault() - if err != nil { - return "", err - } - version = chartRef.Location - } - return version, nil -} func (impl ChartServiceImpl) getChartRepo(templateRequest TemplateRequest) (*chartRepoRepository.ChartRepo, error) { if templateRequest.ChartRepositoryId == 0 { @@ -760,14 +485,12 @@ func (impl ChartServiceImpl) FindLatestChartForAppByAppId(appId int) (chartTempl impl.logger.Errorw("error in fetching chart ", "appId", appId, "err", err) return nil, err } - - appMetrics, err := impl.appLevelMetricsRepository.FindByAppId(appId) - if err != nil && !util.IsErrNoRows(err) { + isAppMetricsEnabled, err := impl.deployedAppMetricsService.GetMetricsFlagByAppId(appId) + if err != nil { impl.logger.Errorw("error in fetching app-metrics", "appId", appId, "err", err) return nil, err } - - chartTemplate, err = impl.chartAdaptor(chart, appMetrics) + chartTemplate, err = impl.chartAdaptor(chart, isAppMetricsEnabled) return chartTemplate, err } @@ -777,12 +500,12 @@ func (impl ChartServiceImpl) GetByAppIdAndChartRefId(appId int, chartRefId int) impl.logger.Errorw("error in fetching chart ", "appId", appId, "err", err) return nil, err } - appLevelMetrics, err := impl.appLevelMetricsRepository.FindByAppId(appId) - if err != nil && !util.IsErrNoRows(err) { - impl.logger.Errorw("error in fetching app metrics flag", "err", err) + isAppMetricsEnabled, err := impl.deployedAppMetricsService.GetMetricsFlagByAppId(appId) + if err != nil { + impl.logger.Errorw("error in fetching app-metrics", "appId", appId, "err", err) return nil, err } - chartTemplate, err = impl.chartAdaptor(chart, appLevelMetrics) + chartTemplate, err = impl.chartAdaptor(chart, isAppMetricsEnabled) return chartTemplate, err } @@ -870,33 +593,20 @@ func (impl ChartServiceImpl) UpdateAppOverride(ctx context.Context, templateRequ return nil, err } - appMetrics := templateRequest.IsAppMetricsEnabled - isAppMetricsSupported, err := impl.CheckIsAppMetricsSupported(templateRequest.ChartRefId) + appLevelMetricsUpdateReq := &bean.DeployedAppMetricsRequest{ + EnableMetrics: templateRequest.IsAppMetricsEnabled, + AppId: templateRequest.AppId, + ChartRefId: templateRequest.ChartRefId, + UserId: templateRequest.UserId, + } + err = impl.deployedAppMetricsService.CreateOrUpdateAppOrEnvLevelMetrics(ctx, appLevelMetricsUpdateReq) if err != nil { + impl.logger.Errorw("error, CheckAndUpdateAppOrEnvLevelMetrics", "err", err, "req", appLevelMetricsUpdateReq) return nil, err } - if appMetrics && !(isAppMetricsSupported) { - appMetricRequest := AppMetricEnableDisableRequest{UserId: templateRequest.UserId, AppId: templateRequest.AppId, IsAppMetricsEnabled: false} - _, span = otel.Tracer("orchestrator").Start(ctx, "updateAppLevelMetrics") - _, err = impl.updateAppLevelMetrics(&appMetricRequest) - span.End() - if err != nil { - impl.logger.Errorw("error in disable app metric flag", "error", err) - return nil, err - } - } else { - appMetricsRequest := AppMetricEnableDisableRequest{UserId: templateRequest.UserId, AppId: templateRequest.AppId, IsAppMetricsEnabled: templateRequest.IsAppMetricsEnabled} - _, span = otel.Tracer("orchestrator").Start(ctx, "updateAppLevelMetrics") - _, err = impl.updateAppLevelMetrics(&appMetricsRequest) - span.End() - if err != nil { - impl.logger.Errorw("err while updating app metrics", "err", err) - return nil, err - } - } _, span = otel.Tracer("orchestrator").Start(ctx, "CreateDeploymentTemplateHistoryFromGlobalTemplate") //creating history entry for deployment template - err = impl.deploymentTemplateHistoryService.CreateDeploymentTemplateHistoryFromGlobalTemplate(template, nil, templateRequest.IsAppMetricsEnabled) + err = impl.deploymentTemplateHistoryService.CreateDeploymentTemplateHistoryFromGlobalTemplate(template, nil, appLevelMetricsUpdateReq.EnableMetrics) span.End() if err != nil { impl.logger.Errorw("error in creating entry for deployment template history", "err", err, "chart", template) @@ -911,66 +621,6 @@ func (impl ChartServiceImpl) UpdateAppOverride(ctx context.Context, templateRequ return templateRequest, nil } -func (impl ChartServiceImpl) handleChartTypeChange(currentLatestChart *chartRepoRepository.Chart, templateRequest *TemplateRequest) (json.RawMessage, error) { - var oldChartRef, newChartRef *chartRepoRepository.ChartRef - var err error - if oldChartRef, err = impl.chartRefRepository.FindById(currentLatestChart.ChartRefId); err != nil { - return nil, fmt.Errorf("chartRef not found for %v", currentLatestChart.ChartRefId) - } - if newChartRef, err = impl.chartRefRepository.FindById(templateRequest.ChartRefId); err != nil { - return nil, fmt.Errorf("chartRef not found for %v", templateRequest.ChartRefId) - } - if len(oldChartRef.Name) == 0 { - oldChartRef.Name = RolloutChartType - } - if len(newChartRef.Name) == 0 { - oldChartRef.Name = RolloutChartType - } - if !CheckCompatibility(oldChartRef.Name, newChartRef.Name) { - return nil, fmt.Errorf("charts are not compatible") - } - updatedOverride, err := PatchWinterSoldierConfig(templateRequest.ValuesOverride, newChartRef.Name) - if err != nil { - return nil, err - } - return updatedOverride, nil -} - -func (impl ChartServiceImpl) updateAppLevelMetrics(appMetricRequest *AppMetricEnableDisableRequest) (*repository3.AppLevelMetrics, error) { - existingAppLevelMetrics, err := impl.appLevelMetricsRepository.FindByAppId(appMetricRequest.AppId) - if err != nil && err != pg.ErrNoRows { - impl.logger.Errorw("error in app metrics app level flag", "error", err) - return nil, err - } - if existingAppLevelMetrics != nil && existingAppLevelMetrics.Id != 0 { - existingAppLevelMetrics.AppMetrics = appMetricRequest.IsAppMetricsEnabled - err := impl.appLevelMetricsRepository.Update(existingAppLevelMetrics) - if err != nil { - impl.logger.Errorw("failed to update app level metrics flag", "error", err) - return nil, err - } - return existingAppLevelMetrics, nil - } else { - appLevelMetricsNew := &repository3.AppLevelMetrics{ - AppId: appMetricRequest.AppId, - AppMetrics: appMetricRequest.IsAppMetricsEnabled, - InfraMetrics: true, - AuditLog: sql.AuditLog{ - CreatedOn: time.Now(), - UpdatedOn: time.Now(), - CreatedBy: appMetricRequest.UserId, - UpdatedBy: appMetricRequest.UserId, - }, - } - err = impl.appLevelMetricsRepository.Save(appLevelMetricsNew) - if err != nil { - impl.logger.Errorw("error in saving app level metrics flag", "error", err) - return appLevelMetricsNew, err - } - return appLevelMetricsNew, nil - } -} - type IsReady struct { Flag bool `json:"flag"` Message string `json:"message"` @@ -1007,101 +657,25 @@ func (impl ChartServiceImpl) IsReadyToTrigger(appId int, envId int, pipelineId i return isReady, nil } -type ChartRef struct { - Id int `json:"id"` - Version string `json:"version"` - Name string `json:"name"` - Description string `json:"description"` - UserUploaded bool `json:"userUploaded"` - IsAppMetricsSupported bool `json:"isAppMetricsSupported"` -} - -type ChartRefMetaData struct { - ChartDescription string `json:"chartDescription"` -} - -type ChartRefResponse struct { - ChartRefs []ChartRef `json:"chartRefs"` - LatestChartRef int `json:"latestChartRef"` - LatestAppChartRef int `json:"latestAppChartRef"` - LatestEnvChartRef int `json:"latestEnvChartRef,omitempty"` - ChartsMetadata map[string]ChartRefMetaData `json:"chartMetadata"` // chartName vs Metadata - CompatibleChartTypes []string `json:"compatibleChartTypes,omitempty"` -} - -type ChartYamlStruct struct { - Name string `yaml:"name"` - Version string `yaml:"version"` - Description string `yaml:"description"` -} - -type ChartDataInfo struct { - ChartLocation string `json:"chartLocation"` - ChartName string `json:"chartName"` - ChartVersion string `json:"chartVersion"` - TemporaryFolder string `json:"temporaryFolder"` - Description string `json:"description"` - Message string `json:"message"` -} - -type ChartDto struct { - Id int `json:"id"` - Name string `json:"name"` - ChartDescription string `json:"chartDescription"` - Version string `json:"version"` - IsUserUploaded bool `json:"isUserUploaded"` -} - -func (impl ChartServiceImpl) ChartRefAutocomplete() ([]ChartRef, error) { - var chartRefs []ChartRef - results, err := impl.chartRefRepository.GetAll() - if err != nil { - impl.logger.Errorw("error in fetching chart config", "err", err) - return chartRefs, err - } - - for _, result := range results { - chartRefs = append(chartRefs, ChartRef{ - Id: result.Id, - Version: result.Version, - Description: result.ChartDescription, - UserUploaded: result.UserUploaded, - IsAppMetricsSupported: result.IsAppMetricsSupported, - }) - } - - return chartRefs, nil -} - -func (impl ChartServiceImpl) ChartRefAutocompleteForAppOrEnv(appId int, envId int) (*ChartRefResponse, error) { - chartRefResponse := &ChartRefResponse{ - ChartsMetadata: make(map[string]ChartRefMetaData), - } - var chartRefs []ChartRef +func (impl ChartServiceImpl) ChartRefAutocompleteForAppOrEnv(appId int, envId int) (*bean2.ChartRefAutocompleteResponse, error) { + chartRefResponse := &bean2.ChartRefAutocompleteResponse{} + var chartRefs []bean2.ChartRefAutocompleteDto - results, err := impl.chartRefRepository.GetAll() + results, err := impl.chartRefService.GetAll() if err != nil { - impl.logger.Errorw("error in fetching chart config", "err", err) + impl.logger.Errorw("error in fetching chart ref", "err", err) return chartRefResponse, err } - resultsMetadata, err := impl.chartRefRepository.GetAllChartMetadata() + resultsMetadataMap, err := impl.chartRefService.GetAllChartMetadata() if err != nil { impl.logger.Errorw("error in fetching chart metadata", "err", err) return chartRefResponse, err } - for _, resultMetadata := range resultsMetadata { - chartRefMetadata := ChartRefMetaData{ - ChartDescription: resultMetadata.ChartDescription, - } - chartRefResponse.ChartsMetadata[resultMetadata.ChartName] = chartRefMetadata - } + chartRefResponse.ChartsMetadata = resultsMetadataMap var LatestAppChartRef int for _, result := range results { - if len(result.Name) == 0 { - result.Name = "Rollout Deployment" - } - chartRefs = append(chartRefs, ChartRef{ + chartRefs = append(chartRefs, bean2.ChartRefAutocompleteDto{ Id: result.Id, Version: result.Version, Name: result.Name, @@ -1144,7 +718,7 @@ func (impl ChartServiceImpl) FindPreviousChartByAppId(appId int) (chartTemplate impl.logger.Errorw("error in fetching chart ", "appId", appId, "err", err) return nil, err } - chartTemplate, err = impl.chartAdaptor(chart, nil) + chartTemplate, err = impl.chartAdaptor(chart, false) return chartTemplate, err } @@ -1216,21 +790,10 @@ func (impl ChartServiceImpl) UpgradeForApp(appId int, chartRefId int, newAppOver return false, err } //creating history entry for deployment template - isAppMetricsEnabled := false - envLevelAppMetrics, err := impl.envLevelAppMetricsRepository.FindByAppIdAndEnvId(appId, envOverrideNew.TargetEnvironment) - if err != nil && err != pg.ErrNoRows { - impl.logger.Errorw("error in getting env level app metrics", "err", err, "appId", appId, "envId", envOverrideNew.TargetEnvironment) + isAppMetricsEnabled, err := impl.deployedAppMetricsService.GetMetricsFlagForAPipelineByAppIdAndEnvId(appId, envOverrideNew.TargetEnvironment) + if err != nil { + impl.logger.Errorw("error, GetMetricsFlagForAPipelineByAppIdAndEnvId", "err", err, "appId", appId, "envId", envOverrideNew.TargetEnvironment) return false, err - } else if err == pg.ErrNoRows { - appLevelAppMetrics, err := impl.appLevelMetricsRepository.FindByAppId(appId) - if err != nil && err != pg.ErrNoRows { - impl.logger.Errorw("error in getting app level app metrics", "err", err, "appId", appId) - return false, err - } else if err == nil { - isAppMetricsEnabled = appLevelAppMetrics.AppMetrics - } - } else { - isAppMetricsEnabled = *envLevelAppMetrics.AppMetrics } err = impl.deploymentTemplateHistoryService.CreateDeploymentTemplateHistoryFromEnvOverrideTemplate(envOverrideNew, nil, isAppMetricsEnabled, 0) if err != nil { @@ -1247,476 +810,34 @@ func (impl ChartServiceImpl) UpgradeForApp(appId int, chartRefId int, newAppOver return true, nil } -// below method is deprecated - -func (impl ChartServiceImpl) AppMetricsEnableDisable(appMetricRequest AppMetricEnableDisableRequest) (*AppMetricEnableDisableRequest, error) { - currentChart, err := impl.chartRepository.FindLatestChartForAppByAppId(appMetricRequest.AppId) - if err != nil && pg.ErrNoRows != err { - impl.logger.Error(err) - return nil, err - } - if pg.ErrNoRows == err { - impl.logger.Errorw("no chart configured for this app", "appId", appMetricRequest.AppId) - err = &util.ApiError{ - HttpStatusCode: http.StatusNotFound, - InternalMessage: "no chart configured for this app", - UserMessage: "no chart configured for this app", - } - return nil, err - } - // validate app metrics compatibility - refChart, err := impl.chartRefRepository.FindById(currentChart.ChartRefId) - if err != nil { - impl.logger.Error(err) - return nil, err - } - if appMetricRequest.IsAppMetricsEnabled == true { - chartMajorVersion, chartMinorVersion, err := util2.ExtractChartVersion(currentChart.ChartVersion) - if err != nil { - impl.logger.Errorw("chart version parsing", "err", err) - return nil, err - } - - if !refChart.UserUploaded && !(chartMajorVersion >= 3 && chartMinorVersion >= 7) { - err = &util.ApiError{ - InternalMessage: "chart version in not compatible for app metrics", - UserMessage: "chart version in not compatible for app metrics", - } - return nil, err - } - } - //update or create app level app metrics - appLevelMetrics, err := impl.updateAppLevelMetrics(&appMetricRequest) - if err != nil { - impl.logger.Errorw("error in saving app level metrics flag", "error", err) - return nil, err - } - //updating audit log details of chart as history service uses it - currentChart.UpdatedOn = time.Now() - currentChart.UpdatedBy = appMetricRequest.UserId - //creating history entry for deployment template - err = impl.deploymentTemplateHistoryService.CreateDeploymentTemplateHistoryFromGlobalTemplate(currentChart, nil, appMetricRequest.IsAppMetricsEnabled) - if err != nil { - impl.logger.Errorw("error in creating entry for deployment template history", "err", err, "chart", currentChart) - return nil, err - } - if appLevelMetrics.Id > 0 { - return &appMetricRequest, nil - } - return nil, err -} - -const memoryPattern = `"1000Mi" or "1Gi"` -const cpuPattern = `"50m" or "0.05"` -const cpu = "cpu" -const memory = "memory" - -func (impl ChartServiceImpl) DeploymentTemplateValidate(ctx context.Context, template interface{}, chartRefId int, scope resourceQualifiers.Scope) (bool, error) { - _, span := otel.Tracer("orchestrator").Start(ctx, "JsonSchemaExtractFromFile") - schemajson, version, err := impl.JsonSchemaExtractFromFile(chartRefId) - span.End() - if err != nil { - impl.logger.Errorw("Json Schema not found err, FindJsonSchema", "err", err) - return true, nil - } - //if err != nil && chartRefId >= 9 { - // impl.logger.Errorw("Json Schema not found err, FindJsonSchema", "err", err) - // return false, err - //} else if err != nil { - // impl.logger.Errorw("Json Schema not found err, FindJsonSchema", "err", err) - // return true, nil - //} - - templateBytes := template.(json.RawMessage) - templatejsonstring, _, err := impl.scopedVariableManager.ExtractVariablesAndResolveTemplate(scope, string(templateBytes), parsers.JsonVariableTemplate, true, false) - if err != nil { - return false, err - } - var templatejson interface{} - err = json.Unmarshal([]byte(templatejsonstring), &templatejson) - if err != nil { - fmt.Println("Error:", err) - return false, err - } - - schemaLoader := gojsonschema.NewGoLoader(schemajson) - documentLoader := gojsonschema.NewGoLoader(templatejson) - marshalTemplatejson, err := json.Marshal(templatejson) +func (impl ChartServiceImpl) CheckIfChartRefUserUploadedByAppId(id int) (bool, error) { + chartInfo, err := impl.chartRepository.FindLatestChartForAppByAppId(id) if err != nil { - impl.logger.Errorw("json template marshal err, DeploymentTemplateValidate", "err", err) return false, err } - _, span = otel.Tracer("orchestrator").Start(ctx, "gojsonschema.Validate") - result, err := gojsonschema.Validate(schemaLoader, documentLoader) - span.End() + chartData, err := impl.chartRefService.FindById(chartInfo.ChartRefId) if err != nil { - impl.logger.Errorw("result validate err, DeploymentTemplateValidate", "err", err) return false, err } - if result.Valid() { - var dat map[string]interface{} - if err := json.Unmarshal(marshalTemplatejson, &dat); err != nil { - impl.logger.Errorw("json template unmarshal err, DeploymentTemplateValidate", "err", err) - return false, err - } - - _, err := util2.CompareLimitsRequests(dat, version) - if err != nil { - impl.logger.Errorw("LimitRequestCompare err, DeploymentTemplateValidate", "err", err) - return false, err - } - _, err = util2.AutoScale(dat) - if err != nil { - impl.logger.Errorw("LimitRequestCompare err, DeploymentTemplateValidate", "err", err) - return false, err - } - - return true, nil - } else { - var stringerror string - for _, err := range result.Errors() { - impl.logger.Errorw("result err, DeploymentTemplateValidate", "err", err.Details()) - if err.Details()["format"] == cpu { - stringerror = stringerror + err.Field() + ": Format should be like " + cpuPattern + "\n" - } else if err.Details()["format"] == memory { - stringerror = stringerror + err.Field() + ": Format should be like " + memoryPattern + "\n" - } else { - stringerror = stringerror + err.String() + "\n" - } - } - return false, errors.New(stringerror) - } -} - -func (impl ChartServiceImpl) JsonSchemaExtractFromFile(chartRefId int) (map[string]interface{}, string, error) { - err := impl.CheckChartExists(chartRefId) - if err != nil { - impl.logger.Errorw("refChartDir Not Found", "err", err) - return nil, "", err - } - - refChartDir, _, err, version, _ := impl.GetRefChart(TemplateRequest{ChartRefId: chartRefId}) - if err != nil { - impl.logger.Errorw("refChartDir Not Found err, JsonSchemaExtractFromFile", err) - return nil, "", err - } - fileStatus := filepath.Join(refChartDir, "schema.json") - if _, err := os.Stat(fileStatus); os.IsNotExist(err) { - impl.logger.Errorw("Schema File Not Found err, JsonSchemaExtractFromFile", err) - return nil, "", err - } else { - jsonFile, err := os.Open(fileStatus) - if err != nil { - impl.logger.Errorw("jsonfile open err, JsonSchemaExtractFromFile", "err", err) - return nil, "", err - } - byteValueJsonFile, err := ioutil.ReadAll(jsonFile) - if err != nil { - impl.logger.Errorw("byteValueJsonFile read err, JsonSchemaExtractFromFile", "err", err) - return nil, "", err - } - - var schemajson map[string]interface{} - err = json.Unmarshal([]byte(byteValueJsonFile), &schemajson) - if err != nil { - impl.logger.Errorw("Unmarshal err in byteValueJsonFile, DeploymentTemplateValidate", "err", err) - return nil, "", err - } - return schemajson, version, nil - } + return chartData.UserUploaded, err } -func (impl ChartServiceImpl) CheckChartExists(chartRefId int) error { - chartRefValue, err := impl.chartRefRepository.FindById(chartRefId) - if err != nil { - impl.logger.Errorw("error in finding ref chart by id", "err", err) +func (impl *ChartServiceImpl) UpdateGitRepoUrlInCharts(appId int, repoUrl, chartLocation string, userId int32) error { + charts, err := impl.chartRepository.FindActiveChartsByAppId(appId) + if err != nil && pg.ErrNoRows != err { return err } - refChartLocation := filepath.Join(string(impl.refChartDir), chartRefValue.Location) - if _, err := os.Stat(refChartLocation); os.IsNotExist(err) { - chartInfo, err := impl.ExtractChartIfMissing(chartRefValue.ChartData, string(impl.refChartDir), chartRefValue.Location) - if chartInfo != nil && chartInfo.TemporaryFolder != "" { - err1 := os.RemoveAll(chartInfo.TemporaryFolder) - if err1 != nil { - impl.logger.Errorw("error in deleting temp dir ", "err", err) + for _, ch := range charts { + if len(ch.GitRepoUrl) == 0 { + ch.GitRepoUrl = repoUrl + ch.ChartLocation = chartLocation + ch.UpdatedOn = time.Now() + ch.UpdatedBy = userId + err = impl.chartRepository.Update(ch) + if err != nil { + return err } } - return err } return nil } - -func (impl ChartServiceImpl) CheckIsAppMetricsSupported(chartRefId int) (bool, error) { - chartRefValue, err := impl.chartRefRepository.FindById(chartRefId) - if err != nil { - impl.logger.Errorw("error in finding ref chart by id", "err", err) - return false, nil - } - return chartRefValue.IsAppMetricsSupported, nil -} - -func (impl *ChartServiceImpl) GetLocationFromChartNameAndVersion(chartName string, chartVersion string) string { - var chartLocation string - chartname := impl.FormatChartName(chartName) - chartversion := strings.ReplaceAll(chartVersion, ".", "-") - if !strings.Contains(chartname, chartversion) { - chartLocation = chartname + "_" + chartversion - } else { - chartLocation = chartname - } - return chartLocation -} - -func (impl *ChartServiceImpl) FormatChartName(chartName string) string { - chartname := strings.ReplaceAll(chartName, ".", "-") - chartname = strings.ReplaceAll(chartname, " ", "_") - return chartname -} - -func (impl *ChartServiceImpl) ValidateUploadedFileFormat(fileName string) error { - if !strings.HasSuffix(fileName, ".tgz") { - return errors.New("unsupported format") - } - return nil -} - -func (impl ChartServiceImpl) ReadChartMetaDataForLocation(chartDir string, fileName string) (*ChartYamlStruct, error) { - chartLocation := filepath.Clean(filepath.Join(chartDir, fileName)) - - chartYamlPath := filepath.Clean(filepath.Join(chartLocation, "Chart.yaml")) - if _, err := os.Stat(chartYamlPath); os.IsNotExist(err) { - return nil, fmt.Errorf("Chart.yaml file not present in the directory") - } - - data, err := ioutil.ReadFile(chartYamlPath) - if err != nil { - impl.logger.Errorw("failed reading data from file", "err", err) - return nil, err - } - //println(data) - var chartYaml ChartYamlStruct - err = yaml.Unmarshal(data, &chartYaml) - if err != nil { - impl.logger.Errorw("Unmarshal error of yaml file", "err", err) - return nil, err - } - if chartYaml.Name == "" || chartYaml.Version == "" { - impl.logger.Errorw("Missing values in yaml file either name or version", "err", err) - return nil, errors.New("Missing values in yaml file either name or version") - } - ver := strings.Split(chartYaml.Version, ".") - if len(ver) == 3 { - for _, verObject := range ver { - if _, err := strconv.ParseInt(verObject, 10, 64); err != nil { - return nil, errors.New("Version should contain integers (Ex: 1.1.0)") - } - } - return &chartYaml, nil - } - return nil, errors.New("Version should be of length 3 integers with dot seperated (Ex: 1.1.0)") -} - -func (impl ChartServiceImpl) ExtractChartIfMissing(chartData []byte, refChartDir string, location string) (*ChartDataInfo, error) { - binaryDataReader := bytes.NewReader(chartData) - dir := impl.chartTemplateService.GetDir() - chartInfo := &ChartDataInfo{ - ChartName: "", - ChartVersion: "", - ChartLocation: "", - TemporaryFolder: "", - Description: "", - Message: "", - } - temporaryChartWorkingDir := filepath.Clean(filepath.Join(refChartDir, dir)) - err := os.MkdirAll(temporaryChartWorkingDir, os.ModePerm) - if err != nil { - impl.logger.Errorw("error in creating directory, CallbackConfigMap", "err", err) - return chartInfo, err - } - chartInfo.TemporaryFolder = temporaryChartWorkingDir - err = util2.ExtractTarGz(binaryDataReader, temporaryChartWorkingDir) - if err != nil { - impl.logger.Errorw("error in extracting binary data of charts", "err", err) - return chartInfo, err - } - - var chartLocation string - var chartName string - var chartVersion string - var fileName string - - files, err := ioutil.ReadDir(temporaryChartWorkingDir) - if err != nil { - impl.logger.Errorw("error in reading err dir", "err", err) - return chartInfo, err - } - - fileName = files[0].Name() - if strings.HasPrefix(files[0].Name(), ".") { - fileName = files[1].Name() - } - - currentChartWorkingDir := filepath.Clean(filepath.Join(temporaryChartWorkingDir, fileName)) - - if location == "" { - chartYaml, err := impl.ReadChartMetaDataForLocation(temporaryChartWorkingDir, fileName) - var errorList error - if err != nil { - impl.logger.Errorw("Chart yaml file or content not found") - errorList = err - } - - err = util2.CheckForMissingFiles(currentChartWorkingDir) - if err != nil { - impl.logger.Errorw("Missing files in the folder", "err", err) - if errorList != nil { - errorList = errors.New(errorList.Error() + "; " + err.Error()) - } else { - errorList = err - } - - } - - if errorList != nil { - return chartInfo, errorList - } - - chartName = chartYaml.Name - chartVersion = chartYaml.Version - chartInfo.Description = chartYaml.Description - chartLocation = impl.GetLocationFromChartNameAndVersion(chartName, chartVersion) - location = chartLocation - - // Validate: chart name shouldn't conflict with Devtron charts (no user uploaded chart names should contain any devtron chart names as the prefix) - isReservedChart, _ := impl.ValidateReservedChartName(chartName) - if isReservedChart { - impl.logger.Errorw("request err, chart name is reserved by Devtron") - err = &util.ApiError{ - Code: constants.ChartNameAlreadyReserved, - InternalMessage: CHART_NAME_RESERVED_INTERNAL_ERROR, - UserMessage: fmt.Sprintf("The name '%s' is reserved for a chart provided by Devtron", chartName), - } - return chartInfo, err - } - - // Validate: chart location should be unique - exists, err := impl.chartRefRepository.CheckIfDataExists(location) - if err != nil { - impl.logger.Errorw("Error in searching the database") - return chartInfo, err - } - if exists { - impl.logger.Errorw("request err, chart name and version exists already in the database") - err = &util.ApiError{ - Code: constants.ChartCreatedAlreadyExists, - InternalMessage: CHART_ALREADY_EXISTS_INTERNAL_ERROR, - UserMessage: fmt.Sprintf("%s of %s exists already in the database", chartVersion, chartName), - } - return chartInfo, err - } - - //User Info Message: uploading new version of the existing chart name - existingChart, err := impl.chartRefRepository.FetchChart(chartName) - if err == nil && existingChart != nil { - chartInfo.Message = "New Version detected for " + existingChart[0].Name - } - - } else { - err = dirCopy.Copy(currentChartWorkingDir, filepath.Clean(filepath.Join(refChartDir, location))) - if err != nil { - impl.logger.Errorw("error in copying chart from temp dir to ref chart dir", "err", err) - return chartInfo, err - } - } - - chartInfo.ChartLocation = location - chartInfo.ChartName = chartName - chartInfo.ChartVersion = chartVersion - return chartInfo, nil -} - -func (impl ChartServiceImpl) ValidateReservedChartName(chartName string) (isReservedChart bool, err error) { - formattedChartName := impl.FormatChartName(chartName) - for _, reservedChart := range *ReservedChartRefNamesList { - isReservedChart = (reservedChart.LocationPrefix != "" && strings.HasPrefix(formattedChartName, reservedChart.LocationPrefix)) || - (reservedChart.Name != "" && strings.HasPrefix(strings.ToLower(chartName), reservedChart.Name)) - if isReservedChart { - return true, nil - } - } - return false, nil -} - -func (impl ChartServiceImpl) FetchCustomChartsInfo() ([]*ChartDto, error) { - resultsMetadata, err := impl.chartRefRepository.GetAllChartMetadata() - if err != nil { - impl.logger.Errorw("error in fetching chart metadata", "err", err) - return nil, err - } - chartsMetadata := make(map[string]string) - for _, resultMetadata := range resultsMetadata { - chartsMetadata[resultMetadata.ChartName] = resultMetadata.ChartDescription - } - repo, err := impl.chartRefRepository.GetAll() - if err != nil { - return nil, err - } - var chartDtos []*ChartDto - for _, ref := range repo { - if len(ref.Name) == 0 { - ref.Name = RolloutChartType - } - if description, ok := chartsMetadata[ref.Name]; ref.ChartDescription == "" && ok { - ref.ChartDescription = description - } - chartDto := &ChartDto{ - Id: ref.Id, - Name: ref.Name, - ChartDescription: ref.ChartDescription, - Version: ref.Version, - IsUserUploaded: ref.UserUploaded, - } - chartDtos = append(chartDtos, chartDto) - } - return chartDtos, err -} - -func (impl ChartServiceImpl) CheckCustomChartByAppId(id int) (bool, error) { - chartInfo, err := impl.chartRepository.FindLatestChartForAppByAppId(id) - if err != nil { - return false, err - } - chartData, err := impl.chartRefRepository.FindById(chartInfo.ChartRefId) - if err != nil { - return false, err - } - return chartData.UserUploaded, err -} - -func (impl ChartServiceImpl) CheckCustomChartByChartId(id int) (bool, error) { - chartData, err := impl.chartRefRepository.FindById(id) - if err != nil { - return false, err - } - return chartData.UserUploaded, nil -} - -func (impl ChartServiceImpl) GetCustomChartInBytes(chartRefId int) ([]byte, error) { - chartRef, err := impl.chartRefRepository.FindById(chartRefId) - if err != nil { - impl.logger.Errorw("error getting chart data", "chartRefId", chartRefId, "err", err) - return nil, err - } - // For user uploaded charts ChartData will be retrieved from DB - if chartRef.ChartData != nil { - return chartRef.ChartData, nil - } - // For Devtron reference charts the chart will be load from the directory location - refChartPath := filepath.Join(string(impl.refChartDir), chartRef.Location) - manifestByteArr, err := impl.chartTemplateService.LoadChartInBytes(refChartPath, false) - if err != nil { - impl.logger.Errorw("error in converting chart to bytes", "err", err) - return nil, err - } - return manifestByteArr, nil -} diff --git a/pkg/chart/ChartUtils.go b/pkg/chart/ChartUtils.go index 0d8b180b01a..47020603520 100644 --- a/pkg/chart/ChartUtils.go +++ b/pkg/chart/ChartUtils.go @@ -2,8 +2,7 @@ package chart import ( "encoding/json" - chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository" - "strings" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/chartRef/bean" ) func PatchWinterSoldierConfig(override json.RawMessage, newChartType string) (json.RawMessage, error) { @@ -38,9 +37,9 @@ func PatchWinterSoldierIfExists(newChartType string, jsonMap map[string]json.Raw return jsonMap, nil } switch newChartType { - case DeploymentChartType: + case bean.DeploymentChartType: winterSoldierUnmarshalled["type"] = json.RawMessage("\"Deployment\"") - case RolloutChartType: + case bean.RolloutChartType: winterSoldierUnmarshalled["type"] = json.RawMessage("\"Rollout\"") } @@ -52,20 +51,6 @@ func PatchWinterSoldierIfExists(newChartType string, jsonMap map[string]json.Raw return jsonMap, nil } -func SetReservedChartList(devtronChartList []*chartRepoRepository.ChartRef) { - reservedChartRefNamesList := []ReservedChartList{ - {Name: strings.ToLower(RolloutChartType), LocationPrefix: ""}, - {Name: "", LocationPrefix: ReferenceChart}, - } - for _, devtronChart := range devtronChartList { - reservedChartRefNamesList = append(reservedChartRefNamesList, ReservedChartList{ - Name: strings.ToLower(devtronChart.Name), - LocationPrefix: strings.Split(devtronChart.Location, "_")[0], - }) - } - ReservedChartRefNamesList = &reservedChartRefNamesList -} - //func IsFlaggerCanaryEnabled(override json.RawMessage) (bool, error) { // //} diff --git a/pkg/chart/bean.go b/pkg/chart/bean.go index c3dce0a3b18..af905de3c84 100644 --- a/pkg/chart/bean.go +++ b/pkg/chart/bean.go @@ -5,11 +5,6 @@ import ( "github.com/devtron-labs/devtron/internal/sql/models" ) -const ( - CHART_ALREADY_EXISTS_INTERNAL_ERROR = "Chart exists already, try uploading another chart" - CHART_NAME_RESERVED_INTERNAL_ERROR = "Change the name of the chart and try uploading again" -) - var ReservedChartRefNamesList *[]ReservedChartList type ReservedChartList struct { @@ -35,13 +30,6 @@ type TemplateRequest struct { UserId int32 `json:"-"` } -type AppMetricEnableDisableRequest struct { - AppId int `json:"appId,omitempty"` - EnvironmentId int `json:"environmentId,omitempty"` - IsAppMetricsEnabled bool `json:"isAppMetricsEnabled"` - UserId int32 `json:"-"` -} - type ChartUpgradeRequest struct { ChartRefId int `json:"chartRefId" validate:"number"` All bool `json:"all"` diff --git a/pkg/chart/mocks/ChartService.go b/pkg/chart/mocks/ChartService.go index 1c58d685379..3cf2e392d64 100644 --- a/pkg/chart/mocks/ChartService.go +++ b/pkg/chart/mocks/ChartService.go @@ -680,19 +680,6 @@ func (_m *ChartService) ReadChartMetaDataForLocation(chartDir string, fileName s return r0, r1 } -// RegisterInArgo provides a mock function with given fields: chartGitAttribute, ctx -func (_m *ChartService) RegisterInArgo(chartGitAttribute *util.ChartGitAttribute, ctx context.Context) error { - ret := _m.Called(chartGitAttribute, ctx) - - var r0 error - if rf, ok := ret.Get(0).(func(*util.ChartGitAttribute, context.Context) error); ok { - r0 = rf(chartGitAttribute, ctx) - } else { - r0 = ret.Error(0) - } - - return r0 -} // UpdateAppOverride provides a mock function with given fields: ctx, templateRequest func (_m *ChartService) UpdateAppOverride(ctx context.Context, templateRequest *chart.TemplateRequest) (*chart.TemplateRequest, error) { diff --git a/pkg/chartRepo/repository/ChartRefRepository.go b/pkg/chartRepo/repository/ChartRefRepository.go index 4c4c9adfc18..b62a9d280fd 100644 --- a/pkg/chartRepo/repository/ChartRefRepository.go +++ b/pkg/chartRepo/repository/ChartRefRepository.go @@ -7,7 +7,6 @@ import ( "strings" ) -type RefChartDir string type ChartRef struct { tableName struct{} `sql:"chart_ref" pg:",discard_unknown_columns"` Id int `sql:"id,pk"` @@ -41,7 +40,7 @@ type ChartRefRepository interface { CheckIfDataExists(location string) (bool, error) FetchChart(name string) ([]*ChartRef, error) FetchInfoOfChartConfiguredInApp(appId int) (*ChartRef, error) - FetchAllChartInfoByUploadFlag(userUploaded bool) ([]*ChartRef, error) + FetchAllNonUserUploadedChartInfo() ([]*ChartRef, error) } type ChartRefRepositoryImpl struct { dbConnection *pg.DB @@ -121,10 +120,10 @@ func (impl ChartRefRepositoryImpl) FetchChart(name string) ([]*ChartRef, error) return chartRefs, err } -func (impl ChartRefRepositoryImpl) FetchAllChartInfoByUploadFlag(userUploaded bool) ([]*ChartRef, error) { +func (impl ChartRefRepositoryImpl) FetchAllNonUserUploadedChartInfo() ([]*ChartRef, error) { var repo []*ChartRef err := impl.dbConnection.Model(&repo). - Where("user_uploaded = ?", userUploaded). + Where("user_uploaded = ?", false). Select() if err != nil { return repo, err diff --git a/pkg/cluster/ClusterServiceExtended.go b/pkg/cluster/ClusterServiceExtended.go index 5a11aee3a00..0982b9b9f4b 100644 --- a/pkg/cluster/ClusterServiceExtended.go +++ b/pkg/cluster/ClusterServiceExtended.go @@ -3,6 +3,7 @@ package cluster import ( "context" "fmt" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config" "net/http" "strings" "time" @@ -10,7 +11,6 @@ import ( cluster3 "github.com/argoproj/argo-cd/v2/pkg/apiclient/cluster" "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" "github.com/devtron-labs/common-lib/utils/k8s" - repository3 "github.com/devtron-labs/devtron/internal/sql/repository" repository5 "github.com/devtron-labs/devtron/pkg/auth/user/repository" "github.com/devtron-labs/devtron/pkg/k8s/informer" @@ -26,12 +26,12 @@ import ( // extends ClusterServiceImpl and enhances method of ClusterService with full mode specific errors type ClusterServiceImplExtended struct { - environmentRepository repository.EnvironmentRepository - grafanaClient grafana.GrafanaClient - installedAppRepository repository2.InstalledAppRepository - clusterServiceCD cluster2.ServiceClient - K8sInformerFactory informer.K8sInformerFactory - gitOpsRepository repository3.GitOpsConfigRepository + environmentRepository repository.EnvironmentRepository + grafanaClient grafana.GrafanaClient + installedAppRepository repository2.InstalledAppRepository + clusterServiceCD cluster2.ServiceClient + K8sInformerFactory informer.K8sInformerFactory + gitOpsConfigReadService config.GitOpsConfigReadService *ClusterServiceImpl } @@ -39,14 +39,15 @@ func NewClusterServiceImplExtended(repository repository.ClusterRepository, envi grafanaClient grafana.GrafanaClient, logger *zap.SugaredLogger, installedAppRepository repository2.InstalledAppRepository, K8sUtil *k8s.K8sServiceImpl, clusterServiceCD cluster2.ServiceClient, K8sInformerFactory informer.K8sInformerFactory, - gitOpsRepository repository3.GitOpsConfigRepository, userAuthRepository repository5.UserAuthRepository, - userRepository repository5.UserRepository, roleGroupRepository repository5.RoleGroupRepository) *ClusterServiceImplExtended { + userAuthRepository repository5.UserAuthRepository, + userRepository repository5.UserRepository, roleGroupRepository repository5.RoleGroupRepository, + gitOpsConfigReadService config.GitOpsConfigReadService) *ClusterServiceImplExtended { clusterServiceExt := &ClusterServiceImplExtended{ - environmentRepository: environmentRepository, - grafanaClient: grafanaClient, - installedAppRepository: installedAppRepository, - clusterServiceCD: clusterServiceCD, - gitOpsRepository: gitOpsRepository, + environmentRepository: environmentRepository, + grafanaClient: grafanaClient, + installedAppRepository: installedAppRepository, + clusterServiceCD: clusterServiceCD, + gitOpsConfigReadService: gitOpsConfigReadService, ClusterServiceImpl: &ClusterServiceImpl{ clusterRepository: repository, logger: logger, @@ -157,7 +158,7 @@ func (impl *ClusterServiceImplExtended) FindAllExceptVirtual() ([]*ClusterBean, } func (impl *ClusterServiceImplExtended) Update(ctx context.Context, bean *ClusterBean, userId int32) (*ClusterBean, error) { - isGitOpsConfigured, err1 := impl.gitOpsRepository.IsGitOpsConfigured() + isGitOpsConfigured, err1 := impl.gitOpsConfigReadService.IsGitOpsConfigured() if err1 != nil { return nil, err1 } @@ -337,7 +338,7 @@ func (impl *ClusterServiceImplExtended) CreateGrafanaDataSource(clusterBean *Clu } func (impl *ClusterServiceImplExtended) Save(ctx context.Context, bean *ClusterBean, userId int32) (*ClusterBean, error) { - isGitOpsConfigured, err := impl.gitOpsRepository.IsGitOpsConfigured() + isGitOpsConfigured, err := impl.gitOpsConfigReadService.IsGitOpsConfigured() if err != nil { return nil, err } diff --git a/pkg/commonService/CommonService.go b/pkg/commonService/CommonService.go index c60e37d0deb..4569dad0137 100644 --- a/pkg/commonService/CommonService.go +++ b/pkg/commonService/CommonService.go @@ -40,7 +40,6 @@ type CommonServiceImpl struct { logger *zap.SugaredLogger chartRepository chartRepoRepository.ChartRepository environmentConfigRepository chartConfig.EnvConfigOverrideRepository - gitOpsRepository repository.GitOpsConfigRepository dockerReg dockerRegistryRepository.DockerArtifactStoreRepository attributeRepo repository.AttributesRepository gitProviderRepository repository.GitProviderRepository @@ -52,7 +51,6 @@ type CommonServiceImpl struct { func NewCommonServiceImpl(logger *zap.SugaredLogger, chartRepository chartRepoRepository.ChartRepository, environmentConfigRepository chartConfig.EnvConfigOverrideRepository, - gitOpsRepository repository.GitOpsConfigRepository, dockerReg dockerRegistryRepository.DockerArtifactStoreRepository, attributeRepo repository.AttributesRepository, gitProviderRepository repository.GitProviderRepository, @@ -62,7 +60,6 @@ func NewCommonServiceImpl(logger *zap.SugaredLogger, logger: logger, chartRepository: chartRepository, environmentConfigRepository: environmentConfigRepository, - gitOpsRepository: gitOpsRepository, dockerReg: dockerReg, attributeRepo: attributeRepo, gitProviderRepository: gitProviderRepository, diff --git a/pkg/deployment/gitOps/common/bean/bean.go b/pkg/deployment/gitOps/common/bean/bean.go new file mode 100644 index 00000000000..4241070a371 --- /dev/null +++ b/pkg/deployment/gitOps/common/bean/bean.go @@ -0,0 +1,6 @@ +package bean + +// TODO : rename +type ChartGitAttribute struct { + RepoUrl, ChartLocation string +} diff --git a/pkg/deployment/gitOps/config/GitOpsConfigReadService.go b/pkg/deployment/gitOps/config/GitOpsConfigReadService.go new file mode 100644 index 00000000000..851cb22c486 --- /dev/null +++ b/pkg/deployment/gitOps/config/GitOpsConfigReadService.go @@ -0,0 +1,145 @@ +package config + +import ( + "fmt" + bean2 "github.com/devtron-labs/devtron/api/bean" + "github.com/devtron-labs/devtron/internal/sql/repository" + "github.com/devtron-labs/devtron/pkg/auth/user" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config/bean" + "github.com/devtron-labs/devtron/util" + "github.com/go-pg/pg" + "go.uber.org/zap" + "regexp" + "strings" +) + +type GitOpsConfigReadService interface { + IsGitOpsConfigured() (bool, error) + GetUserEmailIdAndNameForGitOpsCommit(userId int32) (string, string) + GetGitOpsRepoName(appName string) string + GetGitOpsRepoNameFromUrl(gitRepoUrl string) string + GetBitbucketMetadata() (*bean.BitbucketProviderMetadata, error) + GetGitOpsConfigActive() (*bean2.GitOpsConfigDto, error) + GetConfiguredGitOpsCount() (int, error) +} + +type GitOpsConfigReadServiceImpl struct { + logger *zap.SugaredLogger + gitOpsRepository repository.GitOpsConfigRepository + userService user.UserService + globalEnvVariables *util.GlobalEnvVariables +} + +func NewGitOpsConfigReadServiceImpl(logger *zap.SugaredLogger, + gitOpsRepository repository.GitOpsConfigRepository, + userService user.UserService, + globalEnvVariables *util.GlobalEnvVariables) *GitOpsConfigReadServiceImpl { + return &GitOpsConfigReadServiceImpl{ + logger: logger, + gitOpsRepository: gitOpsRepository, + userService: userService, + globalEnvVariables: globalEnvVariables, + } +} + +func (impl *GitOpsConfigReadServiceImpl) IsGitOpsConfigured() (bool, error) { + isGitOpsConfigured := false + gitOpsConfig, err := impl.gitOpsRepository.GetGitOpsConfigActive() + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("GetGitOpsConfigActive, error while getting", "err", err) + return false, err + } + if gitOpsConfig != nil && gitOpsConfig.Id > 0 { + isGitOpsConfigured = true + } + return isGitOpsConfigured, nil +} + +func (impl *GitOpsConfigReadServiceImpl) GetUserEmailIdAndNameForGitOpsCommit(userId int32) (string, string) { + emailId := bean.GitOpsCommitDefaultEmailId + name := bean.GitOpsCommitDefaultName + //getting emailId associated with user + userEmail, err := impl.userService.GetEmailById(userId) + if err != nil { + impl.logger.Errorw("error in getting user info by id", "err", err, "id", userId) + } + //TODO: export constant in user bean + if userEmail != "admin" && userEmail != "system" && len(userEmail) > 0 { + emailId = userEmail + } else { + emailIdGitOps, err := impl.gitOpsRepository.GetEmailIdFromActiveGitOpsConfig() + if err != nil { + impl.logger.Errorw("error in getting emailId from active gitOps config", "err", err) + } else if len(emailIdGitOps) > 0 { + emailId = emailIdGitOps + } + } + //we are getting name from emailId(replacing special characters in with space) + emailComponents := strings.Split(emailId, "@") + regex, _ := regexp.Compile(`[^\w]`) + if regex != nil { + name = regex.ReplaceAllString(emailComponents[0], " ") + } + return emailId, name +} + +func (impl *GitOpsConfigReadServiceImpl) GetGitOpsRepoName(appName string) string { + var repoName string + if len(impl.globalEnvVariables.GitOpsRepoPrefix) == 0 { + repoName = appName + } else { + repoName = fmt.Sprintf("%s-%s", impl.globalEnvVariables.GitOpsRepoPrefix, appName) + } + return repoName +} + +func (impl *GitOpsConfigReadServiceImpl) GetGitOpsRepoNameFromUrl(gitRepoUrl string) string { + gitRepoUrl = gitRepoUrl[strings.LastIndex(gitRepoUrl, "/")+1:] + gitRepoUrl = strings.ReplaceAll(gitRepoUrl, ".git", "") + return gitRepoUrl +} + +func (impl *GitOpsConfigReadServiceImpl) GetBitbucketMetadata() (*bean.BitbucketProviderMetadata, error) { + metadata := &bean.BitbucketProviderMetadata{} + gitOpsConfigBitbucket, err := impl.gitOpsRepository.GetGitOpsConfigByProvider(bean.BITBUCKET_PROVIDER) + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("error in fetching gitOps bitbucket config", "err", err) + return nil, err + } + if gitOpsConfigBitbucket != nil { + metadata.BitBucketWorkspaceId = gitOpsConfigBitbucket.BitBucketWorkspaceId + metadata.BitBucketProjectKey = gitOpsConfigBitbucket.BitBucketProjectKey + } + return metadata, nil +} + +func (impl *GitOpsConfigReadServiceImpl) GetGitOpsConfigActive() (*bean2.GitOpsConfigDto, error) { + model, err := impl.gitOpsRepository.GetGitOpsConfigActive() + if err != nil { + impl.logger.Errorw("error, GetGitOpsConfigActive", "err", err) + return nil, err + } + config := &bean2.GitOpsConfigDto{ + Id: model.Id, + Provider: model.Provider, + GitHubOrgId: model.GitHubOrgId, + GitLabGroupId: model.GitLabGroupId, + Active: model.Active, + UserId: model.CreatedBy, + AzureProjectName: model.AzureProject, + BitBucketWorkspaceId: model.BitBucketWorkspaceId, + BitBucketProjectKey: model.BitBucketProjectKey, + } + return config, err +} + +func (impl *GitOpsConfigReadServiceImpl) GetConfiguredGitOpsCount() (int, error) { + count := 0 + models, err := impl.gitOpsRepository.GetAllGitOpsConfig() + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("error, GetGitOpsConfigActive", "err", err) + return count, err + } + count = len(models) + return count, nil +} diff --git a/pkg/deployment/gitOps/config/bean/bean.go b/pkg/deployment/gitOps/config/bean/bean.go new file mode 100644 index 00000000000..8e6a43a51c4 --- /dev/null +++ b/pkg/deployment/gitOps/config/bean/bean.go @@ -0,0 +1,14 @@ +package bean + +const ( + GitOpsCommitDefaultEmailId = "devtron-bot@devtron.ai" + GitOpsCommitDefaultName = "devtron bot" +) + +// TODO: remove below object and its related methods to eliminate provider specific signature +type BitbucketProviderMetadata struct { + BitBucketWorkspaceId string + BitBucketProjectKey string +} + +const BITBUCKET_PROVIDER = "BITBUCKET_CLOUD" diff --git a/internal/util/GitCliUtil.go b/pkg/deployment/gitOps/git/GitCliUtil.go similarity index 99% rename from internal/util/GitCliUtil.go rename to pkg/deployment/gitOps/git/GitCliUtil.go index 3996751b6b2..1b54874f944 100644 --- a/internal/util/GitCliUtil.go +++ b/pkg/deployment/gitOps/git/GitCliUtil.go @@ -1,4 +1,4 @@ -package util +package git import ( "fmt" diff --git a/pkg/deployment/gitOps/git/GitOperationService.go b/pkg/deployment/gitOps/git/GitOperationService.go new file mode 100644 index 00000000000..70c88e3f826 --- /dev/null +++ b/pkg/deployment/gitOps/git/GitOperationService.go @@ -0,0 +1,401 @@ +package git + +import ( + "fmt" + bean2 "github.com/devtron-labs/devtron/api/bean" + "github.com/devtron-labs/devtron/internal/util" + commonBean "github.com/devtron-labs/devtron/pkg/deployment/gitOps/common/bean" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git/bean" + dirCopy "github.com/otiai10/copy" + "go.uber.org/zap" + "k8s.io/helm/pkg/proto/hapi/chart" + "os" + "path/filepath" + "regexp" + "sigs.k8s.io/yaml" + "time" +) + +type GitOperationService interface { + CreateGitRepositoryForApp(gitOpsRepoName, baseTemplateName, + version string, userId int32) (chartGitAttribute *commonBean.ChartGitAttribute, err error) + PushChartToGitRepo(gitOpsRepoName, referenceTemplate, version, + tempReferenceTemplateDir string, repoUrl string, userId int32) (err error) + CreateReadmeInGitRepo(gitOpsRepoName string, userId int32) error + CreateChartProxy(chartMetaData *chart.Metadata, refChartLocation string, envName string, + chartProxyReq *bean.ChartProxyReqDto) (string, *commonBean.ChartGitAttribute, error) + GitPull(clonedDir string, repoUrl string, appStoreName string) error + + CommitValues(chartGitAttr *ChartConfig) (commitHash string, commitTime time.Time, err error) + CommitAndPushAllChanges(clonedDir, commitMsg, userName, userEmailId string) (commitHash string, err error) + + CreateRepository(dto *bean2.GitOpsConfigDto, userId int32) (string, bool, error) + GetRepoUrlByRepoName(repoName string) (string, error) + + GetClonedDir(chartDir, repoUrl string) (string, error) + CloneInDir(repoUrl, chartDir string) (string, error) +} + +type GitOperationServiceImpl struct { + logger *zap.SugaredLogger + gitFactory *GitFactory + gitOpsConfigReadService config.GitOpsConfigReadService + chartTemplateService util.ChartTemplateService +} + +func NewGitOperationServiceImpl(logger *zap.SugaredLogger, gitFactory *GitFactory, + gitOpsConfigReadService config.GitOpsConfigReadService, + chartTemplateService util.ChartTemplateService) *GitOperationServiceImpl { + return &GitOperationServiceImpl{ + logger: logger, + gitFactory: gitFactory, + gitOpsConfigReadService: gitOpsConfigReadService, + chartTemplateService: chartTemplateService, + } + +} + +func (impl *GitOperationServiceImpl) CreateGitRepositoryForApp(gitOpsRepoName, baseTemplateName, + version string, userId int32) (chartGitAttribute *commonBean.ChartGitAttribute, err error) { + //baseTemplateName replace whitespace + space := regexp.MustCompile(`\s+`) + gitOpsRepoName = space.ReplaceAllString(gitOpsRepoName, "-") + + bitbucketMetadata, err := impl.gitOpsConfigReadService.GetBitbucketMetadata() + if err != nil { + impl.logger.Errorw("error in getting bitbucket metadata", "err", err) + return nil, err + } + //getting user name & emailId for commit author data + userEmailId, userName := impl.gitOpsConfigReadService.GetUserEmailIdAndNameForGitOpsCommit(userId) + gitRepoRequest := &bean2.GitOpsConfigDto{ + GitRepoName: gitOpsRepoName, + Description: fmt.Sprintf("helm chart for " + gitOpsRepoName), + Username: userName, + UserEmailId: userEmailId, + BitBucketWorkspaceId: bitbucketMetadata.BitBucketWorkspaceId, + BitBucketProjectKey: bitbucketMetadata.BitBucketProjectKey, + } + repoUrl, _, detailedError := impl.gitFactory.Client.CreateRepository(gitRepoRequest) + for _, err := range detailedError.StageErrorMap { + if err != nil { + impl.logger.Errorw("error in creating git project", "name", gitOpsRepoName, "err", err) + return nil, err + } + } + return &commonBean.ChartGitAttribute{RepoUrl: repoUrl, ChartLocation: filepath.Join(baseTemplateName, version)}, nil +} + +func (impl *GitOperationServiceImpl) PushChartToGitRepo(gitOpsRepoName, referenceTemplate, version, + tempReferenceTemplateDir string, repoUrl string, userId int32) (err error) { + chartDir := fmt.Sprintf("%s-%s", gitOpsRepoName, impl.chartTemplateService.GetDir()) + clonedDir, err := impl.GetClonedDir(chartDir, repoUrl) + defer impl.chartTemplateService.CleanDir(clonedDir) + if err != nil { + impl.logger.Errorw("error in cloning repo", "url", repoUrl, "err", err) + return err + } + err = impl.GitPull(clonedDir, repoUrl, gitOpsRepoName) + if err != nil { + impl.logger.Errorw("error in pulling git repo", "url", repoUrl, "err", err) + return err + } + dir := filepath.Join(clonedDir, referenceTemplate, version) + performFirstCommitPush := true + + //if chart already exists don't overrides it by reference template + if _, err := os.Stat(dir); os.IsNotExist(err) { + err = os.MkdirAll(dir, os.ModePerm) + if err != nil { + impl.logger.Errorw("error in making dir", "err", err) + return err + } + err = dirCopy.Copy(tempReferenceTemplateDir, dir) + if err != nil { + impl.logger.Errorw("error copying dir", "err", err) + return err + } + } else { + // auto-healing : data corruption fix - sometimes reference chart contents are not pushed in git-ops repo. + // copying content from reference template dir to cloned dir (if Chart.yaml file is not found) + // if Chart.yaml file is not found, we are assuming here that reference chart contents are not pushed in git-ops repo + if _, err := os.Stat(filepath.Join(dir, "Chart.yaml")); os.IsNotExist(err) { + impl.logger.Infow("auto-healing: Chart.yaml not found in cloned repo from git-ops. copying content", "from", tempReferenceTemplateDir, "to", dir) + err = dirCopy.Copy(tempReferenceTemplateDir, dir) + if err != nil { + impl.logger.Errorw("error copying content in auto-healing", "err", err) + return err + } + } else { + // chart exists on git, hence not performing first commit + performFirstCommitPush = false + } + } + + // if push needed, then only push + if performFirstCommitPush { + userEmailId, userName := impl.gitOpsConfigReadService.GetUserEmailIdAndNameForGitOpsCommit(userId) + commit, err := impl.gitFactory.GitService.CommitAndPushAllChanges(clonedDir, "first commit", userName, userEmailId) + if err != nil { + impl.logger.Errorw("error in pushing git", "err", err) + impl.logger.Warn("re-trying, taking pull and then push again") + err = impl.GitPull(clonedDir, repoUrl, gitOpsRepoName) + if err != nil { + return err + } + err = dirCopy.Copy(tempReferenceTemplateDir, dir) + if err != nil { + impl.logger.Errorw("error copying dir", "err", err) + return err + } + commit, err = impl.gitFactory.GitService.CommitAndPushAllChanges(clonedDir, "first commit", userName, userEmailId) + if err != nil { + impl.logger.Errorw("error in pushing git", "err", err) + return err + } + } + impl.logger.Debugw("template committed", "url", repoUrl, "commit", commit) + } + + return nil +} + +func (impl *GitOperationServiceImpl) CreateReadmeInGitRepo(gitOpsRepoName string, userId int32) error { + userEmailId, userName := impl.gitOpsConfigReadService.GetUserEmailIdAndNameForGitOpsCommit(userId) + gitOpsConfig, err := impl.gitOpsConfigReadService.GetGitOpsConfigActive() + if err != nil { + impl.logger.Errorw("error in getting active gitOps config", "err", err) + return err + } + //updating user email and name in request + if gitOpsConfig != nil { + gitOpsConfig.UserEmailId = userEmailId + gitOpsConfig.Username = userName + gitOpsConfig.GitRepoName = gitOpsRepoName + } + _, err = impl.gitFactory.Client.CreateReadme(gitOpsConfig) + if err != nil { + impl.logger.Errorw("error in creating readme", "err", err, "gitOpsRepoName", gitOpsRepoName, "userId", userId) + return err + } + return nil +} + +func (impl *GitOperationServiceImpl) CreateChartProxy(chartMetaData *chart.Metadata, refChartLocation string, envName string, + chartProxyReq *bean.ChartProxyReqDto) (string, *commonBean.ChartGitAttribute, error) { + chartMetaData.ApiVersion = "v2" // ensure always v2 + dir := impl.chartTemplateService.GetDir() + chartDir := filepath.Join(util.CHART_WORKING_DIR_PATH, dir) + impl.logger.Debugw("chart dir ", "chart", chartMetaData.Name, "dir", chartDir) + err := os.MkdirAll(chartDir, os.ModePerm) //hack for concurrency handling + if err != nil { + impl.logger.Errorw("err in creating dir", "dir", chartDir, "err", err) + return "", nil, err + } + defer impl.chartTemplateService.CleanDir(chartDir) + err = dirCopy.Copy(refChartLocation, chartDir) + + if err != nil { + impl.logger.Errorw("error in copying chart for app", "app", chartMetaData.Name, "error", err) + return "", nil, err + } + archivePath, valuesYaml, err := impl.chartTemplateService.PackageChart(chartDir, chartMetaData) + if err != nil { + impl.logger.Errorw("error in creating archive", "err", err) + return "", nil, err + } + + chartGitAttr, err := impl.createAndPushToGitChartProxy(chartMetaData.Name, chartDir, envName, chartProxyReq) + if err != nil { + impl.logger.Errorw("error in pushing chart to git ", "path", archivePath, "err", err) + return "", nil, err + } + if valuesYaml == "" { + valuesYaml = "{}" + } else { + valuesYamlByte, err := yaml.YAMLToJSON([]byte(valuesYaml)) + if err != nil { + return "", nil, err + } + valuesYaml = string(valuesYamlByte) + } + return valuesYaml, chartGitAttr, nil +} + +func (impl *GitOperationServiceImpl) createAndPushToGitChartProxy(appStoreName, tmpChartLocation string, envName string, + chartProxyReq *bean.ChartProxyReqDto) (chartGitAttribute *commonBean.ChartGitAttribute, err error) { + //baseTemplateName replace whitespace + space := regexp.MustCompile(`\s+`) + appStoreName = space.ReplaceAllString(appStoreName, "-") + + if len(chartProxyReq.GitOpsRepoName) == 0 { + //here git ops repo will be the app name, to breaking the mono repo structure + gitOpsRepoName := impl.gitOpsConfigReadService.GetGitOpsRepoName(chartProxyReq.AppName) + chartProxyReq.GitOpsRepoName = gitOpsRepoName + } + bitbucketMetadata, err := impl.gitOpsConfigReadService.GetBitbucketMetadata() + if err != nil { + impl.logger.Errorw("error in getting bitbucket metadata", "err", err) + return nil, err + } + //getting user name & emailId for commit author data + userEmailId, userName := impl.gitOpsConfigReadService.GetUserEmailIdAndNameForGitOpsCommit(chartProxyReq.UserId) + gitRepoRequest := &bean2.GitOpsConfigDto{ + GitRepoName: chartProxyReq.GitOpsRepoName, + Description: "helm chart for " + chartProxyReq.GitOpsRepoName, + Username: userName, + UserEmailId: userEmailId, + BitBucketWorkspaceId: bitbucketMetadata.BitBucketWorkspaceId, + BitBucketProjectKey: bitbucketMetadata.BitBucketProjectKey, + } + repoUrl, _, detailedError := impl.gitFactory.Client.CreateRepository(gitRepoRequest) + for _, err := range detailedError.StageErrorMap { + if err != nil { + impl.logger.Errorw("error in creating git project", "name", chartProxyReq.GitOpsRepoName, "err", err) + return nil, err + } + } + + chartDir := fmt.Sprintf("%s-%s", chartProxyReq.AppName, impl.chartTemplateService.GetDir()) + clonedDir, err := impl.GetClonedDir(chartDir, repoUrl) + if err != nil { + impl.logger.Errorw("error in cloning repo", "url", repoUrl, "err", err) + return nil, err + } + + err = impl.GitPull(clonedDir, repoUrl, appStoreName) + if err != nil { + return nil, err + } + + acdAppName := fmt.Sprintf("%s-%s", chartProxyReq.AppName, envName) + dir := filepath.Join(clonedDir, acdAppName) + err = os.MkdirAll(dir, os.ModePerm) + if err != nil { + impl.logger.Errorw("error in making dir", "err", err) + return nil, err + } + err = dirCopy.Copy(tmpChartLocation, dir) + if err != nil { + impl.logger.Errorw("error copying dir", "err", err) + return nil, err + } + commit, err := impl.gitFactory.GitService.CommitAndPushAllChanges(clonedDir, "first commit", userName, userEmailId) + if err != nil { + impl.logger.Errorw("error in pushing git", "err", err) + impl.logger.Warn("re-trying, taking pull and then push again") + err = impl.GitPull(clonedDir, repoUrl, acdAppName) + if err != nil { + return nil, err + } + err = dirCopy.Copy(tmpChartLocation, dir) + if err != nil { + impl.logger.Errorw("error copying dir", "err", err) + return nil, err + } + commit, err = impl.gitFactory.GitService.CommitAndPushAllChanges(clonedDir, "first commit", userName, userEmailId) + if err != nil { + impl.logger.Errorw("error in pushing git", "err", err) + return nil, err + } + } + impl.logger.Debugw("template committed", "url", repoUrl, "commit", commit) + defer impl.chartTemplateService.CleanDir(clonedDir) + return &commonBean.ChartGitAttribute{RepoUrl: repoUrl, ChartLocation: filepath.Join("", acdAppName)}, nil +} + +func (impl *GitOperationServiceImpl) GitPull(clonedDir string, repoUrl string, appStoreName string) error { + err := impl.gitFactory.GitService.Pull(clonedDir) //TODO check for local repo exists before clone + if err != nil { + impl.logger.Errorw("error in pulling git", "clonedDir", clonedDir, "err", err) + _, err := impl.gitFactory.GitService.Clone(repoUrl, appStoreName) + if err != nil { + impl.logger.Errorw("error in cloning repo", "url", repoUrl, "err", err) + return err + } + return nil + } + return nil +} + +func (impl *GitOperationServiceImpl) CommitValues(chartGitAttr *ChartConfig) (commitHash string, commitTime time.Time, err error) { + bitbucketMetadata, err := impl.gitOpsConfigReadService.GetBitbucketMetadata() + if err != nil { + impl.logger.Errorw("error in getting bitbucket metadata", "err", err) + return commitHash, commitTime, err + } + gitOpsConfig := &bean2.GitOpsConfigDto{BitBucketWorkspaceId: bitbucketMetadata.BitBucketWorkspaceId} + commitHash, commitTime, err = impl.gitFactory.Client.CommitValues(chartGitAttr, gitOpsConfig) + if err != nil { + impl.logger.Errorw("error in git commit", "err", err) + return commitHash, commitTime, err + } + return commitHash, commitTime, nil +} + +func (impl *GitOperationServiceImpl) CommitAndPushAllChanges(clonedDir, commitMsg, userName, userEmailId string) (commitHash string, err error) { + commitHash, err = impl.gitFactory.GitService.CommitAndPushAllChanges(clonedDir, commitMsg, userName, userEmailId) + if err != nil { + impl.logger.Errorw("error in pushing git", "err", err) + return commitHash, err + } + return commitHash, nil +} + +func (impl *GitOperationServiceImpl) CreateRepository(dto *bean2.GitOpsConfigDto, userId int32) (string, bool, error) { + //getting user name & emailId for commit author data + userEmailId, userName := impl.gitOpsConfigReadService.GetUserEmailIdAndNameForGitOpsCommit(userId) + if dto != nil { + dto.UserEmailId = userEmailId + dto.Username = userName + } + repoUrl, isNew, detailedError := impl.gitFactory.Client.CreateRepository(dto) + for _, err := range detailedError.StageErrorMap { + if err != nil { + impl.logger.Errorw("error in creating git project", "err", err, "req", dto) + return "", false, err + } + } + return repoUrl, isNew, nil +} + +func (impl *GitOperationServiceImpl) GetRepoUrlByRepoName(repoName string) (string, error) { + repoUrl := "" + bitbucketMetadata, err := impl.gitOpsConfigReadService.GetBitbucketMetadata() + if err != nil { + impl.logger.Errorw("error in getting bitbucket metadata", "err", err) + return repoUrl, err + } + dto := &bean2.GitOpsConfigDto{ + GitRepoName: repoName, + BitBucketWorkspaceId: bitbucketMetadata.BitBucketWorkspaceId, + BitBucketProjectKey: bitbucketMetadata.BitBucketProjectKey, + } + repoUrl, err = impl.gitFactory.Client.GetRepoUrl(dto) + if err != nil { + //will allow to continue to persist status on next operation + impl.logger.Errorw("error in getting repo url", "err", err, "repoName", repoName) + } + return repoUrl, nil +} + +func (impl *GitOperationServiceImpl) GetClonedDir(chartDir, repoUrl string) (string, error) { + clonedDir := impl.gitFactory.GitService.GetCloneDirectory(chartDir) + if _, err := os.Stat(clonedDir); os.IsNotExist(err) { + return impl.CloneInDir(repoUrl, chartDir) + } else if err != nil { + impl.logger.Errorw("error in cloning repo", "url", repoUrl, "err", err) + return "", err + } + return clonedDir, nil +} + +func (impl *GitOperationServiceImpl) CloneInDir(repoUrl, chartDir string) (string, error) { + clonedDir, err := impl.gitFactory.GitService.Clone(repoUrl, chartDir) + if err != nil { + impl.logger.Errorw("error in cloning repo", "url", repoUrl, "err", err) + return "", err + } + return clonedDir, nil +} diff --git a/internal/util/GitService.go b/pkg/deployment/gitOps/git/GitService.go similarity index 65% rename from internal/util/GitService.go rename to pkg/deployment/gitOps/git/GitService.go index 882772e523a..7577f2c8aea 100644 --- a/internal/util/GitService.go +++ b/pkg/deployment/gitOps/git/GitService.go @@ -15,14 +15,14 @@ * */ -package util +package git import ( "context" "fmt" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git/adapter" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git/bean" "github.com/devtron-labs/devtron/util" - "io/ioutil" - "net/url" "path/filepath" "time" @@ -57,16 +57,13 @@ type GitClient interface { GetRepoUrl(config *bean2.GitOpsConfigDto) (repoUrl string, err error) DeleteRepository(config *bean2.GitOpsConfigDto) error CreateReadme(config *bean2.GitOpsConfigDto) (string, error) - GetCommits(repoName, projectName string) ([]*GitCommitDto, error) } type GitFactory struct { - Client GitClient - GitService GitService - GitWorkingDir string - logger *zap.SugaredLogger - gitOpsRepository repository.GitOpsConfigRepository - gitCliUtil *GitCliUtil + Client GitClient + GitService GitService + logger *zap.SugaredLogger + gitCliUtil *GitCliUtil } type DetailedErrorGitOpsConfigActions struct { @@ -76,57 +73,38 @@ type DetailedErrorGitOpsConfigActions struct { DeleteRepoFailed bool `json:"deleteRepoFailed"` } -type GitCommitDto struct { - CommitHash string `json:"commitHash"` - AuthorName string `json:"authorName"` - CommitTime time.Time `json:"commitTime"` -} - -func (factory *GitFactory) Reload() error { +func (factory *GitFactory) Reload(gitOpsRepository repository.GitOpsConfigRepository) error { var err error start := time.Now() defer func() { util.TriggerGitOpsMetrics("Reload", "GitService", start, err) }() - logger.Infow("reloading gitops details") - cfg, err := GetGitConfig(factory.gitOpsRepository) + factory.logger.Infow("reloading gitops details") + cfg, err := GetGitConfig(gitOpsRepository) if err != nil { return err } - gitService := NewGitServiceImpl(cfg, logger, factory.gitCliUtil) + gitService := NewGitServiceImpl(cfg, factory.logger, factory.gitCliUtil) factory.GitService = gitService - client, err := NewGitOpsClient(cfg, logger, gitService, factory.gitOpsRepository) + client, err := NewGitOpsClient(cfg, factory.logger, gitService) if err != nil { return err } factory.Client = client - logger.Infow(" gitops details reload success") + factory.logger.Infow(" gitops details reload success") return nil } func (factory *GitFactory) GetGitLabGroupPath(gitOpsConfig *bean2.GitOpsConfigDto) (string, error) { start := time.Now() - var gitLabClient *gitlab.Client var err error defer func() { util.TriggerGitOpsMetrics("GetGitLabGroupPath", "GitService", start, err) }() - if len(gitOpsConfig.Host) > 0 { - _, err = url.ParseRequestURI(gitOpsConfig.Host) - if err != nil { - return "", err - } - gitLabClient, err = gitlab.NewClient(gitOpsConfig.Token, gitlab.WithBaseURL(gitOpsConfig.Host)) - if err != nil { - factory.logger.Errorw("error in getting new gitlab client", "err", err) - return "", err - } - } else { - gitLabClient, err = gitlab.NewClient(gitOpsConfig.Token) - if err != nil { - factory.logger.Errorw("error in getting new gitlab client", "err", err) - return "", err - } + gitLabClient, err := CreateGitlabClient(gitOpsConfig.Host, gitOpsConfig.Token) + if err != nil { + factory.logger.Errorw("error in creating gitlab client", "err", err) + return "", err } group, _, err := gitLabClient.Groups.GetGroup(gitOpsConfig.GitLabGroupId, &gitlab.GetGroupOptions{}) if err != nil { @@ -146,28 +124,16 @@ func (factory *GitFactory) NewClientForValidation(gitOpsConfig *bean2.GitOpsConf defer func() { util.TriggerGitOpsMetrics("NewClientForValidation", "GitService", start, err) }() - cfg := &GitConfig{ - GitlabGroupId: gitOpsConfig.GitLabGroupId, - GitToken: gitOpsConfig.Token, - GitUserName: gitOpsConfig.Username, - GitWorkingDir: GIT_WORKING_DIR, - GithubOrganization: gitOpsConfig.GitHubOrgId, - GitProvider: gitOpsConfig.Provider, - GitHost: gitOpsConfig.Host, - AzureToken: gitOpsConfig.Token, - AzureProject: gitOpsConfig.AzureProjectName, - BitbucketWorkspaceId: gitOpsConfig.BitBucketWorkspaceId, - BitbucketProjectKey: gitOpsConfig.BitBucketProjectKey, - } - gitService := NewGitServiceImpl(cfg, logger, factory.gitCliUtil) + cfg := adapter.ConvertGitOpsConfigToGitConfig(gitOpsConfig) + gitService := NewGitServiceImpl(cfg, factory.logger, factory.gitCliUtil) //factory.GitService = GitService - client, err := NewGitOpsClient(cfg, logger, gitService, factory.gitOpsRepository) + client, err := NewGitOpsClient(cfg, factory.logger, gitService) if err != nil { return client, gitService, err } //factory.Client = client - logger.Infow("client changed successfully", "cfg", cfg) + factory.logger.Infow("client changed successfully", "cfg", cfg) return client, gitService, nil } @@ -177,36 +143,19 @@ func NewGitFactory(logger *zap.SugaredLogger, gitOpsRepository repository.GitOps return nil, err } gitService := NewGitServiceImpl(cfg, logger, gitCliUtil) - client, err := NewGitOpsClient(cfg, logger, gitService, gitOpsRepository) + client, err := NewGitOpsClient(cfg, logger, gitService) if err != nil { logger.Errorw("error in creating gitOps client", "err", err, "gitProvider", cfg.GitProvider) } return &GitFactory{ - Client: client, - logger: logger, - GitService: gitService, - gitOpsRepository: gitOpsRepository, - GitWorkingDir: cfg.GitWorkingDir, - gitCliUtil: gitCliUtil, + Client: client, + logger: logger, + GitService: gitService, + gitCliUtil: gitCliUtil, }, nil } -type GitConfig struct { - GitlabGroupId string //local - GitlabGroupPath string //local - GitToken string //not null // public - GitUserName string //not null // public - GitWorkingDir string //working directory for git. might use pvc - GithubOrganization string - GitProvider string // SUPPORTED VALUES GITHUB, GITLAB - GitHost string - AzureToken string - AzureProject string - BitbucketWorkspaceId string - BitbucketProjectKey string -} - -func GetGitConfig(gitOpsRepository repository.GitOpsConfigRepository) (*GitConfig, error) { +func GetGitConfig(gitOpsRepository repository.GitOpsConfigRepository) (*bean.GitConfig, error) { gitOpsConfig, err := gitOpsRepository.GetGitOpsConfigActive() if err != nil && err != pg.ErrNoRows { return nil, err @@ -215,17 +164,16 @@ func GetGitConfig(gitOpsRepository repository.GitOpsConfigRepository) (*GitConfi // cfg := &GitConfig{} // err := env.Parse(cfg) // return cfg, err - return &GitConfig{}, nil + return &bean.GitConfig{}, nil } if gitOpsConfig == nil || gitOpsConfig.Id == 0 { return nil, err } - cfg := &GitConfig{ + cfg := &bean.GitConfig{ GitlabGroupId: gitOpsConfig.GitLabGroupId, GitToken: gitOpsConfig.Token, GitUserName: gitOpsConfig.Username, - GitWorkingDir: GIT_WORKING_DIR, GithubOrganization: gitOpsConfig.GitHubOrgId, GitProvider: gitOpsConfig.Provider, GitHost: gitOpsConfig.Host, @@ -237,18 +185,18 @@ func GetGitConfig(gitOpsRepository repository.GitOpsConfigRepository) (*GitConfi return cfg, err } -func NewGitOpsClient(config *GitConfig, logger *zap.SugaredLogger, gitService GitService, gitOpsConfigRepository repository.GitOpsConfigRepository) (GitClient, error) { +func NewGitOpsClient(config *bean.GitConfig, logger *zap.SugaredLogger, gitService GitService) (GitClient, error) { if config.GitProvider == GITLAB_PROVIDER { gitLabClient, err := NewGitLabClient(config, logger, gitService) return gitLabClient, err } else if config.GitProvider == GITHUB_PROVIDER { - gitHubClient, err := NewGithubClient(config.GitHost, config.GitToken, config.GithubOrganization, logger, gitService, gitOpsConfigRepository) + gitHubClient, err := NewGithubClient(config.GitHost, config.GitToken, config.GithubOrganization, logger, gitService) return gitHubClient, err } else if config.GitProvider == AZURE_DEVOPS_PROVIDER { - gitAzureClient, err := NewGitAzureClient(config.AzureToken, config.GitHost, config.AzureProject, logger, gitService, gitOpsConfigRepository) + gitAzureClient, err := NewGitAzureClient(config.AzureToken, config.GitHost, config.AzureProject, logger, gitService) return gitAzureClient, err } else if config.GitProvider == BITBUCKET_PROVIDER { - gitBitbucketClient := NewGitBitbucketClient(config.GitUserName, config.GitToken, config.GitHost, logger, gitService, gitOpsConfigRepository) + gitBitbucketClient := NewGitBitbucketClient(config.GitUserName, config.GitToken, config.GitHost, logger, gitService) return gitBitbucketClient, nil } else { logger.Errorw("no gitops config provided, gitops will not work ") @@ -271,36 +219,31 @@ type ChartConfig struct { type GitService interface { Clone(url, targetDir string) (clonedDir string, err error) CommitAndPushAllChanges(repoRoot, commitMsg, name, emailId string) (commitHash string, err error) - ForceResetHead(repoRoot string) (err error) - CommitValues(config *ChartConfig) (commitHash string, err error) GetCloneDirectory(targetDir string) (clonedDir string) Pull(repoRoot string) (err error) } type GitServiceImpl struct { Auth *http.BasicAuth - config *GitConfig logger *zap.SugaredLogger gitCliUtil *GitCliUtil } -func NewGitServiceImpl(config *GitConfig, logger *zap.SugaredLogger, GitCliUtil *GitCliUtil) *GitServiceImpl { +func NewGitServiceImpl(config *bean.GitConfig, logger *zap.SugaredLogger, GitCliUtil *GitCliUtil) *GitServiceImpl { auth := &http.BasicAuth{Password: config.GitToken, Username: config.GitUserName} return &GitServiceImpl{ Auth: auth, logger: logger, - config: config, gitCliUtil: GitCliUtil, } } func (impl GitServiceImpl) GetCloneDirectory(targetDir string) (clonedDir string) { - start := time.Now() defer func() { util.TriggerGitOpsMetrics("GetCloneDirectory", "GitService", start, nil) }() - clonedDir = filepath.Join(impl.config.GitWorkingDir, targetDir) + clonedDir = filepath.Join(GIT_WORKING_DIR, targetDir) return clonedDir } @@ -310,7 +253,7 @@ func (impl GitServiceImpl) Clone(url, targetDir string) (clonedDir string, err e util.TriggerGitOpsMetrics("Clone", "GitService", start, err) }() impl.logger.Debugw("git checkout ", "url", url, "dir", targetDir) - clonedDir = filepath.Join(impl.config.GitWorkingDir, targetDir) + clonedDir = filepath.Join(GIT_WORKING_DIR, targetDir) _, errorMsg, err := impl.gitCliUtil.Clone(clonedDir, url, impl.Auth.Username, impl.Auth.Password) if err != nil { impl.logger.Errorw("error in git checkout", "url", url, "targetDir", targetDir, "err", err) @@ -373,45 +316,6 @@ func (impl GitServiceImpl) getRepoAndWorktree(repoRoot string) (*git.Repository, return r, w, err } -func (impl GitServiceImpl) ForceResetHead(repoRoot string) (err error) { - start := time.Now() - defer func() { - util.TriggerGitOpsMetrics("ForceResetHead", "GitService", start, err) - }() - _, workTree, err := impl.getRepoAndWorktree(repoRoot) - if err != nil { - return err - } - err = workTree.Reset(&git.ResetOptions{Mode: git.HardReset}) - if err != nil { - return err - } - err = workTree.Pull(&git.PullOptions{ - Auth: impl.Auth, - Force: true, - SingleBranch: true, - }) - return err -} - -func (impl GitServiceImpl) CommitValues(config *ChartConfig) (commitHash string, err error) { - //TODO acquire lock - start := time.Now() - defer func() { - util.TriggerGitOpsMetrics("CommitValues", "GitService", start, err) - }() - gitDir := filepath.Join(impl.config.GitWorkingDir, config.ChartName) - if err != nil { - return "", err - } - err = ioutil.WriteFile(filepath.Join(gitDir, config.ChartLocation, config.FileName), []byte(config.FileContent), 0600) - if err != nil { - return "", err - } - hash, err := impl.CommitAndPushAllChanges(gitDir, config.ReleaseMessage, "devtron bot", "devtron-bot@devtron.ai") - return hash, err -} - func (impl GitServiceImpl) Pull(repoRoot string) (err error) { start := time.Now() defer func() { diff --git a/internal/util/GitServiceAzure.go b/pkg/deployment/gitOps/git/GitServiceAzure.go similarity index 87% rename from internal/util/GitServiceAzure.go rename to pkg/deployment/gitOps/git/GitServiceAzure.go index d47f4f8be4a..d474070f3d6 100644 --- a/internal/util/GitServiceAzure.go +++ b/pkg/deployment/gitOps/git/GitServiceAzure.go @@ -1,10 +1,9 @@ -package util +package git import ( "context" "fmt" bean2 "github.com/devtron-labs/devtron/api/bean" - "github.com/devtron-labs/devtron/internal/sql/repository" "github.com/microsoft/azure-devops-go-api/azuredevops" "github.com/microsoft/azure-devops-go-api/azuredevops/git" "go.uber.org/zap" @@ -13,11 +12,10 @@ import ( ) type GitAzureClient struct { - client *git.Client - logger *zap.SugaredLogger - project string - gitService GitService - gitOpsConfigRepository repository.GitOpsConfigRepository + client *git.Client + logger *zap.SugaredLogger + project string + gitService GitService } func (impl GitAzureClient) GetRepoUrl(config *bean2.GitOpsConfigDto) (repoUrl string, err error) { @@ -31,8 +29,7 @@ func (impl GitAzureClient) GetRepoUrl(config *bean2.GitOpsConfigDto) (repoUrl st } } -func NewGitAzureClient(token string, host string, project string, logger *zap.SugaredLogger, gitService GitService, - gitOpsConfigRepository repository.GitOpsConfigRepository) (GitAzureClient, error) { +func NewGitAzureClient(token string, host string, project string, logger *zap.SugaredLogger, gitService GitService) (GitAzureClient, error) { ctx := context.Background() // Create a connection to your organization connection := azuredevops.NewPatConnection(host, token) @@ -42,11 +39,10 @@ func NewGitAzureClient(token string, host string, project string, logger *zap.Su logger.Errorw("error in creating azure gitops client, gitops related operation might fail", "err", err) } return GitAzureClient{ - client: &coreClient, - project: project, - logger: logger, - gitService: gitService, - gitOpsConfigRepository: gitOpsConfigRepository, + client: &coreClient, + project: project, + logger: logger, + gitService: gitService, }, err } func (impl GitAzureClient) DeleteRepository(config *bean2.GitOpsConfigDto) error { @@ -91,7 +87,7 @@ func (impl GitAzureClient) CreateRepository(config *bean2.GitOpsConfigDto) (url detailedErrorGitOpsConfigActions.StageErrorMap[CreateRepoStage] = err return "", true, detailedErrorGitOpsConfigActions } - logger.Infow("repo created ", "r", operationReference.WebUrl) + impl.logger.Infow("repo created ", "r", operationReference.WebUrl) detailedErrorGitOpsConfigActions.SuccessfulStages = append(detailedErrorGitOpsConfigActions.SuccessfulStages, CreateRepoStage) validated, err := impl.ensureProjectAvailabilityOnHttp(config.GitRepoName) if err != nil { @@ -237,7 +233,7 @@ func (impl GitAzureClient) CommitValues(config *ChartConfig, gitOpsConfig *bean2 } //gitPush.Commits commitId := "" - commitAuthorTime := time.Time{} + commitAuthorTime := time.Now() //default is current time, if found then will get updated accordingly if len(*push.Commits) > 0 { commitId = *(*push.Commits)[0].CommitId commitAuthorTime = (*push.Commits)[0].Author.Date.Time @@ -298,26 +294,3 @@ func (impl GitAzureClient) ensureProjectAvailabilityOnSsh(projectName string, re } return false, nil } - -func (impl GitAzureClient) GetCommits(repoName, projectName string) ([]*GitCommitDto, error) { - azureClient := *impl.client - getCommitsArgs := git.GetCommitsArgs{ - RepositoryId: &repoName, - Project: &projectName, - } - gitCommits, err := azureClient.GetCommits(context.Background(), getCommitsArgs) - if err != nil { - impl.logger.Errorw("error in getting commits", "err", err, "repoName", repoName, "projectName", projectName) - return nil, err - } - var gitCommitsDto []*GitCommitDto - for _, gitCommit := range *gitCommits { - gitCommitDto := &GitCommitDto{ - CommitHash: *gitCommit.CommitId, - AuthorName: *gitCommit.Author.Name, - CommitTime: gitCommit.Author.Date.Time, - } - gitCommitsDto = append(gitCommitsDto, gitCommitDto) - } - return gitCommitsDto, nil -} diff --git a/internal/util/GitServiceBitbucket.go b/pkg/deployment/gitOps/git/GitServiceBitbucket.go similarity index 81% rename from internal/util/GitServiceBitbucket.go rename to pkg/deployment/gitOps/git/GitServiceBitbucket.go index 8be8359c0ee..a7f6cd16935 100644 --- a/internal/util/GitServiceBitbucket.go +++ b/pkg/deployment/gitOps/git/GitServiceBitbucket.go @@ -1,10 +1,8 @@ -package util +package git import ( "fmt" bean2 "github.com/devtron-labs/devtron/api/bean" - "github.com/devtron-labs/devtron/internal/sql/repository" - "github.com/go-pg/pg" "github.com/ktrysmt/go-bitbucket" "go.uber.org/zap" "io/ioutil" @@ -22,21 +20,18 @@ const ( ) type GitBitbucketClient struct { - client *bitbucket.Client - logger *zap.SugaredLogger - gitService GitService - gitOpsConfigRepository repository.GitOpsConfigRepository + client *bitbucket.Client + logger *zap.SugaredLogger + gitService GitService } -func NewGitBitbucketClient(username, token, host string, logger *zap.SugaredLogger, gitService GitService, - gitOpsConfigRepository repository.GitOpsConfigRepository) GitBitbucketClient { +func NewGitBitbucketClient(username, token, host string, logger *zap.SugaredLogger, gitService GitService) GitBitbucketClient { coreClient := bitbucket.NewBasicAuth(username, token) logger.Infow("bitbucket client created", "clientDetails", coreClient) return GitBitbucketClient{ - client: coreClient, - logger: logger, - gitService: gitService, - gitOpsConfigRepository: gitOpsConfigRepository, + client: coreClient, + logger: logger, + gitService: gitService, } } @@ -100,7 +95,7 @@ func (impl GitBitbucketClient) CreateRepository(config *bean2.GitOpsConfigDto) ( return "", true, detailedErrorGitOpsConfigActions } repoUrl = fmt.Sprintf(BITBUCKET_CLONE_BASE_URL+"%s/%s.git", repoOptions.Owner, repoOptions.RepoSlug) - logger.Infow("repo created ", "repoUrl", repoUrl) + impl.logger.Infow("repo created ", "repoUrl", repoUrl) detailedErrorGitOpsConfigActions.SuccessfulStages = append(detailedErrorGitOpsConfigActions.SuccessfulStages, CreateRepoStage) validated, err := impl.ensureProjectAvailabilityOnHttp(repoOptions) @@ -256,47 +251,3 @@ func (impl GitBitbucketClient) CommitValues(config *ChartConfig, gitOpsConfig *b } return commitHash, commitTime, nil } - -func (impl GitBitbucketClient) GetCommits(repoName, projectName string) ([]*GitCommitDto, error) { - gitOpsConfigBitbucket, err := impl.gitOpsConfigRepository.GetGitOpsConfigByProvider(BITBUCKET_PROVIDER) - if err != nil { - if err == pg.ErrNoRows { - gitOpsConfigBitbucket = &repository.GitOpsConfig{} - gitOpsConfigBitbucket.BitBucketWorkspaceId = "" - gitOpsConfigBitbucket.BitBucketProjectKey = "" - } else { - impl.logger.Errorw("error in fetching gitOps bitbucket config", "err", err) - return nil, err - } - } - bitbucketWorkspaceId := gitOpsConfigBitbucket.BitBucketWorkspaceId - bitbucketClient := impl.client - getCommitsOptions := &bitbucket.CommitsOptions{ - RepoSlug: repoName, - Owner: bitbucketWorkspaceId, - Branchortag: "master", - } - gitCommitsIf, err := bitbucketClient.Repositories.Commits.GetCommits(getCommitsOptions) - if err != nil { - impl.logger.Errorw("error in getting commits", "err", err, "repoName", repoName) - return nil, err - } - - gitCommits := gitCommitsIf.(map[string]interface{})["values"].([]interface{}) - var gitCommitsDto []*GitCommitDto - for _, gitCommit := range gitCommits { - - commitHash := gitCommit.(map[string]string)["hash"] - commitTime, err := time.Parse(time.RFC3339, gitCommit.(map[string]interface{})["date"].(string)) - if err != nil { - impl.logger.Errorw("error in getting commitTime", "err", err, "gitCommit", gitCommit) - return nil, err - } - gitCommitDto := &GitCommitDto{ - CommitHash: commitHash, - CommitTime: commitTime, - } - gitCommitsDto = append(gitCommitsDto, gitCommitDto) - } - return gitCommitsDto, nil -} diff --git a/internal/util/GitServiceGithub.go b/pkg/deployment/gitOps/git/GitServiceGithub.go similarity index 85% rename from internal/util/GitServiceGithub.go rename to pkg/deployment/gitOps/git/GitServiceGithub.go index 12efedebc35..2d4fc52fbf4 100644 --- a/internal/util/GitServiceGithub.go +++ b/pkg/deployment/gitOps/git/GitServiceGithub.go @@ -1,10 +1,9 @@ -package util +package git import ( "context" "fmt" bean2 "github.com/devtron-labs/devtron/api/bean" - "github.com/devtron-labs/devtron/internal/sql/repository" "github.com/google/go-github/github" "go.uber.org/zap" "golang.org/x/oauth2" @@ -16,17 +15,14 @@ import ( ) type GitHubClient struct { - client *github.Client - - //config *GitConfig - logger *zap.SugaredLogger - org string - gitService GitService - gitOpsConfigRepository repository.GitOpsConfigRepository + client *github.Client + logger *zap.SugaredLogger + org string + gitService GitService } func NewGithubClient(host string, token string, org string, logger *zap.SugaredLogger, - gitService GitService, gitOpsConfigRepository repository.GitOpsConfigRepository) (GitHubClient, error) { + gitService GitService) (GitHubClient, error) { ctx := context.Background() httpTransport := &http2.Transport{} httpClient := &http2.Client{Transport: httpTransport} @@ -52,11 +48,10 @@ func NewGithubClient(host string, token string, org string, logger *zap.SugaredL } return GitHubClient{ - client: client, - org: org, - logger: logger, - gitService: gitService, - gitOpsConfigRepository: gitOpsConfigRepository, + client: client, + org: org, + logger: logger, + gitService: gitService, }, err } func (impl GitHubClient) DeleteRepository(config *bean2.GitOpsConfigDto) error { @@ -99,7 +94,7 @@ func (impl GitHubClient) CreateRepository(config *bean2.GitOpsConfigDto) (url st detailedErrorGitOpsConfigActions.StageErrorMap[CreateRepoStage] = err return "", true, detailedErrorGitOpsConfigActions } - logger.Infow("github repo created ", "r", r.CloneURL) + impl.logger.Infow("github repo created ", "r", r.CloneURL) detailedErrorGitOpsConfigActions.SuccessfulStages = append(detailedErrorGitOpsConfigActions.SuccessfulStages, CreateRepoStage) validated, err := impl.ensureProjectAvailabilityOnHttp(config) @@ -196,7 +191,11 @@ func (impl GitHubClient) CommitValues(config *ChartConfig, gitOpsConfig *bean2.G impl.logger.Errorw("error in commit github", "err", err, "config", config) return "", time.Time{}, err } - return *c.SHA, *c.Commit.Author.Date, nil + commitTime = time.Now() // default is current time, if found then will get updated accordingly + if c != nil && c.Commit.Author != nil { + commitTime = *c.Commit.Author.Date + } + return *c.SHA, commitTime, nil } func (impl GitHubClient) GetRepoUrl(config *bean2.GitOpsConfigDto) (repoUrl string, err error) { @@ -244,22 +243,3 @@ func (impl GitHubClient) ensureProjectAvailabilityOnSsh(projectName string, repo } return false, nil } - -func (impl GitHubClient) GetCommits(repoName, projectName string) ([]*GitCommitDto, error) { - githubClient := impl.client - gitCommits, _, err := githubClient.Repositories.ListCommits(context.Background(), impl.org, repoName, &github.CommitsListOptions{}) - if err != nil { - impl.logger.Errorw("error in getting commits", "err", err, "repoName", repoName) - return nil, err - } - var gitCommitsDto []*GitCommitDto - for _, gitCommit := range gitCommits { - gitCommitDto := &GitCommitDto{ - CommitHash: gitCommit.GetSHA(), - AuthorName: *gitCommit.Author.Name, - CommitTime: *gitCommit.Commit.Author.Date, - } - gitCommitsDto = append(gitCommitsDto, gitCommitDto) - } - return gitCommitsDto, nil -} diff --git a/internal/util/GitServiceGitlab.go b/pkg/deployment/gitOps/git/GitServiceGitlab.go similarity index 89% rename from internal/util/GitServiceGitlab.go rename to pkg/deployment/gitOps/git/GitServiceGitlab.go index ad34974412c..12eb11e85e5 100644 --- a/internal/util/GitServiceGitlab.go +++ b/pkg/deployment/gitOps/git/GitServiceGitlab.go @@ -1,8 +1,9 @@ -package util +package git import ( "fmt" bean2 "github.com/devtron-labs/devtron/api/bean" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git/bean" "github.com/xanzy/go-gitlab" "go.uber.org/zap" "net/url" @@ -13,30 +14,17 @@ import ( type GitLabClient struct { client *gitlab.Client - config *GitConfig + config *bean.GitConfig logger *zap.SugaredLogger gitService GitService } -func NewGitLabClient(config *GitConfig, logger *zap.SugaredLogger, gitService GitService) (GitClient, error) { - var gitLabClient *gitlab.Client - var err error - if len(config.GitHost) > 0 { - _, err = url.ParseRequestURI(config.GitHost) - if err != nil { - return nil, err - } - gitLabClient, err = gitlab.NewClient(config.GitToken, gitlab.WithBaseURL(config.GitHost)) - if err != nil { - return nil, err - } - } else { - gitLabClient, err = gitlab.NewClient(config.GitToken) - if err != nil { - return nil, err - } +func NewGitLabClient(config *bean.GitConfig, logger *zap.SugaredLogger, gitService GitService) (GitClient, error) { + gitLabClient, err := CreateGitlabClient(config.GitHost, config.GitToken) + if err != nil { + logger.Errorw("error in creating gitlab client", "err", err) + return nil, err } - gitlabGroupId := "" if len(config.GitlabGroupId) > 0 { if _, err := strconv.Atoi(config.GitlabGroupId); err == nil { @@ -82,6 +70,27 @@ func NewGitLabClient(config *GitConfig, logger *zap.SugaredLogger, gitService Gi }, nil } +func CreateGitlabClient(host, token string) (*gitlab.Client, error) { + var gitLabClient *gitlab.Client + var err error + if len(host) > 0 { + _, err = url.ParseRequestURI(host) + if err != nil { + return nil, err + } + gitLabClient, err = gitlab.NewClient(token, gitlab.WithBaseURL(host)) + if err != nil { + return nil, err + } + } else { + gitLabClient, err = gitlab.NewClient(token) + if err != nil { + return nil, err + } + } + return gitLabClient, err +} + func (impl GitLabClient) DeleteRepository(config *bean2.GitOpsConfigDto) error { err := impl.DeleteProject(config.GitRepoName) if err != nil { @@ -267,28 +276,9 @@ func (impl GitLabClient) CommitValues(config *ChartConfig, gitOpsConfig *bean2.G if err != nil { return "", time.Time{}, err } - return c.ID, *c.AuthoredDate, err -} - -func (impl GitLabClient) GetCommits(repoName, projectName string) ([]*GitCommitDto, error) { - gitlabClient := impl.client - branch := "master" - listCommitOptions := &gitlab.ListCommitsOptions{ - RefName: &branch, - } - gitCommits, _, err := gitlabClient.Commits.ListCommits(fmt.Sprintf("%s/%s", impl.config.GitlabGroupPath, repoName), listCommitOptions) - if err != nil { - impl.logger.Errorw("error in getting commits", "err", err, "repoName", repoName) - return nil, err - } - var gitCommitsDto []*GitCommitDto - for _, gitCommit := range gitCommits { - gitCommitDto := &GitCommitDto{ - CommitHash: gitCommit.String(), - AuthorName: gitCommit.AuthorName, - CommitTime: *gitCommit.AuthoredDate, - } - gitCommitsDto = append(gitCommitsDto, gitCommitDto) + commitTime = time.Now() //default is current time, if found then will get updated accordingly + if c != nil { + commitTime = *c.AuthoredDate } - return gitCommitsDto, nil + return c.ID, commitTime, err } diff --git a/internal/util/GitService_test.go b/pkg/deployment/gitOps/git/GitService_test.go similarity index 81% rename from internal/util/GitService_test.go rename to pkg/deployment/gitOps/git/GitService_test.go index 6c23a4202d7..3726bfdfcca 100644 --- a/internal/util/GitService_test.go +++ b/pkg/deployment/gitOps/git/GitService_test.go @@ -1,16 +1,18 @@ -package util +package git import ( "github.com/devtron-labs/devtron/api/bean" + "github.com/devtron-labs/devtron/internal/util" + bean2 "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git/bean" "testing" ) func getTestGithubClient() GitHubClient { - logger, err := NewSugardLogger() + logger, err := util.NewSugardLogger() gitCliUtl := NewGitCliUtil(logger) - gitService := NewGitServiceImpl(&GitConfig{GitToken: "", GitUserName: "nishant"}, logger, gitCliUtl) + gitService := NewGitServiceImpl(&bean2.GitConfig{GitToken: "", GitUserName: "nishant"}, logger, gitCliUtl) - githubClient, err := NewGithubClient("", "", "test-org", logger, gitService, nil) + githubClient, err := NewGithubClient("", "", "test-org", logger, gitService) if err != nil { panic(err) } diff --git a/pkg/deployment/gitOps/git/adapter/adapter.go b/pkg/deployment/gitOps/git/adapter/adapter.go new file mode 100644 index 00000000000..62b7f9c9644 --- /dev/null +++ b/pkg/deployment/gitOps/git/adapter/adapter.go @@ -0,0 +1,21 @@ +package adapter + +import ( + bean2 "github.com/devtron-labs/devtron/api/bean" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git/bean" +) + +func ConvertGitOpsConfigToGitConfig(dto *bean2.GitOpsConfigDto) *bean.GitConfig { + return &bean.GitConfig{ + GitlabGroupId: dto.GitLabGroupId, + GitToken: dto.Token, + GitUserName: dto.Username, + GithubOrganization: dto.GitHubOrgId, + GitProvider: dto.Provider, + GitHost: dto.Host, + AzureToken: dto.Token, + AzureProject: dto.AzureProjectName, + BitbucketWorkspaceId: dto.BitBucketWorkspaceId, + BitbucketProjectKey: dto.BitBucketProjectKey, + } +} diff --git a/pkg/deployment/gitOps/git/bean/bean.go b/pkg/deployment/gitOps/git/bean/bean.go new file mode 100644 index 00000000000..c806e552516 --- /dev/null +++ b/pkg/deployment/gitOps/git/bean/bean.go @@ -0,0 +1,21 @@ +package bean + +type ChartProxyReqDto struct { + GitOpsRepoName string `json:"gitOpsRepoName"` + AppName string `json:"appName,omitempty"` + UserId int32 `json:"-"` +} + +type GitConfig struct { + GitlabGroupId string //local + GitlabGroupPath string //local + GitToken string //not null // public + GitUserName string //not null // public + GithubOrganization string + GitProvider string // SUPPORTED VALUES GITHUB, GITLAB + GitHost string + AzureToken string + AzureProject string + BitbucketWorkspaceId string + BitbucketProjectKey string +} diff --git a/pkg/deployment/gitOps/wire_gitOps.go b/pkg/deployment/gitOps/wire_gitOps.go new file mode 100644 index 00000000000..7c2df272710 --- /dev/null +++ b/pkg/deployment/gitOps/wire_gitOps.go @@ -0,0 +1,19 @@ +package gitOps + +import ( + "github.com/devtron-labs/devtron/internal/sql/repository" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git" + "github.com/google/wire" +) + +var GitOpsWireSet = wire.NewSet( + repository.NewGitOpsConfigRepositoryImpl, + wire.Bind(new(repository.GitOpsConfigRepository), new(*repository.GitOpsConfigRepositoryImpl)), + + config.NewGitOpsConfigReadServiceImpl, + wire.Bind(new(config.GitOpsConfigReadService), new(*config.GitOpsConfigReadServiceImpl)), + + git.NewGitOperationServiceImpl, + wire.Bind(new(git.GitOperationService), new(*git.GitOperationServiceImpl)), +) diff --git a/pkg/deployment/manifest/deployedAppMetrics/DeployedAppMetrics.go b/pkg/deployment/manifest/deployedAppMetrics/DeployedAppMetrics.go new file mode 100644 index 00000000000..1e1e81b55e2 --- /dev/null +++ b/pkg/deployment/manifest/deployedAppMetrics/DeployedAppMetrics.go @@ -0,0 +1,215 @@ +package deployedAppMetrics + +import ( + "context" + "github.com/devtron-labs/devtron/internal/util" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deployedAppMetrics/bean" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deployedAppMetrics/repository" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/chartRef" + "github.com/devtron-labs/devtron/pkg/sql" + "github.com/go-pg/pg" + "go.opentelemetry.io/otel" + "go.uber.org/zap" + "time" +) + +type DeployedAppMetricsService interface { + GetMetricsFlagByAppId(appId int) (bool, error) + GetMetricsFlagByAppIdAndEnvId(appId, envId int) (bool, error) + GetMetricsFlagForAPipelineByAppIdAndEnvId(appId, envId int) (bool, error) + CreateOrUpdateAppOrEnvLevelMetrics(ctx context.Context, req *bean.DeployedAppMetricsRequest) error + DeleteEnvLevelMetricsIfPresent(appId, envId int) error +} + +type DeployedAppMetricsServiceImpl struct { + logger *zap.SugaredLogger + appLevelMetricsRepository repository.AppLevelMetricsRepository + envLevelMetricsRepository repository.EnvLevelAppMetricsRepository + chartRefService chartRef.ChartRefService +} + +func NewDeployedAppMetricsServiceImpl(logger *zap.SugaredLogger, + appLevelMetricsRepository repository.AppLevelMetricsRepository, + envLevelMetricsRepository repository.EnvLevelAppMetricsRepository, + chartRefService chartRef.ChartRefService) *DeployedAppMetricsServiceImpl { + return &DeployedAppMetricsServiceImpl{ + logger: logger, + appLevelMetricsRepository: appLevelMetricsRepository, + envLevelMetricsRepository: envLevelMetricsRepository, + chartRefService: chartRefService, + } +} + +func (impl *DeployedAppMetricsServiceImpl) GetMetricsFlagByAppId(appId int) (bool, error) { + isAppMetricsEnabled := false + appMetrics, err := impl.appLevelMetricsRepository.FindByAppId(appId) + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("error in fetching app level metrics", "appId", appId, "err", err) + return isAppMetricsEnabled, err + } + if appMetrics != nil { + isAppMetricsEnabled = appMetrics.AppMetrics + } + return isAppMetricsEnabled, nil +} + +func (impl *DeployedAppMetricsServiceImpl) GetMetricsFlagByAppIdAndEnvId(appId, envId int) (bool, error) { + isAppMetricsEnabled := false + envLevelAppMetrics, err := impl.envLevelMetricsRepository.FindByAppIdAndEnvId(appId, envId) + if err != nil { + impl.logger.Errorw("error in getting env level app metrics", "err", err, "appId", appId, "envId", envId) + return isAppMetricsEnabled, err + } + if envLevelAppMetrics != nil { + isAppMetricsEnabled = envLevelAppMetrics.AppMetrics + } + return isAppMetricsEnabled, nil +} + +// GetMetricsFlagForAPipelineByAppIdAndEnvId - this function returns metrics flag for pipeline after resolving override and app level values +func (impl *DeployedAppMetricsServiceImpl) GetMetricsFlagForAPipelineByAppIdAndEnvId(appId, envId int) (bool, error) { + isAppMetricsEnabled := false + envLevelAppMetrics, err := impl.envLevelMetricsRepository.FindByAppIdAndEnvId(appId, envId) + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("error in getting env level app metrics", "err", err, "appId", appId, "envId", envId) + return isAppMetricsEnabled, err + } else if err == pg.ErrNoRows { + isAppLevelMetricsEnabled, err := impl.GetMetricsFlagByAppId(appId) + if err != nil { + impl.logger.Errorw("error, GetMetricsFlagByAppId", "err", err, "appId", appId) + return false, err + } + isAppMetricsEnabled = isAppLevelMetricsEnabled + } else if envLevelAppMetrics != nil { + isAppMetricsEnabled = envLevelAppMetrics.AppMetrics + } + return isAppMetricsEnabled, nil +} + +// CheckAndUpdateAppOrEnvLevelMetrics - this method checks whether chart being used supports metrics or not, is app level or env level and updates accordingly +func (impl *DeployedAppMetricsServiceImpl) CreateOrUpdateAppOrEnvLevelMetrics(ctx context.Context, req *bean.DeployedAppMetricsRequest) error { + isAppMetricsSupported, err := impl.checkIsAppMetricsSupported(req.ChartRefId) + if err != nil { + return err + } + if !(isAppMetricsSupported) { + //chart does not have metrics support, disabling + req.EnableMetrics = false + } + if req.EnvId == 0 { + _, span := otel.Tracer("orchestrator").Start(ctx, "createOrUpdateAppLevelMetrics") + _, err = impl.createOrUpdateAppLevelMetrics(req) + span.End() + if err != nil { + impl.logger.Errorw("error in disable app metric flag", "error", err, "req", req) + return err + } + } else { + _, span := otel.Tracer("orchestrator").Start(ctx, "createOrUpdateEnvLevelMetrics") + _, err = impl.createOrUpdateEnvLevelMetrics(req) + span.End() + if err != nil { + impl.logger.Errorw("error in disable env level app metric flag", "error", err, "req", req) + return err + } + } + return nil +} + +func (impl *DeployedAppMetricsServiceImpl) DeleteEnvLevelMetricsIfPresent(appId, envId int) error { + envLevelAppMetrics, err := impl.envLevelMetricsRepository.FindByAppIdAndEnvId(appId, envId) + if err != nil && !util.IsErrNoRows(err) { + impl.logger.Errorw("error while fetching env level app metric", "err", err, "appId", appId, "envId", envId) + return err + } + if envLevelAppMetrics != nil && envLevelAppMetrics.Id > 0 { + err = impl.envLevelMetricsRepository.Delete(envLevelAppMetrics) + if err != nil { + impl.logger.Errorw("error while deletion of app metric at env level", "err", err, "model", envLevelAppMetrics) + return err + } + } + return nil +} + +func (impl *DeployedAppMetricsServiceImpl) checkIsAppMetricsSupported(chartRefId int) (bool, error) { + chartRefValue, err := impl.chartRefService.FindById(chartRefId) + if err != nil { + impl.logger.Errorw("error in finding reference chart by id", "err", err) + return false, nil + } + return chartRefValue.IsAppMetricsSupported, nil +} + +func (impl *DeployedAppMetricsServiceImpl) createOrUpdateAppLevelMetrics(req *bean.DeployedAppMetricsRequest) (*repository.AppLevelMetrics, error) { + existingAppLevelMetrics, err := impl.appLevelMetricsRepository.FindByAppId(req.AppId) + if err != nil && err != pg.ErrNoRows { + impl.logger.Errorw("error in app metrics app level flag", "error", err) + return nil, err + } + if existingAppLevelMetrics != nil && existingAppLevelMetrics.Id != 0 { + existingAppLevelMetrics.AppMetrics = req.EnableMetrics + existingAppLevelMetrics.UpdatedBy = req.UserId + existingAppLevelMetrics.UpdatedOn = time.Now() + err := impl.appLevelMetricsRepository.Update(existingAppLevelMetrics) + if err != nil { + impl.logger.Errorw("error in to updating app level metrics", "error", err, "model", existingAppLevelMetrics) + return nil, err + } + return existingAppLevelMetrics, nil + } else { + appLevelMetricsNew := &repository.AppLevelMetrics{ + AppId: req.AppId, + AppMetrics: req.EnableMetrics, + AuditLog: sql.AuditLog{ + CreatedOn: time.Now(), + UpdatedOn: time.Now(), + CreatedBy: req.UserId, + UpdatedBy: req.UserId, + }, + } + err = impl.appLevelMetricsRepository.Save(appLevelMetricsNew) + if err != nil { + impl.logger.Errorw("error in saving app level metrics flag", "error", err, "model", appLevelMetricsNew) + return appLevelMetricsNew, err + } + return appLevelMetricsNew, nil + } +} + +func (impl *DeployedAppMetricsServiceImpl) createOrUpdateEnvLevelMetrics(req *bean.DeployedAppMetricsRequest) (*repository.EnvLevelAppMetrics, error) { + // update and create env level app metrics + envLevelAppMetrics, err := impl.envLevelMetricsRepository.FindByAppIdAndEnvId(req.AppId, req.EnvId) + if err != nil && err != pg.ErrNoRows { + impl.logger.Error("err", err) + return nil, err + } + if envLevelAppMetrics == nil || envLevelAppMetrics.Id == 0 { + envLevelAppMetrics = &repository.EnvLevelAppMetrics{ + AppId: req.AppId, + EnvId: req.EnvId, + AppMetrics: req.EnableMetrics, + AuditLog: sql.AuditLog{ + CreatedOn: time.Now(), + UpdatedOn: time.Now(), + CreatedBy: req.UserId, + UpdatedBy: req.UserId, + }, + } + err = impl.envLevelMetricsRepository.Save(envLevelAppMetrics) + if err != nil { + impl.logger.Error("err", err) + return nil, err + } + } else { + envLevelAppMetrics.AppMetrics = req.EnableMetrics + envLevelAppMetrics.UpdatedOn = time.Now() + envLevelAppMetrics.UpdatedBy = req.UserId + err = impl.envLevelMetricsRepository.Update(envLevelAppMetrics) + if err != nil { + impl.logger.Error("err", err) + return nil, err + } + } + return envLevelAppMetrics, err +} diff --git a/pkg/deployment/manifest/deployedAppMetrics/bean/bean.go b/pkg/deployment/manifest/deployedAppMetrics/bean/bean.go new file mode 100644 index 00000000000..42761fdc486 --- /dev/null +++ b/pkg/deployment/manifest/deployedAppMetrics/bean/bean.go @@ -0,0 +1,9 @@ +package bean + +type DeployedAppMetricsRequest struct { + EnableMetrics bool + AppId int + EnvId int // if not zero then request for override + ChartRefId int + UserId int32 +} diff --git a/internal/sql/repository/AppLevelMetricsRepository.go b/pkg/deployment/manifest/deployedAppMetrics/repository/AppLevelMetricsRepository.go similarity index 86% rename from internal/sql/repository/AppLevelMetricsRepository.go rename to pkg/deployment/manifest/deployedAppMetrics/repository/AppLevelMetricsRepository.go index 6e3568e11a4..1a67deefdd9 100644 --- a/internal/sql/repository/AppLevelMetricsRepository.go +++ b/pkg/deployment/manifest/deployedAppMetrics/repository/AppLevelMetricsRepository.go @@ -24,11 +24,11 @@ import ( ) type AppLevelMetrics struct { - tableName struct{} `sql:"app_level_metrics" pg:",discard_unknown_columns"` - Id int `sql:"id,pk"` - AppId int `sql:"app_id,notnull"` - AppMetrics bool `sql:"app_metrics,notnull"` - InfraMetrics bool `sql:"infra_metrics,notnull"` + tableName struct{} `sql:"app_level_metrics" pg:",discard_unknown_columns"` + Id int `sql:"id,pk"` + AppId int `sql:"app_id,notnull"` + AppMetrics bool `sql:"app_metrics,notnull"` + //InfraMetrics bool `sql:"infra_metrics,notnull"` not being used sql.AuditLog } diff --git a/internal/sql/repository/EnvLevelAppMetricsRepository.go b/pkg/deployment/manifest/deployedAppMetrics/repository/EnvLevelAppMetricsRepository.go similarity index 87% rename from internal/sql/repository/EnvLevelAppMetricsRepository.go rename to pkg/deployment/manifest/deployedAppMetrics/repository/EnvLevelAppMetricsRepository.go index c26ce4146e2..9c985ab6e3f 100644 --- a/internal/sql/repository/EnvLevelAppMetricsRepository.go +++ b/pkg/deployment/manifest/deployedAppMetrics/repository/EnvLevelAppMetricsRepository.go @@ -24,12 +24,12 @@ import ( ) type EnvLevelAppMetrics struct { - tableName struct{} `sql:"env_level_app_metrics" pg:",discard_unknown_columns"` - Id int `sql:"id,pk"` - AppId int `sql:"app_id,notnull"` - EnvId int `sql:"env_id,notnull"` - AppMetrics *bool `sql:"app_metrics,notnull"` - InfraMetrics *bool `sql:"infra_metrics,notnull"` + tableName struct{} `sql:"env_level_app_metrics" pg:",discard_unknown_columns"` + Id int `sql:"id,pk"` + AppId int `sql:"app_id,notnull"` + EnvId int `sql:"env_id,notnull"` + AppMetrics bool `sql:"app_metrics,notnull"` + //InfraMetrics *bool `sql:"infra_metrics,notnull"` not being used sql.AuditLog } @@ -57,7 +57,8 @@ func (impl *EnvLevelAppMetricsRepositoryImpl) Save(metrics *EnvLevelAppMetrics) func (impl *EnvLevelAppMetricsRepositoryImpl) FindByAppIdAndEnvId(appId int, envId int) (*EnvLevelAppMetrics, error) { envAppLevelMetrics := &EnvLevelAppMetrics{} - err := impl.dbConnection.Model(envAppLevelMetrics).Where("env_level_app_metrics.app_id = ? ", appId).Where("env_level_app_metrics.env_id = ? ", envId).Select() + err := impl.dbConnection.Model(envAppLevelMetrics).Where("env_level_app_metrics.app_id = ? ", appId). + Where("env_level_app_metrics.env_id = ? ", envId).Select() return envAppLevelMetrics, err } func (impl *EnvLevelAppMetricsRepositoryImpl) FindByAppId(appId int) ([]*EnvLevelAppMetrics, error) { diff --git a/pkg/deployment/manifest/deploymentTemplate/DeploymentTemplateService.go b/pkg/deployment/manifest/deploymentTemplate/DeploymentTemplateService.go new file mode 100644 index 00000000000..2c43ce535ac --- /dev/null +++ b/pkg/deployment/manifest/deploymentTemplate/DeploymentTemplateService.go @@ -0,0 +1,16 @@ +package deploymentTemplate + +import "go.uber.org/zap" + +type DeploymentTemplateService interface { +} + +type DeploymentTemplateServiceImpl struct { + logger *zap.SugaredLogger +} + +func NewDeploymentTemplateServiceImpl(logger *zap.SugaredLogger) *DeploymentTemplateServiceImpl { + return &DeploymentTemplateServiceImpl{ + logger: logger, + } +} diff --git a/pkg/deployment/manifest/deploymentTemplate/DeploymentTemplateValidationService.go b/pkg/deployment/manifest/deploymentTemplate/DeploymentTemplateValidationService.go new file mode 100644 index 00000000000..8c0bf25b062 --- /dev/null +++ b/pkg/deployment/manifest/deploymentTemplate/DeploymentTemplateValidationService.go @@ -0,0 +1,127 @@ +package deploymentTemplate + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/bean" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/chartRef" + "github.com/devtron-labs/devtron/pkg/resourceQualifiers" + "github.com/devtron-labs/devtron/pkg/variables" + "github.com/devtron-labs/devtron/pkg/variables/parsers" + util2 "github.com/devtron-labs/devtron/util" + "github.com/xeipuuv/gojsonschema" + "go.opentelemetry.io/otel" + "go.uber.org/zap" +) + +type DeploymentTemplateValidationService interface { + DeploymentTemplateValidate(ctx context.Context, template interface{}, chartRefId int, scope resourceQualifiers.Scope) (bool, error) + FlaggerCanaryEnabled(values json.RawMessage) (bool, error) +} + +type DeploymentTemplateValidationServiceImpl struct { + logger *zap.SugaredLogger + chartRefService chartRef.ChartRefService + scopedVariableManager variables.ScopedVariableManager +} + +func NewDeploymentTemplateValidationServiceImpl(logger *zap.SugaredLogger, + chartRefService chartRef.ChartRefService, + scopedVariableManager variables.ScopedVariableManager) *DeploymentTemplateValidationServiceImpl { + return &DeploymentTemplateValidationServiceImpl{ + logger: logger, + chartRefService: chartRefService, + scopedVariableManager: scopedVariableManager, + } +} + +func (impl *DeploymentTemplateValidationServiceImpl) DeploymentTemplateValidate(ctx context.Context, template interface{}, chartRefId int, scope resourceQualifiers.Scope) (bool, error) { + _, span := otel.Tracer("orchestrator").Start(ctx, "JsonSchemaExtractFromFile") + schemajson, version, err := impl.chartRefService.JsonSchemaExtractFromFile(chartRefId) + span.End() + if err != nil { + impl.logger.Errorw("Json Schema not found err, FindJsonSchema", "err", err) + return true, nil + } + + templateBytes := template.(json.RawMessage) + templatejsonstring, _, err := impl.scopedVariableManager.ExtractVariablesAndResolveTemplate(scope, string(templateBytes), parsers.JsonVariableTemplate, true, false) + if err != nil { + return false, err + } + var templatejson interface{} + err = json.Unmarshal([]byte(templatejsonstring), &templatejson) + if err != nil { + fmt.Println("Error:", err) + return false, err + } + + schemaLoader := gojsonschema.NewGoLoader(schemajson) + documentLoader := gojsonschema.NewGoLoader(templatejson) + marshalTemplatejson, err := json.Marshal(templatejson) + if err != nil { + impl.logger.Errorw("json template marshal err, DeploymentTemplateValidate", "err", err) + return false, err + } + _, span = otel.Tracer("orchestrator").Start(ctx, "gojsonschema.Validate") + result, err := gojsonschema.Validate(schemaLoader, documentLoader) + span.End() + if err != nil { + impl.logger.Errorw("result validate err, DeploymentTemplateValidate", "err", err) + return false, err + } + if result.Valid() { + var dat map[string]interface{} + if err := json.Unmarshal(marshalTemplatejson, &dat); err != nil { + impl.logger.Errorw("json template unmarshal err, DeploymentTemplateValidate", "err", err) + return false, err + } + _, err := util2.CompareLimitsRequests(dat, version) + if err != nil { + impl.logger.Errorw("LimitRequestCompare err, DeploymentTemplateValidate", "err", err) + return false, err + } + _, err = util2.AutoScale(dat) + if err != nil { + impl.logger.Errorw("LimitRequestCompare err, DeploymentTemplateValidate", "err", err) + return false, err + } + return true, nil + } else { + var stringerror string + for _, err := range result.Errors() { + impl.logger.Errorw("result err, DeploymentTemplateValidate", "err", err.Details()) + if err.Details()["format"] == bean.Cpu { + stringerror = stringerror + err.Field() + ": Format should be like " + bean.CpuPattern + "\n" + } else if err.Details()["format"] == bean.Memory { + stringerror = stringerror + err.Field() + ": Format should be like " + bean.MemoryPattern + "\n" + } else { + stringerror = stringerror + err.String() + "\n" + } + } + return false, errors.New(stringerror) + } +} + +func (impl *DeploymentTemplateValidationServiceImpl) FlaggerCanaryEnabled(values json.RawMessage) (bool, error) { + var jsonMap map[string]json.RawMessage + if err := json.Unmarshal(values, &jsonMap); err != nil { + return false, err + } + + flaggerCanary, found := jsonMap[bean.FlaggerCanary] + if !found { + return false, nil + } + var flaggerCanaryUnmarshalled map[string]json.RawMessage + if err := json.Unmarshal(flaggerCanary, &flaggerCanaryUnmarshalled); err != nil { + return false, err + } + enabled, found := flaggerCanaryUnmarshalled[bean.EnabledFlag] + if !found { + return true, fmt.Errorf("flagger canary enabled field must be set and be equal to false") + } + return string(enabled) == bean.TrueFlag, nil +} diff --git a/pkg/deployment/manifest/deploymentTemplate/adapter/adapter.go b/pkg/deployment/manifest/deploymentTemplate/adapter/adapter.go new file mode 100644 index 00000000000..b8e8da3083f --- /dev/null +++ b/pkg/deployment/manifest/deploymentTemplate/adapter/adapter.go @@ -0,0 +1 @@ +package adapter diff --git a/pkg/deployment/manifest/deploymentTemplate/bean/bean.go b/pkg/deployment/manifest/deploymentTemplate/bean/bean.go new file mode 100644 index 00000000000..78671118fcc --- /dev/null +++ b/pkg/deployment/manifest/deploymentTemplate/bean/bean.go @@ -0,0 +1,11 @@ +package bean + +const ( + MemoryPattern = `"1000Mi" or "1Gi"` + CpuPattern = `"50m" or "0.05"` + Cpu = "cpu" + Memory = "memory" + FlaggerCanary = "flaggerCanary" + EnabledFlag = "enabled" + TrueFlag = "true" +) diff --git a/pkg/chart/ChartCompatibility.go b/pkg/deployment/manifest/deploymentTemplate/chartRef/ChartCompatibility.go similarity index 67% rename from pkg/chart/ChartCompatibility.go rename to pkg/deployment/manifest/deploymentTemplate/chartRef/ChartCompatibility.go index 4c1fb3cd71e..cee6fcfff91 100644 --- a/pkg/chart/ChartCompatibility.go +++ b/pkg/deployment/manifest/deploymentTemplate/chartRef/ChartCompatibility.go @@ -1,16 +1,12 @@ -package chart +package chartRef -type stringSet map[string]struct{} +import "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/chartRef/bean" -const ( - DeploymentChartType = "Deployment" - RolloutChartType = "Rollout Deployment" - ReferenceChart = "reference-chart" -) +type stringSet map[string]struct{} var chartCompatibilityMatrix = map[string]stringSet{ - DeploymentChartType: {RolloutChartType: {}, DeploymentChartType: {}}, - RolloutChartType: {DeploymentChartType: {}, RolloutChartType: {}}, + bean.DeploymentChartType: {bean.RolloutChartType: {}, bean.DeploymentChartType: {}}, + bean.RolloutChartType: {bean.DeploymentChartType: {}, bean.RolloutChartType: {}}, } func CheckCompatibility(oldChartType, newChartType string) bool { diff --git a/pkg/deployment/manifest/deploymentTemplate/chartRef/ChartRefService.go b/pkg/deployment/manifest/deploymentTemplate/chartRef/ChartRefService.go new file mode 100644 index 00000000000..9db0e2ade5f --- /dev/null +++ b/pkg/deployment/manifest/deploymentTemplate/chartRef/ChartRefService.go @@ -0,0 +1,627 @@ +package chartRef + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "github.com/devtron-labs/devtron/internal/constants" + "github.com/devtron-labs/devtron/internal/util" + chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/chartRef/adapter" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/chartRef/bean" + util2 "github.com/devtron-labs/devtron/util" + dirCopy "github.com/otiai10/copy" + "go.uber.org/zap" + "io/ioutil" + "k8s.io/helm/pkg/chartutil" + "os" + "path" + "path/filepath" + "sigs.k8s.io/yaml" + "strconv" + "strings" +) + +type ChartRefService interface { + ChartRefDbReadService + CustomChartService + ChartRefFileOpService +} + +type ChartRefDbReadService interface { + GetDefault() (*bean.ChartRefDto, error) + GetAll() ([]*bean.ChartRefDto, error) + GetAllChartMetadata() (map[string]bean.ChartRefMetaData, error) + FindById(chartRefId int) (*bean.ChartRefDto, error) + FindByVersionAndName(version, name string) (*bean.ChartRefDto, error) + FetchInfoOfChartConfiguredInApp(appId int) (*bean.ChartRefDto, error) + ChartRefAutocomplete() ([]*bean.ChartRefAutocompleteDto, error) + CheckChartExists(chartRefId int) error + ChartRefIdsCompatible(oldChartRefId int, newChartRefId int) (bool, string, string) +} + +type CustomChartService interface { + SaveCustomChart(req *bean.CustomChartRefDto) error + FetchCustomChartsInfo() ([]*bean.ChartDto, error) + ValidateCustomChartUploadedFileFormat(fileName string) error +} + +type ChartRefFileOpService interface { + GetAppOverrideForDefaultTemplate(chartRefId int) (map[string]interface{}, string, error) + JsonSchemaExtractFromFile(chartRefId int) (map[string]interface{}, string, error) + GetSchemaAndReadmeForTemplateByChartRefId(chartRefId int) ([]byte, []byte, error) + GetRefChart(chartRefId int) (string, string, string, string, error) + ExtractChartIfMissing(chartData []byte, refChartDir string, location string) (*bean.ChartDataInfo, error) + GetChartInBytes(chartRefId int) ([]byte, error) +} + +type ChartRefServiceImpl struct { + logger *zap.SugaredLogger + chartRefRepository chartRepoRepository.ChartRefRepository + chartTemplateService util.ChartTemplateService + mergeUtil util.MergeUtil +} + +func NewChartRefServiceImpl(logger *zap.SugaredLogger, + chartRefRepository chartRepoRepository.ChartRefRepository, + chartTemplateService util.ChartTemplateService, + mergeUtil util.MergeUtil) *ChartRefServiceImpl { + // cache devtron reference charts list + devtronChartList, _ := chartRefRepository.FetchAllNonUserUploadedChartInfo() + setReservedChartList(devtronChartList) + return &ChartRefServiceImpl{ + logger: logger, + chartRefRepository: chartRefRepository, + chartTemplateService: chartTemplateService, + mergeUtil: mergeUtil, + } +} + +func (impl *ChartRefServiceImpl) ValidateCustomChartUploadedFileFormat(fileName string) error { + if !strings.HasSuffix(fileName, ".tgz") { + return errors.New("unsupported format") + } + return nil +} + +func (impl *ChartRefServiceImpl) GetDefault() (*bean.ChartRefDto, error) { + chartRef, err := impl.chartRefRepository.GetDefault() + if err != nil { + impl.logger.Errorw("error in getting default chartRef", "err", err) + return nil, err + } + return adapter.ConvertChartRefDbObjToBean(chartRef), nil +} + +func (impl *ChartRefServiceImpl) GetAll() ([]*bean.ChartRefDto, error) { + chartRefs, err := impl.chartRefRepository.GetAll() + if err != nil { + impl.logger.Errorw("error in getting all chartRefs", "err", err) + return nil, err + } + chartRefDtos := make([]*bean.ChartRefDto, 0, len(chartRefs)) + for _, chartRef := range chartRefs { + chartRefDtos = append(chartRefDtos, adapter.ConvertChartRefDbObjToBean(chartRef)) + } + return chartRefDtos, nil +} + +func (impl *ChartRefServiceImpl) GetAllChartMetadata() (map[string]bean.ChartRefMetaData, error) { + chartRefMetadatas, err := impl.chartRefRepository.GetAllChartMetadata() + if err != nil { + impl.logger.Errorw("error in getting all chart metadatas", "err", err) + return nil, err + } + chartsMetadataMap := make(map[string]bean.ChartRefMetaData, len(chartRefMetadatas)) + for _, chartRefMetadata := range chartRefMetadatas { + metadataDto := bean.ChartRefMetaData{ + ChartDescription: chartRefMetadata.ChartDescription, + } + chartsMetadataMap[chartRefMetadata.ChartName] = metadataDto + } + return chartsMetadataMap, nil +} + +func (impl *ChartRefServiceImpl) ChartRefIdsCompatible(oldChartRefId int, newChartRefId int) (bool, string, string) { + oldChart, err := impl.FindById(oldChartRefId) + if err != nil { + return false, "", "" + } + newChart, err := impl.FindById(newChartRefId) + if err != nil { + return false, "", "" + } + return CheckCompatibility(oldChart.Name, newChart.Name), oldChart.Name, newChart.Name +} + +func (impl *ChartRefServiceImpl) FindById(chartRefId int) (*bean.ChartRefDto, error) { + chartRef, err := impl.chartRefRepository.FindById(chartRefId) + if err != nil { + impl.logger.Errorw("error in getting chartRef by id", "err", err, "chartRefId", chartRefId) + return nil, err + } + return adapter.ConvertChartRefDbObjToBean(chartRef), nil +} + +func (impl *ChartRefServiceImpl) FindByVersionAndName(version, name string) (*bean.ChartRefDto, error) { + chartRef, err := impl.chartRefRepository.FindByVersionAndName(name, version) + if err != nil { + impl.logger.Errorw("error in getting chartRef by version and name", "err", err, "version", version, "name", name) + return nil, err + } + return adapter.ConvertChartRefDbObjToBean(chartRef), nil +} + +func (impl *ChartRefServiceImpl) FetchInfoOfChartConfiguredInApp(appId int) (*bean.ChartRefDto, error) { + chartRef, err := impl.chartRefRepository.FetchInfoOfChartConfiguredInApp(appId) + if err != nil { + impl.logger.Errorw("error in getting chart info for chart configured in app", "err", err, "appId", appId) + return nil, err + } + return adapter.ConvertChartRefDbObjToBean(chartRef), nil +} + +func (impl *ChartRefServiceImpl) SaveCustomChart(req *bean.CustomChartRefDto) error { + chartRefDbObj := adapter.ConvertCustomChartRefDtoToDbObj(req) + err := impl.chartRefRepository.Save(chartRefDbObj) + if err != nil { + impl.logger.Errorw("error in saving chart ref", "err", err, "chartRef", chartRefDbObj) + return err + } + return nil +} + +func (impl *ChartRefServiceImpl) GetRefChart(chartRefId int) (string, string, string, string, error) { + var template string + var version string + //path of file in chart from where strategy config is to be taken + var pipelineStrategyPath string + if chartRefId > 0 { + chartRef, err := impl.chartRefRepository.FindById(chartRefId) + if err != nil { + chartRef, err = impl.chartRefRepository.GetDefault() + if err != nil { + return "", "", "", "", err + } + } else if chartRef.UserUploaded { + refChartLocation := filepath.Join(bean.RefChartDirPath, chartRef.Location) + if _, err := os.Stat(refChartLocation); os.IsNotExist(err) { + chartInfo, err := impl.ExtractChartIfMissing(chartRef.ChartData, bean.RefChartDirPath, chartRef.Location) + if chartInfo != nil && chartInfo.TemporaryFolder != "" { + err1 := os.RemoveAll(chartInfo.TemporaryFolder) + if err1 != nil { + impl.logger.Errorw("error in deleting temp dir ", "err", err) + } + } + if err != nil { + impl.logger.Errorw("Error regarding uploaded chart", "err", err) + return "", "", "", "", err + } + + } + } + template = chartRef.Location + version = chartRef.Version + pipelineStrategyPath = chartRef.DeploymentStrategyPath + } else { + chartRef, err := impl.chartRefRepository.GetDefault() + if err != nil { + return "", "", "", "", err + } + template = chartRef.Location + version = chartRef.Version + pipelineStrategyPath = chartRef.DeploymentStrategyPath + } + + //TODO VIKI- fetch from chart ref table + chartPath := path.Join(bean.RefChartDirPath, template) + valid, err := chartutil.IsChartDir(chartPath) + if err != nil || !valid { + impl.logger.Errorw("invalid base chart", "dir", chartPath, "err", err) + return "", "", "", "", err + } + return chartPath, template, version, pipelineStrategyPath, nil +} + +func (impl *ChartRefServiceImpl) GetSchemaAndReadmeForTemplateByChartRefId(chartRefId int) ([]byte, []byte, error) { + refChart, _, _, _, err := impl.GetRefChart(chartRefId) + if err != nil { + impl.logger.Errorw("error in getting refChart", "err", err, "chartRefId", chartRefId) + return nil, nil, err + } + var schemaByte []byte + var readmeByte []byte + err = impl.CheckChartExists(chartRefId) + if err != nil { + impl.logger.Errorw("error in getting refChart", "err", err, "chartRefId", chartRefId) + return nil, nil, err + } + schemaByte, err = ioutil.ReadFile(filepath.Clean(filepath.Join(refChart, "schema.json"))) + if err != nil { + impl.logger.Errorw("error in reading schema.json file for refChart", "err", err, "chartRefId", chartRefId) + } + readmeByte, err = ioutil.ReadFile(filepath.Clean(filepath.Join(refChart, "README.md"))) + if err != nil { + impl.logger.Errorw("error in reading readme file for refChart", "err", err, "chartRefId", chartRefId) + } + return schemaByte, readmeByte, nil +} + +func (impl *ChartRefServiceImpl) ChartRefAutocomplete() ([]*bean.ChartRefAutocompleteDto, error) { + var chartRefs []*bean.ChartRefAutocompleteDto + results, err := impl.chartRefRepository.GetAll() + if err != nil { + impl.logger.Errorw("error in fetching chart config", "err", err) + return chartRefs, err + } + + for _, result := range results { + chartRefs = append(chartRefs, &bean.ChartRefAutocompleteDto{ + Id: result.Id, + Version: result.Version, + Description: result.ChartDescription, + UserUploaded: result.UserUploaded, + IsAppMetricsSupported: result.IsAppMetricsSupported, + }) + } + + return chartRefs, nil +} + +func (impl *ChartRefServiceImpl) GetChartInBytes(chartRefId int) ([]byte, error) { + chartRef, err := impl.chartRefRepository.FindById(chartRefId) + if err != nil { + impl.logger.Errorw("error getting chart data", "chartRefId", chartRefId, "err", err) + return nil, err + } + // For user uploaded charts ChartData will be retrieved from DB + if chartRef.ChartData != nil { + return chartRef.ChartData, nil + } + // For Devtron reference charts the chart will be load from the directory location + refChartPath := filepath.Join(bean.RefChartDirPath, chartRef.Location) + manifestByteArr, err := impl.chartTemplateService.LoadChartInBytes(refChartPath, false) + if err != nil { + impl.logger.Errorw("error in converting chart to bytes", "err", err) + return nil, err + } + return manifestByteArr, nil +} + +func (impl *ChartRefServiceImpl) FetchCustomChartsInfo() ([]*bean.ChartDto, error) { + resultsMetadata, err := impl.chartRefRepository.GetAllChartMetadata() + if err != nil { + impl.logger.Errorw("error in fetching chart metadata", "err", err) + return nil, err + } + chartsMetadata := make(map[string]string) + for _, resultMetadata := range resultsMetadata { + chartsMetadata[resultMetadata.ChartName] = resultMetadata.ChartDescription + } + repo, err := impl.chartRefRepository.GetAll() + if err != nil { + return nil, err + } + var chartDtos []*bean.ChartDto + for _, ref := range repo { + if len(ref.Name) == 0 { + ref.Name = bean.RolloutChartType + } + if description, ok := chartsMetadata[ref.Name]; ref.ChartDescription == "" && ok { + ref.ChartDescription = description + } + chartDto := &bean.ChartDto{ + Id: ref.Id, + Name: ref.Name, + ChartDescription: ref.ChartDescription, + Version: ref.Version, + IsUserUploaded: ref.UserUploaded, + } + chartDtos = append(chartDtos, chartDto) + } + return chartDtos, err +} + +func (impl *ChartRefServiceImpl) CheckChartExists(chartRefId int) error { + chartRefValue, err := impl.chartRefRepository.FindById(chartRefId) + if err != nil { + impl.logger.Errorw("error in finding ref chart by id", "err", err) + return err + } + refChartLocation := filepath.Join(bean.RefChartDirPath, chartRefValue.Location) + if _, err := os.Stat(refChartLocation); os.IsNotExist(err) { + chartInfo, err := impl.ExtractChartIfMissing(chartRefValue.ChartData, bean.RefChartDirPath, chartRefValue.Location) + if chartInfo != nil && chartInfo.TemporaryFolder != "" { + err1 := os.RemoveAll(chartInfo.TemporaryFolder) + if err1 != nil { + impl.logger.Errorw("error in deleting temp dir ", "err", err) + } + } + return err + } + return nil +} +func (impl *ChartRefServiceImpl) GetAppOverrideForDefaultTemplate(chartRefId int) (map[string]interface{}, string, error) { + err := impl.CheckChartExists(chartRefId) + if err != nil { + impl.logger.Errorw("error in getting missing chart for chartRefId", "err", err, "chartRefId") + return nil, "", err + } + + refChart, _, _, _, err := impl.GetRefChart(chartRefId) + if err != nil { + return nil, "", err + } + var appOverrideByte, envOverrideByte []byte + appOverrideByte, err = ioutil.ReadFile(filepath.Clean(filepath.Join(refChart, "app-values.yaml"))) + if err != nil { + impl.logger.Infow("App values yaml file is missing") + } else { + appOverrideByte, err = yaml.YAMLToJSON(appOverrideByte) + if err != nil { + return nil, "", err + } + } + + envOverrideByte, err = ioutil.ReadFile(filepath.Clean(filepath.Join(refChart, "env-values.yaml"))) + if err != nil { + impl.logger.Infow("Env values yaml file is missing") + } else { + envOverrideByte, err = yaml.YAMLToJSON(envOverrideByte) + if err != nil { + return nil, "", err + } + } + + messages := make(map[string]interface{}) + var merged []byte + if appOverrideByte == nil && envOverrideByte == nil { + return messages, "", nil + } else if appOverrideByte == nil || envOverrideByte == nil { + if appOverrideByte == nil { + merged = envOverrideByte + } else { + merged = appOverrideByte + } + } else { + merged, err = impl.mergeUtil.JsonPatch(appOverrideByte, []byte(envOverrideByte)) + if err != nil { + return nil, "", err + } + } + + appOverride := json.RawMessage(merged) + messages["defaultAppOverride"] = appOverride + return messages, string(merged), nil +} + +func (impl *ChartRefServiceImpl) JsonSchemaExtractFromFile(chartRefId int) (map[string]interface{}, string, error) { + err := impl.CheckChartExists(chartRefId) + if err != nil { + impl.logger.Errorw("refChartDir Not Found", "err", err) + return nil, "", err + } + + refChartDir, _, version, _, err := impl.GetRefChart(chartRefId) + if err != nil { + impl.logger.Errorw("refChartDir Not Found err, JsonSchemaExtractFromFile", err) + return nil, "", err + } + fileStatus := filepath.Join(refChartDir, "schema.json") + if _, err := os.Stat(fileStatus); os.IsNotExist(err) { + impl.logger.Errorw("Schema File Not Found err, JsonSchemaExtractFromFile", err) + return nil, "", err + } else { + jsonFile, err := os.Open(fileStatus) + if err != nil { + impl.logger.Errorw("jsonfile open err, JsonSchemaExtractFromFile", "err", err) + return nil, "", err + } + byteValueJsonFile, err := ioutil.ReadAll(jsonFile) + if err != nil { + impl.logger.Errorw("byteValueJsonFile read err, JsonSchemaExtractFromFile", "err", err) + return nil, "", err + } + + var schemajson map[string]interface{} + err = json.Unmarshal([]byte(byteValueJsonFile), &schemajson) + if err != nil { + impl.logger.Errorw("Unmarshal err in byteValueJsonFile, DeploymentTemplateValidate", "err", err) + return nil, "", err + } + return schemajson, version, nil + } +} + +func (impl *ChartRefServiceImpl) ExtractChartIfMissing(chartData []byte, refChartDir string, location string) (*bean.ChartDataInfo, error) { + binaryDataReader := bytes.NewReader(chartData) + dir := impl.chartTemplateService.GetDir() + chartInfo := &bean.ChartDataInfo{} + temporaryChartWorkingDir := filepath.Clean(filepath.Join(refChartDir, dir)) + err := os.MkdirAll(temporaryChartWorkingDir, os.ModePerm) + if err != nil { + impl.logger.Errorw("error in creating directory, CallbackConfigMap", "err", err) + return chartInfo, err + } + chartInfo.TemporaryFolder = temporaryChartWorkingDir + err = util2.ExtractTarGz(binaryDataReader, temporaryChartWorkingDir) + if err != nil { + impl.logger.Errorw("error in extracting binary data of charts", "err", err) + return chartInfo, err + } + + var chartLocation string + var chartName string + var chartVersion string + var fileName string + + files, err := ioutil.ReadDir(temporaryChartWorkingDir) + if err != nil { + impl.logger.Errorw("error in reading err dir", "err", err) + return chartInfo, err + } + + fileName = files[0].Name() + if strings.HasPrefix(files[0].Name(), ".") { + fileName = files[1].Name() + } + + currentChartWorkingDir := filepath.Clean(filepath.Join(temporaryChartWorkingDir, fileName)) + + if location == "" { + chartYaml, err := impl.readChartMetaDataForLocation(temporaryChartWorkingDir, fileName) + var errorList error + if err != nil { + impl.logger.Errorw("Chart yaml file or content not found") + errorList = err + } + + err = util2.CheckForMissingFiles(currentChartWorkingDir) + if err != nil { + impl.logger.Errorw("Missing files in the folder", "err", err) + if errorList != nil { + errorList = errors.New(errorList.Error() + "; " + err.Error()) + } else { + errorList = err + } + + } + + if errorList != nil { + return chartInfo, errorList + } + + chartName = chartYaml.Name + chartVersion = chartYaml.Version + chartInfo.Description = chartYaml.Description + chartLocation = impl.getLocationFromChartNameAndVersion(chartName, chartVersion) + location = chartLocation + + // Validate: chart name shouldn't conflict with Devtron charts (no user uploaded chart names should contain any devtron chart names as the prefix) + isReservedChart, _ := impl.validateReservedChartName(chartName) + if isReservedChart { + impl.logger.Errorw("request err, chart name is reserved by Devtron") + err = &util.ApiError{ + Code: constants.ChartNameAlreadyReserved, + InternalMessage: bean.ChartNameReservedInternalError, + UserMessage: fmt.Sprintf("The name '%s' is reserved for a chart provided by Devtron", chartName), + } + return chartInfo, err + } + + // Validate: chart location should be unique + exists, err := impl.chartRefRepository.CheckIfDataExists(location) + if err != nil { + impl.logger.Errorw("Error in searching the database") + return chartInfo, err + } + if exists { + impl.logger.Errorw("request err, chart name and version exists already in the database") + err = &util.ApiError{ + Code: constants.ChartCreatedAlreadyExists, + InternalMessage: bean.ChartAlreadyExistsInternalError, + UserMessage: fmt.Sprintf("%s of %s exists already in the database", chartVersion, chartName), + } + return chartInfo, err + } + + //User Info Message: uploading new version of the existing chart name + existingChart, err := impl.chartRefRepository.FetchChart(chartName) + if err == nil && existingChart != nil { + chartInfo.Message = "New Version detected for " + existingChart[0].Name + } + + } else { + err = dirCopy.Copy(currentChartWorkingDir, filepath.Clean(filepath.Join(refChartDir, location))) + if err != nil { + impl.logger.Errorw("error in copying chart from temp dir to ref chart dir", "err", err) + return chartInfo, err + } + } + + chartInfo.ChartLocation = location + chartInfo.ChartName = chartName + chartInfo.ChartVersion = chartVersion + return chartInfo, nil +} + +func (impl *ChartRefServiceImpl) readChartMetaDataForLocation(chartDir string, fileName string) (*bean.ChartYamlStruct, error) { + chartLocation := filepath.Clean(filepath.Join(chartDir, fileName)) + + chartYamlPath := filepath.Clean(filepath.Join(chartLocation, "Chart.yaml")) + if _, err := os.Stat(chartYamlPath); os.IsNotExist(err) { + return nil, fmt.Errorf("Chart.yaml file not present in the directory") + } + + data, err := ioutil.ReadFile(chartYamlPath) + if err != nil { + impl.logger.Errorw("failed reading data from file", "err", err) + return nil, err + } + //println(data) + var chartYaml bean.ChartYamlStruct + err = yaml.Unmarshal(data, &chartYaml) + if err != nil { + impl.logger.Errorw("Unmarshal error of yaml file", "err", err) + return nil, err + } + if chartYaml.Name == "" || chartYaml.Version == "" { + impl.logger.Errorw("Missing values in yaml file either name or version", "err", err) + return nil, errors.New("Missing values in yaml file either name or version") + } + ver := strings.Split(chartYaml.Version, ".") + if len(ver) == 3 { + for _, verObject := range ver { + if _, err := strconv.ParseInt(verObject, 10, 64); err != nil { + return nil, errors.New("Version should contain integers (Ex: 1.1.0)") + } + } + return &chartYaml, nil + } + return nil, errors.New("Version should be of length 3 integers with dot seperated (Ex: 1.1.0)") +} + +func (impl *ChartRefServiceImpl) validateReservedChartName(chartName string) (isReservedChart bool, err error) { + formattedChartName := impl.formatChartName(chartName) + for _, reservedChart := range *bean.ReservedChartRefNamesList { + isReservedChart = (reservedChart.LocationPrefix != "" && strings.HasPrefix(formattedChartName, reservedChart.LocationPrefix)) || + (reservedChart.Name != "" && strings.HasPrefix(strings.ToLower(chartName), reservedChart.Name)) + if isReservedChart { + return true, nil + } + } + return false, nil +} + +func (impl *ChartRefServiceImpl) getLocationFromChartNameAndVersion(chartName string, chartVersion string) string { + var chartLocation string + chartname := impl.formatChartName(chartName) + chartversion := strings.ReplaceAll(chartVersion, ".", "-") + if !strings.Contains(chartname, chartversion) { + chartLocation = chartname + "_" + chartversion + } else { + chartLocation = chartname + } + return chartLocation +} + +func (impl *ChartRefServiceImpl) formatChartName(chartName string) string { + chartname := strings.ReplaceAll(chartName, ".", "-") + chartname = strings.ReplaceAll(chartname, " ", "_") + return chartname +} + +func setReservedChartList(devtronChartList []*chartRepoRepository.ChartRef) { + reservedChartRefNamesList := []bean.ReservedChartList{ + {Name: strings.ToLower(bean.RolloutChartType), LocationPrefix: ""}, + {Name: "", LocationPrefix: bean.ReferenceChart}, + } + for _, devtronChart := range devtronChartList { + reservedChartRefNamesList = append(reservedChartRefNamesList, bean.ReservedChartList{ + Name: strings.ToLower(devtronChart.Name), + LocationPrefix: strings.Split(devtronChart.Location, "_")[0], + }) + } + bean.ReservedChartRefNamesList = &reservedChartRefNamesList +} diff --git a/pkg/deployment/manifest/deploymentTemplate/chartRef/adapter/adapter.go b/pkg/deployment/manifest/deploymentTemplate/chartRef/adapter/adapter.go new file mode 100644 index 00000000000..6e2ec31658e --- /dev/null +++ b/pkg/deployment/manifest/deploymentTemplate/chartRef/adapter/adapter.go @@ -0,0 +1,45 @@ +package adapter + +import ( + chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/chartRef/bean" +) + +func ConvertChartRefDbObjToBean(ref *chartRepoRepository.ChartRef) *bean.ChartRefDto { + dto := &bean.ChartRefDto{ + Id: ref.Id, + Location: ref.Location, + Version: ref.Version, + Default: ref.Default, + ChartData: ref.ChartData, + ChartDescription: ref.ChartDescription, + UserUploaded: ref.UserUploaded, + IsAppMetricsSupported: ref.IsAppMetricsSupported, + DeploymentStrategyPath: ref.DeploymentStrategyPath, + JsonPathForStrategy: ref.JsonPathForStrategy, + } + if len(ref.Name) == 0 { + dto.Name = bean.RolloutChartType + } else { + dto.Name = ref.Name + } + return dto +} + +func ConvertCustomChartRefDtoToDbObj(ref *bean.CustomChartRefDto) *chartRepoRepository.ChartRef { + return &chartRepoRepository.ChartRef{ + Id: ref.Id, + Location: ref.Location, + Version: ref.Version, + Active: ref.Active, + Default: ref.Default, + Name: ref.Name, + ChartData: ref.ChartData, + ChartDescription: ref.ChartDescription, + UserUploaded: ref.UserUploaded, + IsAppMetricsSupported: ref.IsAppMetricsSupported, + DeploymentStrategyPath: ref.DeploymentStrategyPath, + JsonPathForStrategy: ref.JsonPathForStrategy, + AuditLog: ref.AuditLog, + } +} diff --git a/pkg/deployment/manifest/deploymentTemplate/chartRef/bean/bean.go b/pkg/deployment/manifest/deploymentTemplate/chartRef/bean/bean.go new file mode 100644 index 00000000000..0a2428435e5 --- /dev/null +++ b/pkg/deployment/manifest/deploymentTemplate/chartRef/bean/bean.go @@ -0,0 +1,96 @@ +package bean + +import "github.com/devtron-labs/devtron/pkg/sql" + +const ( + DeploymentChartType = "Deployment" + RolloutChartType = "Rollout Deployment" + ReferenceChart = "reference-chart" + RefChartDirPath = "scripts/devtron-reference-helm-charts" + ChartAlreadyExistsInternalError = "Chart exists already, try uploading another chart" + ChartNameReservedInternalError = "Change the name of the chart and try uploading again" +) + +type ChartDataInfo struct { + ChartLocation string `json:"chartLocation"` + ChartName string `json:"chartName"` + ChartVersion string `json:"chartVersion"` + TemporaryFolder string `json:"temporaryFolder"` + Description string `json:"description"` + Message string `json:"message"` +} + +type ChartYamlStruct struct { + Name string `yaml:"name"` + Version string `yaml:"version"` + Description string `yaml:"description"` +} + +var ReservedChartRefNamesList *[]ReservedChartList + +type ReservedChartList struct { + LocationPrefix string + Name string +} + +type ChartRefDto struct { + Id int `json:"id"` + Location string `json:"location"` + Version string `json:"version"` + Default bool `json:"isDefault"` + Name string `json:"name"` + ChartData []byte `json:"chartData"` + ChartDescription string `json:"chartDescription"` + UserUploaded bool `json:"userUploaded,notnull"` + IsAppMetricsSupported bool `json:"isAppMetricsSupported"` + DeploymentStrategyPath string `json:"deploymentStrategyPath"` + JsonPathForStrategy string `json:"jsonPathForStrategy"` +} + +// TODO: below objects are created/moved while refactoring to remove db object usage, to remove/replace them with the common objects mentioned above + +type CustomChartRefDto struct { + Id int `sql:"id,pk"` + Location string `sql:"location"` + Version string `sql:"version"` + Active bool `sql:"active,notnull"` + Default bool `sql:"is_default,notnull"` + Name string `sql:"name"` + ChartData []byte `sql:"chart_data"` + ChartDescription string `sql:"chart_description"` + UserUploaded bool `sql:"user_uploaded,notnull"` + IsAppMetricsSupported bool `sql:"is_app_metrics_supported,notnull"` + DeploymentStrategyPath string `sql:"deployment_strategy_path"` + JsonPathForStrategy string `sql:"json_path_for_strategy"` + sql.AuditLog +} + +type ChartRefAutocompleteDto struct { + Id int `json:"id"` + Version string `json:"version"` + Name string `json:"name"` + Description string `json:"description"` + UserUploaded bool `json:"userUploaded"` + IsAppMetricsSupported bool `json:"isAppMetricsSupported"` +} + +type ChartRefMetaData struct { + ChartDescription string `json:"chartDescription"` +} + +type ChartRefAutocompleteResponse struct { + ChartRefs []ChartRefAutocompleteDto `json:"chartRefs"` + LatestChartRef int `json:"latestChartRef"` + LatestAppChartRef int `json:"latestAppChartRef"` + LatestEnvChartRef int `json:"latestEnvChartRef,omitempty"` + ChartsMetadata map[string]ChartRefMetaData `json:"chartMetadata"` // chartName vs Metadata + CompatibleChartTypes []string `json:"compatibleChartTypes,omitempty"` +} + +type ChartDto struct { + Id int `json:"id"` + Name string `json:"name"` + ChartDescription string `json:"chartDescription"` + Version string `json:"version"` + IsUserUploaded bool `json:"isUserUploaded"` +} diff --git a/pkg/deployment/manifest/wire_deployment_manifest.go b/pkg/deployment/manifest/wire_deployment_manifest.go new file mode 100644 index 00000000000..425fbbd19c7 --- /dev/null +++ b/pkg/deployment/manifest/wire_deployment_manifest.go @@ -0,0 +1,25 @@ +package manifest + +import ( + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deployedAppMetrics" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deployedAppMetrics/repository" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/chartRef" + "github.com/google/wire" +) + +var DeploymentManifestWireSet = wire.NewSet( + repository.NewAppLevelMetricsRepositoryImpl, + wire.Bind(new(repository.AppLevelMetricsRepository), new(*repository.AppLevelMetricsRepositoryImpl)), + repository.NewEnvLevelAppMetricsRepositoryImpl, + wire.Bind(new(repository.EnvLevelAppMetricsRepository), new(*repository.EnvLevelAppMetricsRepositoryImpl)), + + deployedAppMetrics.NewDeployedAppMetricsServiceImpl, + wire.Bind(new(deployedAppMetrics.DeployedAppMetricsService), new(*deployedAppMetrics.DeployedAppMetricsServiceImpl)), + deploymentTemplate.NewDeploymentTemplateServiceImpl, + wire.Bind(new(deploymentTemplate.DeploymentTemplateService), new(*deploymentTemplate.DeploymentTemplateServiceImpl)), + deploymentTemplate.NewDeploymentTemplateValidationServiceImpl, + wire.Bind(new(deploymentTemplate.DeploymentTemplateValidationService), new(*deploymentTemplate.DeploymentTemplateValidationServiceImpl)), + chartRef.NewChartRefServiceImpl, + wire.Bind(new(chartRef.ChartRefService), new(*chartRef.ChartRefServiceImpl)), +) diff --git a/pkg/deployment/wire_deployment.go b/pkg/deployment/wire_deployment.go new file mode 100644 index 00000000000..5a959cd701b --- /dev/null +++ b/pkg/deployment/wire_deployment.go @@ -0,0 +1,14 @@ +package deployment + +import ( + "github.com/devtron-labs/devtron/pkg/deployment/gitOps" + "github.com/devtron-labs/devtron/pkg/deployment/manifest" + "github.com/google/wire" +) + +// TODO: add separate wire sets for full and ea mode when reached that level of transparency + +var DeploymentWireSet = wire.NewSet( + gitOps.GitOpsWireSet, + manifest.DeploymentManifestWireSet, +) diff --git a/pkg/generateManifest/DeployementTemplateService.go b/pkg/generateManifest/DeployementTemplateService.go index 30deb77eb6c..82b8a909a8e 100644 --- a/pkg/generateManifest/DeployementTemplateService.go +++ b/pkg/generateManifest/DeployementTemplateService.go @@ -13,6 +13,7 @@ import ( "github.com/devtron-labs/devtron/pkg/chart" chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository" repository3 "github.com/devtron-labs/devtron/pkg/cluster/repository" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/chartRef" "github.com/devtron-labs/devtron/pkg/pipeline" "github.com/devtron-labs/devtron/pkg/pipeline/history" "github.com/devtron-labs/devtron/pkg/resourceQualifiers" @@ -84,6 +85,7 @@ type DeploymentTemplateServiceImpl struct { environmentRepository repository3.EnvironmentRepository appRepository appRepository.AppRepository scopedVariableManager variables.ScopedVariableManager + chartRefService chartRef.ChartRefService } func NewDeploymentTemplateServiceImpl(Logger *zap.SugaredLogger, chartService chart.ChartService, @@ -100,7 +102,7 @@ func NewDeploymentTemplateServiceImpl(Logger *zap.SugaredLogger, chartService ch environmentRepository repository3.EnvironmentRepository, appRepository appRepository.AppRepository, scopedVariableManager variables.ScopedVariableManager, -) *DeploymentTemplateServiceImpl { + chartRefService chartRef.ChartRefService) *DeploymentTemplateServiceImpl { return &DeploymentTemplateServiceImpl{ Logger: Logger, chartService: chartService, @@ -117,6 +119,7 @@ func NewDeploymentTemplateServiceImpl(Logger *zap.SugaredLogger, chartService ch environmentRepository: environmentRepository, appRepository: appRepository, scopedVariableManager: scopedVariableManager, + chartRefService: chartRefService, } } @@ -132,7 +135,7 @@ func (impl DeploymentTemplateServiceImpl) FetchDeploymentsWithChartRefs(appId in for _, item := range defaultVersions.ChartRefs { res := &repository.DeploymentTemplateComparisonMetadata{ - ChartId: item.Id, + ChartRefId: item.Id, ChartVersion: item.Version, ChartType: item.Name, Type: repository.DefaultVersions, @@ -148,7 +151,7 @@ func (impl DeploymentTemplateServiceImpl) FetchDeploymentsWithChartRefs(appId in for _, env := range publishedOnEnvs { item := &repository.DeploymentTemplateComparisonMetadata{ - ChartId: env.ChartRefId, + ChartRefId: env.ChartRefId, EnvironmentId: env.EnvironmentId, EnvironmentName: env.EnvironmentName, Type: repository.PublishedOnEnvironments, @@ -197,7 +200,7 @@ func (impl DeploymentTemplateServiceImpl) GetDeploymentTemplate(ctx context.Cont } else { switch request.Type { case repository.DefaultVersions: - _, values, err = impl.chartService.GetAppOverrideForDefaultTemplate(request.ChartRefId) + _, values, err = impl.chartRefService.GetAppOverrideForDefaultTemplate(request.ChartRefId) resolvedValue = values case repository.PublishedOnEnvironments: values, resolvedValue, variableSnapshot, err = impl.fetchResolvedTemplateForPublishedEnvs(ctx, request) @@ -301,7 +304,7 @@ func (impl DeploymentTemplateServiceImpl) extractScopeData(request DeploymentTem } func (impl DeploymentTemplateServiceImpl) GenerateManifest(ctx context.Context, chartRefId int, valuesYaml string) (*openapi2.TemplateChartResponse, error) { - refChart, template, err, version, _ := impl.chartService.GetRefChart(chart.TemplateRequest{ChartRefId: chartRefId}) + refChart, template, version, _, err := impl.chartRefService.GetRefChart(chartRefId) if err != nil { impl.Logger.Errorw("error in getting refChart", "err", err, "chartRefId", chartRefId) return nil, err diff --git a/pkg/generateManifest/DeployementTemplateService_test.go b/pkg/generateManifest/DeployementTemplateService_test.go index 43bce354d77..d2aac53148f 100644 --- a/pkg/generateManifest/DeployementTemplateService_test.go +++ b/pkg/generateManifest/DeployementTemplateService_test.go @@ -65,7 +65,7 @@ func TestDeploymentTemplateServiceImpl_FetchDeploymentsWithChartRefs(t *testing. deployedOnEnv := []*repository.DeploymentTemplateComparisonMetadata{ { - ChartId: 1, + ChartRefId: 1, ChartVersion: "4.18.1", EnvironmentId: 1, PipelineConfigOverrideId: 5, @@ -74,7 +74,7 @@ func TestDeploymentTemplateServiceImpl_FetchDeploymentsWithChartRefs(t *testing. Status: "Succeeded", }, { - ChartId: 1, + ChartRefId: 1, ChartVersion: "4.18.1", EnvironmentId: 1, PipelineConfigOverrideId: 5, @@ -83,7 +83,7 @@ func TestDeploymentTemplateServiceImpl_FetchDeploymentsWithChartRefs(t *testing. Status: "Succeeded", }, { - ChartId: 1, + ChartRefId: 1, ChartVersion: "4.18.1", EnvironmentId: 1, PipelineConfigOverrideId: 5, @@ -95,7 +95,7 @@ func TestDeploymentTemplateServiceImpl_FetchDeploymentsWithChartRefs(t *testing. deployedOnOtherEnvs := []*repository.DeploymentTemplateComparisonMetadata{ { - ChartId: 1, + ChartRefId: 1, ChartVersion: "4.18.1", EnvironmentId: 2, PipelineConfigOverrideId: 9, @@ -121,7 +121,7 @@ func TestDeploymentTemplateServiceImpl_FetchDeploymentsWithChartRefs(t *testing. }, want: []*repository.DeploymentTemplateComparisonMetadata{ { - ChartId: 1, + ChartRefId: 1, ChartVersion: "v1.0.1", ChartType: "Deployment", EnvironmentId: 0, @@ -133,7 +133,7 @@ func TestDeploymentTemplateServiceImpl_FetchDeploymentsWithChartRefs(t *testing. Type: 1, }, { - ChartId: 2, + ChartRefId: 2, ChartVersion: "v1.0.2", ChartType: "Deployment", EnvironmentId: 0, @@ -144,7 +144,7 @@ func TestDeploymentTemplateServiceImpl_FetchDeploymentsWithChartRefs(t *testing. Status: "", Type: 1, }, { - ChartId: 3, + ChartRefId: 3, ChartVersion: "v1.0.3", ChartType: "Deployment", EnvironmentId: 0, @@ -155,7 +155,7 @@ func TestDeploymentTemplateServiceImpl_FetchDeploymentsWithChartRefs(t *testing. Status: "", Type: 1, }, { - ChartId: 2, + ChartRefId: 2, ChartVersion: "", ChartType: "", EnvironmentId: 1, @@ -166,7 +166,7 @@ func TestDeploymentTemplateServiceImpl_FetchDeploymentsWithChartRefs(t *testing. Status: "", Type: 2, }, { - ChartId: 1, + ChartRefId: 1, ChartVersion: "4.18.1", ChartType: "", EnvironmentId: 1, @@ -177,7 +177,7 @@ func TestDeploymentTemplateServiceImpl_FetchDeploymentsWithChartRefs(t *testing. Status: "Succeeded", Type: 3, }, { - ChartId: 1, + ChartRefId: 1, ChartVersion: "4.18.1", ChartType: "", EnvironmentId: 1, @@ -188,7 +188,7 @@ func TestDeploymentTemplateServiceImpl_FetchDeploymentsWithChartRefs(t *testing. Status: "Succeeded", Type: 3, }, { - ChartId: 1, + ChartRefId: 1, ChartVersion: "4.18.1", ChartType: "", EnvironmentId: 1, @@ -199,7 +199,7 @@ func TestDeploymentTemplateServiceImpl_FetchDeploymentsWithChartRefs(t *testing. Status: "Succeeded", Type: 3, }, { - ChartId: 1, + ChartRefId: 1, ChartVersion: "v1.0.1", ChartType: "Deployment", EnvironmentId: 2, diff --git a/pkg/gitops/GitOpsConfigService.go b/pkg/gitops/GitOpsConfigService.go index 0c8d148a075..5925bf06de8 100644 --- a/pkg/gitops/GitOpsConfigService.go +++ b/pkg/gitops/GitOpsConfigService.go @@ -22,6 +22,9 @@ import ( "encoding/json" "fmt" util4 "github.com/devtron-labs/common-lib/utils/k8s" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config/bean" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git" "math/rand" "net/http" "net/url" @@ -33,7 +36,6 @@ import ( cluster3 "github.com/argoproj/argo-cd/v2/pkg/apiclient/cluster" bean2 "github.com/devtron-labs/devtron/api/bean" - "github.com/devtron-labs/devtron/client/argocdServer" cluster2 "github.com/devtron-labs/devtron/client/argocdServer/cluster" "github.com/devtron-labs/devtron/internal/sql/repository" "github.com/devtron-labs/devtron/internal/util" @@ -59,23 +61,22 @@ type GitOpsConfigService interface { GetGitOpsConfigById(id int) (*bean2.GitOpsConfigDto, error) GetAllGitOpsConfig() ([]*bean2.GitOpsConfigDto, error) GetGitOpsConfigByProvider(provider string) (*bean2.GitOpsConfigDto, error) - GetGitOpsConfigActive() (*bean2.GitOpsConfigDto, error) } const ( - GitOpsSecretName = "devtron-gitops-secret" - DryrunRepoName = "devtron-sample-repo-dryrun-" - DeleteRepoStage = "Delete Repo" - CommitOnRestStage = "Commit On Rest" - PushStage = "Push" - CloneStage = "Clone" - GetRepoUrlStage = "Get Repo RedirectionUrl" - CreateRepoStage = "Create Repo" - CloneHttp = "Clone Http" - CreateReadmeStage = "Create Readme" - GITHUB_PROVIDER = "GITHUB" - GITLAB_PROVIDER = "GITLAB" - BITBUCKET_PROVIDER = "BITBUCKET_CLOUD" + GitOpsSecretName = "devtron-gitops-secret" + DryrunRepoName = "devtron-sample-repo-dryrun-" + DeleteRepoStage = "Delete Repo" + CommitOnRestStage = "Commit On Rest" + PushStage = "Push" + CloneStage = "Clone" + GetRepoUrlStage = "Get Repo RedirectionUrl" + CreateRepoStage = "Create Repo" + CloneHttp = "Clone Http" + CreateReadmeStage = "Create Readme" + GITHUB_PROVIDER = "GITHUB" + GITLAB_PROVIDER = "GITLAB" + AZURE_DEVOPS_PROVIDER = "AZURE_DEVOPS" BITBUCKET_API_HOST = "https://api.bitbucket.org/2.0/" ) @@ -88,40 +89,37 @@ type DetailedErrorGitOpsConfigResponse struct { } type GitOpsConfigServiceImpl struct { - randSource rand.Source - logger *zap.SugaredLogger - globalEnvVariables *util2.GlobalEnvVariables - gitOpsRepository repository.GitOpsConfigRepository - K8sUtil *util4.K8sServiceImpl - aCDAuthConfig *util3.ACDAuthConfig - clusterService cluster.ClusterService - envService cluster.EnvironmentService - versionService argocdServer.VersionService - gitFactory *util.GitFactory - chartTemplateService util.ChartTemplateService - argoUserService argo.ArgoUserService - clusterServiceCD cluster2.ServiceClient + randSource rand.Source + logger *zap.SugaredLogger + globalEnvVariables *util2.GlobalEnvVariables + gitOpsRepository repository.GitOpsConfigRepository + K8sUtil *util4.K8sServiceImpl + aCDAuthConfig *util3.ACDAuthConfig + clusterService cluster.ClusterService + gitFactory *git.GitFactory + argoUserService argo.ArgoUserService + clusterServiceCD cluster2.ServiceClient + gitOpsConfigReadService config.GitOpsConfigReadService } func NewGitOpsConfigServiceImpl(Logger *zap.SugaredLogger, globalEnvVariables *util2.GlobalEnvVariables, gitOpsRepository repository.GitOpsConfigRepository, K8sUtil *util4.K8sServiceImpl, aCDAuthConfig *util3.ACDAuthConfig, - clusterService cluster.ClusterService, envService cluster.EnvironmentService, versionService argocdServer.VersionService, - gitFactory *util.GitFactory, chartTemplateService util.ChartTemplateService, argoUserService argo.ArgoUserService, clusterServiceCD cluster2.ServiceClient) *GitOpsConfigServiceImpl { + clusterService cluster.ClusterService, + gitFactory *git.GitFactory, argoUserService argo.ArgoUserService, + clusterServiceCD cluster2.ServiceClient, gitOpsConfigReadService config.GitOpsConfigReadService) *GitOpsConfigServiceImpl { return &GitOpsConfigServiceImpl{ - randSource: rand.NewSource(time.Now().UnixNano()), - logger: Logger, - globalEnvVariables: globalEnvVariables, - gitOpsRepository: gitOpsRepository, - K8sUtil: K8sUtil, - aCDAuthConfig: aCDAuthConfig, - clusterService: clusterService, - envService: envService, - versionService: versionService, - gitFactory: gitFactory, - chartTemplateService: chartTemplateService, - argoUserService: argoUserService, - clusterServiceCD: clusterServiceCD, + randSource: rand.NewSource(time.Now().UnixNano()), + logger: Logger, + globalEnvVariables: globalEnvVariables, + gitOpsRepository: gitOpsRepository, + K8sUtil: K8sUtil, + aCDAuthConfig: aCDAuthConfig, + clusterService: clusterService, + gitFactory: gitFactory, + argoUserService: argoUserService, + clusterServiceCD: clusterServiceCD, + gitOpsConfigReadService: gitOpsConfigReadService, } } @@ -292,8 +290,8 @@ func (impl *GitOpsConfigServiceImpl) CreateGitOpsConfig(ctx context.Context, req request.Host = fmt.Sprintf(request.Host+"/%s", groupName) } } - if strings.ToUpper(request.Provider) == BITBUCKET_PROVIDER { - request.Host = util.BITBUCKET_CLONE_BASE_URL + request.BitBucketWorkspaceId + if strings.ToUpper(request.Provider) == bean.BITBUCKET_PROVIDER { + request.Host = git.BITBUCKET_CLONE_BASE_URL + request.BitBucketWorkspaceId } operationComplete := false retryCount := 0 @@ -324,7 +322,7 @@ func (impl *GitOpsConfigServiceImpl) CreateGitOpsConfig(ctx context.Context, req } // if git-ops config is created/saved successfully (just before transaction commit) and this was first git-ops config, then upsert clusters in acd - isGitOpsConfigured, err := impl.gitOpsRepository.IsGitOpsConfigured() + isGitOpsConfigured, err := impl.gitOpsConfigReadService.IsGitOpsConfigured() if err != nil { return nil, err } @@ -350,7 +348,7 @@ func (impl *GitOpsConfigServiceImpl) CreateGitOpsConfig(ctx context.Context, req return nil, err } - err = impl.gitFactory.Reload() + err = impl.gitFactory.Reload(impl.gitOpsRepository) if err != nil { return nil, err } @@ -493,8 +491,8 @@ func (impl *GitOpsConfigServiceImpl) UpdateGitOpsConfig(request *bean2.GitOpsCon request.Host = fmt.Sprintf(request.Host+"/%s", groupName) } } - if strings.ToUpper(request.Provider) == BITBUCKET_PROVIDER { - request.Host = util.BITBUCKET_CLONE_BASE_URL + request.BitBucketWorkspaceId + if strings.ToUpper(request.Provider) == bean.BITBUCKET_PROVIDER { + request.Host = git.BITBUCKET_CLONE_BASE_URL + request.BitBucketWorkspaceId } operationComplete := false retryCount := 0 @@ -525,7 +523,7 @@ func (impl *GitOpsConfigServiceImpl) UpdateGitOpsConfig(request *bean2.GitOpsCon if err != nil { return err } - err = impl.gitFactory.Reload() + err = impl.gitFactory.Reload(impl.gitOpsRepository) if err != nil { return err } @@ -666,26 +664,6 @@ type KeyDto struct { Key string `json:"key,omitempty"` } -func (impl *GitOpsConfigServiceImpl) GetGitOpsConfigActive() (*bean2.GitOpsConfigDto, error) { - model, err := impl.gitOpsRepository.GetGitOpsConfigActive() - if err != nil { - impl.logger.Errorw("GetGitOpsConfigActive, error while getting error", "err", err) - return nil, err - } - config := &bean2.GitOpsConfigDto{ - Id: model.Id, - Provider: model.Provider, - GitHubOrgId: model.GitHubOrgId, - GitLabGroupId: model.GitLabGroupId, - Active: model.Active, - UserId: model.CreatedBy, - AzureProjectName: model.AzureProject, - BitBucketWorkspaceId: model.BitBucketWorkspaceId, - BitBucketProjectKey: model.BitBucketProjectKey, - } - return config, err -} - func (impl *GitOpsConfigServiceImpl) GitOpsValidateDryRun(config *bean2.GitOpsConfigDto) DetailedErrorGitOpsConfigResponse { if impl.globalEnvVariables.SkipGitOpsValidation { return DetailedErrorGitOpsConfigResponse{} @@ -702,13 +680,13 @@ func (impl *GitOpsConfigServiceImpl) GitOpsValidateDryRun(config *bean2.GitOpsCo } config.Token = model.Token } - detailedErrorGitOpsConfigActions := util.DetailedErrorGitOpsConfigActions{} + detailedErrorGitOpsConfigActions := git.DetailedErrorGitOpsConfigActions{} detailedErrorGitOpsConfigActions.StageErrorMap = make(map[string]error) /*if strings.ToUpper(config.Provider) == GITHUB_PROVIDER { config.Host = GITHUB_HOST }*/ - if strings.ToUpper(config.Provider) == BITBUCKET_PROVIDER { - config.Host = util.BITBUCKET_CLONE_BASE_URL + if strings.ToUpper(config.Provider) == bean.BITBUCKET_PROVIDER { + config.Host = git.BITBUCKET_CLONE_BASE_URL config.BitBucketProjectKey = strings.ToUpper(config.BitBucketProjectKey) } client, gitService, err := impl.gitFactory.NewClientForValidation(config) @@ -721,7 +699,7 @@ func (impl *GitOpsConfigServiceImpl) GitOpsValidateDryRun(config *bean2.GitOpsCo } appName := DryrunRepoName + util2.Generate(6) //getting user name & emailId for commit author data - userEmailId, userName := impl.chartTemplateService.GetUserEmailIdAndNameForGitOpsCommit(config.UserId) + userEmailId, userName := impl.gitOpsConfigReadService.GetUserEmailIdAndNameForGitOpsCommit(config.UserId) config.UserEmailId = userEmailId config.GitRepoName = appName repoUrl, _, detailedErrorCreateRepo := client.CreateRepository(config) @@ -816,7 +794,7 @@ func (impl *GitOpsConfigServiceImpl) extractErrorMessageByProvider(err error, pr return err } -func (impl *GitOpsConfigServiceImpl) convertDetailedErrorToResponse(detailedErrorGitOpsConfigActions util.DetailedErrorGitOpsConfigActions) (detailedErrorResponse DetailedErrorGitOpsConfigResponse) { +func (impl *GitOpsConfigServiceImpl) convertDetailedErrorToResponse(detailedErrorGitOpsConfigActions git.DetailedErrorGitOpsConfigActions) (detailedErrorResponse DetailedErrorGitOpsConfigResponse) { detailedErrorResponse.StageErrorMap = make(map[string]string) detailedErrorResponse.SuccessfulStages = detailedErrorGitOpsConfigActions.SuccessfulStages for stage, err := range detailedErrorGitOpsConfigActions.StageErrorMap { diff --git a/pkg/pipeline/AppDeploymentTypeChangeManager.go b/pkg/pipeline/AppDeploymentTypeChangeManager.go index 4e12e270927..5f340c755f4 100644 --- a/pkg/pipeline/AppDeploymentTypeChangeManager.go +++ b/pkg/pipeline/AppDeploymentTypeChangeManager.go @@ -29,6 +29,8 @@ import ( "github.com/devtron-labs/devtron/internal/util" app2 "github.com/devtron-labs/devtron/pkg/app" "github.com/devtron-labs/devtron/pkg/bean" + chartService "github.com/devtron-labs/devtron/pkg/chart" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config" "github.com/juju/errors" "go.uber.org/zap" "strconv" @@ -55,17 +57,18 @@ type AppDeploymentTypeChangeManager interface { } type AppDeploymentTypeChangeManagerImpl struct { - logger *zap.SugaredLogger - pipelineRepository pipelineConfig.PipelineRepository - workflowDagExecutor WorkflowDagExecutor - appService app2.AppService - chartTemplateService util.ChartTemplateService - appStatusRepository appStatus.AppStatusRepository - helmAppService client.HelmAppService - application application2.ServiceClient + logger *zap.SugaredLogger + pipelineRepository pipelineConfig.PipelineRepository + workflowDagExecutor WorkflowDagExecutor + appService app2.AppService + appStatusRepository appStatus.AppStatusRepository + helmAppService client.HelmAppService + application application2.ServiceClient appArtifactManager AppArtifactManager cdPipelineConfigService CdPipelineConfigService + gitOpsConfigReadService config.GitOpsConfigReadService + chartService chartService.ChartService } func NewAppDeploymentTypeChangeManagerImpl( @@ -73,23 +76,25 @@ func NewAppDeploymentTypeChangeManagerImpl( pipelineRepository pipelineConfig.PipelineRepository, workflowDagExecutor WorkflowDagExecutor, appService app2.AppService, - chartTemplateService util.ChartTemplateService, appStatusRepository appStatus.AppStatusRepository, helmAppService client.HelmAppService, application application2.ServiceClient, appArtifactManager AppArtifactManager, - cdPipelineConfigService CdPipelineConfigService) *AppDeploymentTypeChangeManagerImpl { + cdPipelineConfigService CdPipelineConfigService, + gitOpsConfigReadService config.GitOpsConfigReadService, + chartService chartService.ChartService) *AppDeploymentTypeChangeManagerImpl { return &AppDeploymentTypeChangeManagerImpl{ logger: logger, pipelineRepository: pipelineRepository, workflowDagExecutor: workflowDagExecutor, appService: appService, - chartTemplateService: chartTemplateService, appStatusRepository: appStatusRepository, helmAppService: helmAppService, application: application, appArtifactManager: appArtifactManager, cdPipelineConfigService: cdPipelineConfigService, + gitOpsConfigReadService: gitOpsConfigReadService, + chartService: chartService, } } @@ -397,7 +402,7 @@ func (impl *AppDeploymentTypeChangeManagerImpl) DeleteDeploymentApps(ctx context successfulPipelines := make([]*bean.DeploymentChangeStatus, 0) failedPipelines := make([]*bean.DeploymentChangeStatus, 0) - isGitOpsConfigured, gitOpsConfigErr := impl.cdPipelineConfigService.IsGitopsConfigured() + isGitOpsConfigured, gitOpsConfigErr := impl.gitOpsConfigReadService.IsGitOpsConfigured() // Iterate over all the pipelines in the environment for given deployment app type for _, pipeline := range pipelines { @@ -445,7 +450,7 @@ func (impl *AppDeploymentTypeChangeManagerImpl) DeleteDeploymentApps(ctx context impl.logger.Errorw("error in registering acd app", "err", err) } if AcdRegisterErr == nil { - RepoURLUpdateErr = impl.chartTemplateService.UpdateGitRepoUrlInCharts(pipeline.AppId, chartGitAttr, userId) + RepoURLUpdateErr = impl.chartService.UpdateGitRepoUrlInCharts(pipeline.AppId, chartGitAttr.RepoUrl, chartGitAttr.ChartLocation, userId) if RepoURLUpdateErr != nil { impl.logger.Errorw("error in updating git repo url in charts", "err", err) } diff --git a/pkg/pipeline/DeploymentConfigService.go b/pkg/pipeline/DeploymentConfigService.go index fa7a7a8972e..f12c90c9e06 100644 --- a/pkg/pipeline/DeploymentConfigService.go +++ b/pkg/pipeline/DeploymentConfigService.go @@ -3,11 +3,12 @@ package pipeline import ( "context" "encoding/json" - "github.com/devtron-labs/devtron/internal/sql/repository" "github.com/devtron-labs/devtron/internal/sql/repository/chartConfig" "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig" "github.com/devtron-labs/devtron/pkg/bean" chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deployedAppMetrics" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/chartRef" "github.com/devtron-labs/devtron/pkg/pipeline/history" repository2 "github.com/devtron-labs/devtron/pkg/pipeline/history/repository" "github.com/devtron-labs/devtron/pkg/resourceQualifiers" @@ -24,43 +25,39 @@ type DeploymentConfigService interface { } type DeploymentConfigServiceImpl struct { - logger *zap.SugaredLogger - envConfigOverrideRepository chartConfig.EnvConfigOverrideRepository - chartRepository chartRepoRepository.ChartRepository - pipelineRepository pipelineConfig.PipelineRepository - envLevelAppMetricsRepository repository.EnvLevelAppMetricsRepository - appLevelMetricsRepository repository.AppLevelMetricsRepository - pipelineConfigRepository chartConfig.PipelineConfigRepository - configMapRepository chartConfig.ConfigMapRepository - configMapHistoryService history.ConfigMapHistoryService - chartRefRepository chartRepoRepository.ChartRefRepository - scopedVariableManager variables.ScopedVariableCMCSManager + logger *zap.SugaredLogger + envConfigOverrideRepository chartConfig.EnvConfigOverrideRepository + chartRepository chartRepoRepository.ChartRepository + pipelineRepository pipelineConfig.PipelineRepository + pipelineConfigRepository chartConfig.PipelineConfigRepository + configMapRepository chartConfig.ConfigMapRepository + configMapHistoryService history.ConfigMapHistoryService + scopedVariableManager variables.ScopedVariableCMCSManager + deployedAppMetricsService deployedAppMetrics.DeployedAppMetricsService + chartRefService chartRef.ChartRefService } func NewDeploymentConfigServiceImpl(logger *zap.SugaredLogger, envConfigOverrideRepository chartConfig.EnvConfigOverrideRepository, chartRepository chartRepoRepository.ChartRepository, pipelineRepository pipelineConfig.PipelineRepository, - envLevelAppMetricsRepository repository.EnvLevelAppMetricsRepository, - appLevelMetricsRepository repository.AppLevelMetricsRepository, pipelineConfigRepository chartConfig.PipelineConfigRepository, configMapRepository chartConfig.ConfigMapRepository, configMapHistoryService history.ConfigMapHistoryService, - chartRefRepository chartRepoRepository.ChartRefRepository, scopedVariableManager variables.ScopedVariableCMCSManager, -) *DeploymentConfigServiceImpl { + deployedAppMetricsService deployedAppMetrics.DeployedAppMetricsService, + chartRefService chartRef.ChartRefService) *DeploymentConfigServiceImpl { return &DeploymentConfigServiceImpl{ - logger: logger, - envConfigOverrideRepository: envConfigOverrideRepository, - chartRepository: chartRepository, - pipelineRepository: pipelineRepository, - envLevelAppMetricsRepository: envLevelAppMetricsRepository, - appLevelMetricsRepository: appLevelMetricsRepository, - pipelineConfigRepository: pipelineConfigRepository, - configMapRepository: configMapRepository, - configMapHistoryService: configMapHistoryService, - chartRefRepository: chartRefRepository, - scopedVariableManager: scopedVariableManager, + logger: logger, + envConfigOverrideRepository: envConfigOverrideRepository, + chartRepository: chartRepository, + pipelineRepository: pipelineRepository, + pipelineConfigRepository: pipelineConfigRepository, + configMapRepository: configMapRepository, + configMapHistoryService: configMapHistoryService, + scopedVariableManager: scopedVariableManager, + deployedAppMetricsService: deployedAppMetricsService, + chartRefService: chartRefService, } } @@ -97,19 +94,10 @@ func (impl *DeploymentConfigServiceImpl) GetLatestDeploymentConfigurationByPipel } func (impl *DeploymentConfigServiceImpl) GetLatestDeploymentTemplateConfig(ctx context.Context, pipeline *pipelineConfig.Pipeline) (*history.HistoryDetailDto, error) { - isAppMetricsEnabled := false - envLevelAppMetrics, err := impl.envLevelAppMetricsRepository.FindByAppIdAndEnvId(pipeline.AppId, pipeline.EnvironmentId) - if err != nil && err != pg.ErrNoRows { - impl.logger.Errorw("error in getting env level app metrics", "err", err, "appId", pipeline.AppId, "envId", pipeline.EnvironmentId) - } else if err == pg.ErrNoRows { - appLevelAppMetrics, err := impl.appLevelMetricsRepository.FindByAppId(pipeline.AppId) - if err != nil && err != pg.ErrNoRows { - impl.logger.Errorw("error in getting app level app metrics", "err", err, "appId", pipeline.AppId) - } else if err == nil { - isAppMetricsEnabled = appLevelAppMetrics.AppMetrics - } - } else { - isAppMetricsEnabled = *envLevelAppMetrics.AppMetrics + isAppMetricsEnabled, err := impl.deployedAppMetricsService.GetMetricsFlagForAPipelineByAppIdAndEnvId(pipeline.AppId, pipeline.EnvironmentId) + if err != nil { + impl.logger.Errorw("error, GetMetricsFlagForAPipelineByAppIdAndEnvId", "err", err, "appId", pipeline.AppId, "envId", pipeline.EnvironmentId) + return nil, err } envOverride, err := impl.envConfigOverrideRepository.ActiveEnvConfigOverride(pipeline.AppId, pipeline.EnvironmentId) if err != nil { @@ -120,7 +108,7 @@ func (impl *DeploymentConfigServiceImpl) GetLatestDeploymentTemplateConfig(ctx c deploymentTemplateConfig := &history.HistoryDetailDto{} if envOverride != nil && envOverride.Id > 0 && envOverride.IsOverride { if envOverride.Chart != nil { - chartRef, err := impl.chartRefRepository.FindById(envOverride.Chart.ChartRefId) + chartRefDto, err := impl.chartRefService.FindById(envOverride.Chart.ChartRefId) if err != nil { impl.logger.Errorw("error in getting chartRef by id", "err", err, "chartRefId", envOverride.Chart.ChartRefId) return nil, err @@ -145,7 +133,7 @@ func (impl *DeploymentConfigServiceImpl) GetLatestDeploymentTemplateConfig(ctx c deploymentTemplateConfig = &history.HistoryDetailDto{ TemplateName: envOverride.Chart.ChartName, - TemplateVersion: chartRef.Version, + TemplateVersion: chartRefDto.Version, IsAppMetricsEnabled: &isAppMetricsEnabled, CodeEditorValue: &history.HistoryDetailConfig{ DisplayName: "values.yaml", @@ -161,7 +149,7 @@ func (impl *DeploymentConfigServiceImpl) GetLatestDeploymentTemplateConfig(ctx c impl.logger.Errorw("error in getting chart by appId", "err", err, "appId", pipeline.AppId) return nil, err } - chartRef, err := impl.chartRefRepository.FindById(chart.ChartRefId) + chartRefDto, err := impl.chartRefService.FindById(chart.ChartRefId) if err != nil { impl.logger.Errorw("error in getting chartRef by id", "err", err, "chartRefId", envOverride.Chart.ChartRefId) return nil, err @@ -186,7 +174,7 @@ func (impl *DeploymentConfigServiceImpl) GetLatestDeploymentTemplateConfig(ctx c } deploymentTemplateConfig = &history.HistoryDetailDto{ TemplateName: chart.ChartName, - TemplateVersion: chartRef.Version, + TemplateVersion: chartRefDto.Version, IsAppMetricsEnabled: &isAppMetricsEnabled, CodeEditorValue: &history.HistoryDetailConfig{ DisplayName: "values.yaml", diff --git a/pkg/pipeline/DeploymentPipelineConfigService.go b/pkg/pipeline/DeploymentPipelineConfigService.go index 122a9b18994..016dc73d06d 100644 --- a/pkg/pipeline/DeploymentPipelineConfigService.go +++ b/pkg/pipeline/DeploymentPipelineConfigService.go @@ -26,6 +26,7 @@ import ( bean2 "github.com/devtron-labs/devtron/api/bean" client "github.com/devtron-labs/devtron/api/helm-app" models2 "github.com/devtron-labs/devtron/api/helm-app/models" + "github.com/devtron-labs/devtron/client/argocdServer" "github.com/devtron-labs/devtron/client/argocdServer/application" "github.com/devtron-labs/devtron/internal/sql/models" "github.com/devtron-labs/devtron/internal/sql/repository" @@ -40,6 +41,10 @@ import ( chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository" "github.com/devtron-labs/devtron/pkg/cluster" repository2 "github.com/devtron-labs/devtron/pkg/cluster/repository" + commonBean "github.com/devtron-labs/devtron/pkg/deployment/gitOps/common/bean" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deployedAppMetrics" "github.com/devtron-labs/devtron/pkg/imageDigestPolicy" bean3 "github.com/devtron-labs/devtron/pkg/pipeline/bean" "github.com/devtron-labs/devtron/pkg/pipeline/history" @@ -108,8 +113,7 @@ type CdPipelineConfigService interface { MarkGitOpsDevtronAppsDeletedWhereArgoAppIsDeleted(appId int, envId int, acdToken string, pipeline *pipelineConfig.Pipeline) (bool, error) //GetEnvironmentListForAutocompleteFilter : lists environment for given configuration GetEnvironmentListForAutocompleteFilter(envName string, clusterIds []int, offset int, size int, token string, checkAuthBatch func(token string, appObject []string, envObject []string) (map[string]bool, map[string]bool), ctx context.Context) (*cluster.ResourceGroupingResponse, error) - IsGitopsConfigured() (bool, error) - RegisterInACD(gitOpsRepoName string, chartGitAttr *util.ChartGitAttribute, userId int32, ctx context.Context) error + RegisterInACD(gitOpsRepoName string, chartGitAttr *commonBean.ChartGitAttribute, userId int32, ctx context.Context) error } type CdPipelineConfigServiceImpl struct { @@ -129,14 +133,10 @@ type CdPipelineConfigServiceImpl struct { clusterRepository repository2.ClusterRepository helmAppService client.HelmAppService enforcerUtil rbac.EnforcerUtil - gitOpsRepository repository.GitOpsConfigRepository pipelineStrategyHistoryService history.PipelineStrategyHistoryService chartRepository chartRepoRepository.ChartRepository resourceGroupService resourceGroup2.ResourceGroupService - chartDeploymentService util.ChartDeploymentService - chartTemplateService util.ChartTemplateService propertiesConfigService PropertiesConfigService - appLevelMetricsRepository repository.AppLevelMetricsRepository deploymentTemplateHistoryService history.DeploymentTemplateHistoryService scopedVariableManager variables.ScopedVariableManager deploymentConfig *DeploymentServiceTypeConfig @@ -146,43 +146,32 @@ type CdPipelineConfigServiceImpl struct { devtronAppCMCSService DevtronAppCMCSService ciPipelineConfigService CiPipelineConfigService buildPipelineSwitchService BuildPipelineSwitchService + argoClientWrapperService argocdServer.ArgoClientWrapperService + deployedAppMetricsService deployedAppMetrics.DeployedAppMetricsService + gitOpsConfigReadService config.GitOpsConfigReadService + gitOperationService git.GitOperationService imageDigestPolicyService imageDigestPolicy.ImageDigestPolicyService } -func NewCdPipelineConfigServiceImpl( - logger *zap.SugaredLogger, - pipelineRepository pipelineConfig.PipelineRepository, - environmentRepository repository2.EnvironmentRepository, - pipelineConfigRepository chartConfig.PipelineConfigRepository, - appWorkflowRepository appWorkflow.AppWorkflowRepository, - pipelineStageService PipelineStageService, - appRepo app2.AppRepository, - appService app.AppService, - deploymentGroupRepository repository.DeploymentGroupRepository, - ciCdPipelineOrchestrator CiCdPipelineOrchestrator, - appStatusRepository appStatus.AppStatusRepository, - ciPipelineRepository pipelineConfig.CiPipelineRepository, - prePostCdScriptHistoryService history.PrePostCdScriptHistoryService, - clusterRepository repository2.ClusterRepository, - helmAppService client.HelmAppService, - enforcerUtil rbac.EnforcerUtil, - gitOpsRepository repository.GitOpsConfigRepository, - pipelineStrategyHistoryService history.PipelineStrategyHistoryService, - chartRepository chartRepoRepository.ChartRepository, - resourceGroupService resourceGroup2.ResourceGroupService, - chartDeploymentService util.ChartDeploymentService, - chartTemplateService util.ChartTemplateService, +func NewCdPipelineConfigServiceImpl(logger *zap.SugaredLogger, pipelineRepository pipelineConfig.PipelineRepository, + environmentRepository repository2.EnvironmentRepository, pipelineConfigRepository chartConfig.PipelineConfigRepository, + appWorkflowRepository appWorkflow.AppWorkflowRepository, pipelineStageService PipelineStageService, + appRepo app2.AppRepository, appService app.AppService, deploymentGroupRepository repository.DeploymentGroupRepository, + ciCdPipelineOrchestrator CiCdPipelineOrchestrator, appStatusRepository appStatus.AppStatusRepository, + ciPipelineRepository pipelineConfig.CiPipelineRepository, prePostCdScriptHistoryService history.PrePostCdScriptHistoryService, + clusterRepository repository2.ClusterRepository, helmAppService client.HelmAppService, + enforcerUtil rbac.EnforcerUtil, pipelineStrategyHistoryService history.PipelineStrategyHistoryService, + chartRepository chartRepoRepository.ChartRepository, resourceGroupService resourceGroup2.ResourceGroupService, propertiesConfigService PropertiesConfigService, - appLevelMetricsRepository repository.AppLevelMetricsRepository, deploymentTemplateHistoryService history.DeploymentTemplateHistoryService, - scopedVariableManager variables.ScopedVariableManager, - deploymentConfig *DeploymentServiceTypeConfig, - application application.ServiceClient, - customTagService CustomTagService, - pipelineConfigListenerService PipelineConfigListenerService, - devtronAppCMCSService DevtronAppCMCSService, - ciPipelineConfigService CiPipelineConfigService, - buildPipelineSwitchService BuildPipelineSwitchService, + scopedVariableManager variables.ScopedVariableManager, deploymentConfig *DeploymentServiceTypeConfig, + application application.ServiceClient, customTagService CustomTagService, + pipelineConfigListenerService PipelineConfigListenerService, devtronAppCMCSService DevtronAppCMCSService, + ciPipelineConfigService CiPipelineConfigService, buildPipelineSwitchService BuildPipelineSwitchService, + argoClientWrapperService argocdServer.ArgoClientWrapperService, + deployedAppMetricsService deployedAppMetrics.DeployedAppMetricsService, + gitOpsConfigReadService config.GitOpsConfigReadService, + gitOperationService git.GitOperationService, imageDigestPolicyService imageDigestPolicy.ImageDigestPolicyService) *CdPipelineConfigServiceImpl { return &CdPipelineConfigServiceImpl{ logger: logger, @@ -201,14 +190,10 @@ func NewCdPipelineConfigServiceImpl( clusterRepository: clusterRepository, helmAppService: helmAppService, enforcerUtil: enforcerUtil, - gitOpsRepository: gitOpsRepository, pipelineStrategyHistoryService: pipelineStrategyHistoryService, chartRepository: chartRepository, resourceGroupService: resourceGroupService, - chartDeploymentService: chartDeploymentService, - chartTemplateService: chartTemplateService, propertiesConfigService: propertiesConfigService, - appLevelMetricsRepository: appLevelMetricsRepository, deploymentTemplateHistoryService: deploymentTemplateHistoryService, scopedVariableManager: scopedVariableManager, deploymentConfig: deploymentConfig, @@ -218,6 +203,10 @@ func NewCdPipelineConfigServiceImpl( customTagService: customTagService, ciPipelineConfigService: ciPipelineConfigService, buildPipelineSwitchService: buildPipelineSwitchService, + argoClientWrapperService: argoClientWrapperService, + deployedAppMetricsService: deployedAppMetricsService, + gitOpsConfigReadService: gitOpsConfigReadService, + gitOperationService: gitOperationService, imageDigestPolicyService: imageDigestPolicyService, } } @@ -367,8 +356,11 @@ func (impl *CdPipelineConfigServiceImpl) GetCdPipelineById(pipelineId int) (cdPi func (impl *CdPipelineConfigServiceImpl) CreateCdPipelines(pipelineCreateRequest *bean.CdPipelines, ctx context.Context) (*bean.CdPipelines, error) { //Validation for checking deployment App type - isGitOpsConfigured, err := impl.IsGitopsConfigured() - + isGitOpsConfigured, err := impl.gitOpsConfigReadService.IsGitOpsConfigured() + if err != nil { + impl.logger.Errorw("error in checking if gitOps is configured or not", "err", err) + return nil, err + } for _, pipeline := range pipelineCreateRequest.Pipelines { // skip creation of pipeline if envId is not set if pipeline.EnvironmentId <= 0 { @@ -1541,23 +1533,6 @@ func (impl *CdPipelineConfigServiceImpl) GetEnvironmentListForAutocompleteFilter return result, nil } -func (impl *CdPipelineConfigServiceImpl) IsGitopsConfigured() (bool, error) { - - isGitOpsConfigured := false - gitOpsConfig, err := impl.gitOpsRepository.GetGitOpsConfigActive() - - if err != nil && err != pg.ErrNoRows { - impl.logger.Errorw("GetGitOpsConfigActive, error while getting", "err", err) - return false, err - } - if gitOpsConfig != nil && gitOpsConfig.Id > 0 { - isGitOpsConfigured = true - } - - return isGitOpsConfigured, nil - -} - func (impl *CdPipelineConfigServiceImpl) validateDeploymentAppType(pipeline *bean.CDPipelineConfigObject, deploymentConfig map[string]bool) error { // Config value doesn't exist in attribute table @@ -1641,21 +1616,20 @@ func (impl *CdPipelineConfigServiceImpl) ValidateCDPipelineRequest(pipelineCreat } -func (impl *CdPipelineConfigServiceImpl) RegisterInACD(gitOpsRepoName string, chartGitAttr *util.ChartGitAttribute, userId int32, ctx context.Context) error { - - err := impl.chartDeploymentService.RegisterInArgo(chartGitAttr, ctx) +func (impl *CdPipelineConfigServiceImpl) RegisterInACD(gitOpsRepoName string, chartGitAttr *commonBean.ChartGitAttribute, userId int32, ctx context.Context) error { + err := impl.argoClientWrapperService.RegisterGitOpsRepoInArgo(ctx, chartGitAttr.RepoUrl) if err != nil { impl.logger.Errorw("error while register git repo in argo", "err", err) emptyRepoErrorMessage := []string{"failed to get index: 404 Not Found", "remote repository is empty"} if strings.Contains(err.Error(), emptyRepoErrorMessage[0]) || strings.Contains(err.Error(), emptyRepoErrorMessage[1]) { // - found empty repository, create some file in repository - err := impl.chartTemplateService.CreateReadmeInGitRepo(gitOpsRepoName, userId) + err := impl.gitOperationService.CreateReadmeInGitRepo(gitOpsRepoName, userId) if err != nil { impl.logger.Errorw("error in creating file in git repo", "err", err) return err } // - retry register in argo - err = impl.chartDeploymentService.RegisterInArgo(chartGitAttr, ctx) + err = impl.argoClientWrapperService.RegisterGitOpsRepoInArgo(ctx, chartGitAttr.RepoUrl) if err != nil { impl.logger.Errorw("error in re-try register in argo", "err", err) return err @@ -1713,11 +1687,20 @@ func (impl *CdPipelineConfigServiceImpl) createCdPipeline(ctx context.Context, a if err != nil { return 0, err } - envOverride, err := impl.propertiesConfigService.CreateIfRequired(chart, pipeline.EnvironmentId, userId, false, models.CHARTSTATUS_NEW, false, false, pipeline.Namespace, chart.IsBasicViewLocked, chart.CurrentViewEditor, tx) + //getting global app metrics for cd pipeline create because env level metrics is not created yet + appLevelAppMetricsEnabled := false + isAppLevelMetricsEnabled, err := impl.deployedAppMetricsService.GetMetricsFlagByAppId(app.Id) if err != nil { + impl.logger.Errorw("error, GetMetricsFlagByAppId", "err", err, "appId", app.Id) return 0, err } - + appLevelAppMetricsEnabled = isAppLevelMetricsEnabled + envOverride, updatedAppMetrics, err := impl.propertiesConfigService.CreateIfRequired(chart, pipeline.EnvironmentId, userId, false, + models.CHARTSTATUS_NEW, false, appLevelAppMetricsEnabled, pipeline.Namespace, chart.IsBasicViewLocked, chart.CurrentViewEditor, tx) + if err != nil { + return 0, err + } + appLevelAppMetricsEnabled = updatedAppMetrics // Get pipeline override based on Deployment strategy //TODO: mark as created in our db pipelineId, err = impl.ciCdPipelineOrchestrator.CreateCDPipelines(pipeline, app.Id, userId, tx, app.AppName) @@ -1774,14 +1757,7 @@ func (impl *CdPipelineConfigServiceImpl) createCdPipeline(ctx context.Context, a return 0, err } } - //getting global app metrics for cd pipeline create because env level metrics is not created yet - appLevelAppMetricsEnabled := false - appLevelMetrics, err := impl.appLevelMetricsRepository.FindByAppId(app.Id) - if err != nil && err != pg.ErrNoRows { - impl.logger.Errorw("error in getting app level metrics app level", "error", err) - } else if err == nil { - appLevelAppMetricsEnabled = appLevelMetrics.AppMetrics - } + err = impl.deploymentTemplateHistoryService.CreateDeploymentTemplateHistoryFromEnvOverrideTemplate(envOverride, tx, appLevelAppMetricsEnabled, pipelineId) if err != nil { impl.logger.Errorw("error in creating entry for env deployment template history", "err", err, "envOverride", envOverride) @@ -1990,7 +1966,7 @@ func (impl *CdPipelineConfigServiceImpl) handleDigestPolicyOperations(tx *pg.Tx, return resourceQualifierId, nil } -func (impl *CdPipelineConfigServiceImpl) updateGitRepoUrlInCharts(appId int, chartGitAttribute *util.ChartGitAttribute, userId int32) error { +func (impl *CdPipelineConfigServiceImpl) updateGitRepoUrlInCharts(appId int, chartGitAttribute *commonBean.ChartGitAttribute, userId int32) error { charts, err := impl.chartRepository.FindActiveChartsByAppId(appId) if err != nil && pg.ErrNoRows != err { return err diff --git a/pkg/pipeline/PropertiesConfig.go b/pkg/pipeline/PropertiesConfig.go index e20aaae55d8..40adfb2f7b1 100644 --- a/pkg/pipeline/PropertiesConfig.go +++ b/pkg/pipeline/PropertiesConfig.go @@ -18,24 +18,23 @@ package pipeline import ( + "context" "encoding/json" "fmt" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deployedAppMetrics" + bean2 "github.com/devtron-labs/devtron/pkg/deployment/manifest/deployedAppMetrics/bean" "github.com/devtron-labs/devtron/pkg/pipeline/bean" "github.com/devtron-labs/devtron/pkg/variables" repository5 "github.com/devtron-labs/devtron/pkg/variables/repository" "time" - chartService "github.com/devtron-labs/devtron/pkg/chart" chartRepoRepository "github.com/devtron-labs/devtron/pkg/chartRepo/repository" repository2 "github.com/devtron-labs/devtron/pkg/cluster/repository" "github.com/devtron-labs/devtron/pkg/pipeline/history" "github.com/devtron-labs/devtron/pkg/sql" - "github.com/devtron-labs/devtron/client/argocdServer/application" "github.com/devtron-labs/devtron/internal/sql/models" - "github.com/devtron-labs/devtron/internal/sql/repository" "github.com/devtron-labs/devtron/internal/sql/repository/chartConfig" - "github.com/devtron-labs/devtron/internal/util" "github.com/go-pg/pg" "github.com/juju/errors" "go.uber.org/zap" @@ -45,60 +44,42 @@ type PropertiesConfigService interface { CreateEnvironmentProperties(appId int, propertiesRequest *bean.EnvironmentProperties) (*bean.EnvironmentProperties, error) UpdateEnvironmentProperties(appId int, propertiesRequest *bean.EnvironmentProperties, userId int32) (*bean.EnvironmentProperties, error) //create environment entry for each new environment - CreateIfRequired(chart *chartRepoRepository.Chart, environmentId int, userId int32, manualReviewed bool, chartStatus models.ChartStatus, isOverride, isAppMetricsEnabled bool, namespace string, IsBasicViewLocked bool, CurrentViewEditor models.ChartsViewEditorType, tx *pg.Tx) (*chartConfig.EnvConfigOverride, error) + CreateIfRequired(chart *chartRepoRepository.Chart, environmentId int, userId int32, manualReviewed bool, chartStatus models.ChartStatus, isOverride, isAppMetricsEnabled bool, namespace string, IsBasicViewLocked bool, CurrentViewEditor models.ChartsViewEditorType, tx *pg.Tx) (*chartConfig.EnvConfigOverride, bool, error) GetEnvironmentProperties(appId, environmentId int, chartRefId int) (environmentPropertiesResponse *bean.EnvironmentPropertiesResponse, err error) GetEnvironmentPropertiesById(environmentId int) ([]bean.EnvironmentProperties, error) GetAppIdByChartEnvId(chartEnvId int) (*chartConfig.EnvConfigOverride, error) GetLatestEnvironmentProperties(appId, environmentId int) (*bean.EnvironmentProperties, error) - FindEnvLevelAppMetricsByAppIdAndEnvId(appId int, envId int) (*repository.EnvLevelAppMetrics, error) ResetEnvironmentProperties(id int) (bool, error) CreateEnvironmentPropertiesWithNamespace(appId int, propertiesRequest *bean.EnvironmentProperties) (*bean.EnvironmentProperties, error) - EnvMetricsEnableDisable(appMetricRequest *chartService.AppMetricEnableDisableRequest) (*chartService.AppMetricEnableDisableRequest, error) FetchEnvProperties(appId, envId, chartRefId int) (*chartConfig.EnvConfigOverride, error) } type PropertiesConfigServiceImpl struct { logger *zap.SugaredLogger envConfigRepo chartConfig.EnvConfigOverrideRepository chartRepo chartRepoRepository.ChartRepository - chartRefRepository chartRepoRepository.ChartRefRepository - mergeUtil util.MergeUtil environmentRepository repository2.EnvironmentRepository - ciCdPipelineOrchestrator CiCdPipelineOrchestrator - application application.ServiceClient - envLevelAppMetricsRepository repository.EnvLevelAppMetricsRepository - appLevelMetricsRepository repository.AppLevelMetricsRepository deploymentTemplateHistoryService history.DeploymentTemplateHistoryService scopedVariableManager variables.ScopedVariableManager + deployedAppMetricsService deployedAppMetrics.DeployedAppMetricsService } func NewPropertiesConfigServiceImpl(logger *zap.SugaredLogger, envConfigRepo chartConfig.EnvConfigOverrideRepository, chartRepo chartRepoRepository.ChartRepository, - chartRefRepository chartRepoRepository.ChartRefRepository, - mergeUtil util.MergeUtil, environmentRepository repository2.EnvironmentRepository, - ciCdPipelineOrchestrator CiCdPipelineOrchestrator, - application application.ServiceClient, - envLevelAppMetricsRepository repository.EnvLevelAppMetricsRepository, - appLevelMetricsRepository repository.AppLevelMetricsRepository, deploymentTemplateHistoryService history.DeploymentTemplateHistoryService, scopedVariableManager variables.ScopedVariableManager, -) *PropertiesConfigServiceImpl { + deployedAppMetricsService deployedAppMetrics.DeployedAppMetricsService) *PropertiesConfigServiceImpl { return &PropertiesConfigServiceImpl{ logger: logger, envConfigRepo: envConfigRepo, chartRepo: chartRepo, - chartRefRepository: chartRefRepository, - mergeUtil: mergeUtil, environmentRepository: environmentRepository, - ciCdPipelineOrchestrator: ciCdPipelineOrchestrator, - application: application, - envLevelAppMetricsRepository: envLevelAppMetricsRepository, - appLevelMetricsRepository: appLevelMetricsRepository, deploymentTemplateHistoryService: deploymentTemplateHistoryService, scopedVariableManager: scopedVariableManager, + deployedAppMetricsService: deployedAppMetricsService, } } @@ -191,27 +172,12 @@ func (impl PropertiesConfigServiceImpl) GetEnvironmentProperties(appId, environm environmentPropertiesResponse.EnvironmentConfig.CurrentViewEditor = chart.CurrentViewEditor } } - - envLevelMetrics, err := impl.envLevelAppMetricsRepository.FindByAppIdAndEnvId(appId, environmentId) - if err != nil && !util.IsErrNoRows(err) { - impl.logger.Error(err) + isAppMetricsEnabled, err := impl.deployedAppMetricsService.GetMetricsFlagForAPipelineByAppIdAndEnvId(appId, environmentId) + if err != nil { + impl.logger.Errorw("error, GetMetricsFlagForAPipelineByAppIdAndEnvId", "err", err, "appId", appId, "envId", environmentId) return nil, err } - if util.IsErrNoRows(err) { - appLevelMetrics, err := impl.appLevelMetricsRepository.FindByAppId(appId) - if err != nil && !util.IsErrNoRows(err) { - impl.logger.Errorw("error in app metrics app level flag", "error", err) - return nil, err - } - if util.IsErrNoRows(err) { - flag := false - environmentPropertiesResponse.AppMetrics = &flag - } else { - environmentPropertiesResponse.AppMetrics = &appLevelMetrics.AppMetrics - } - } else { - environmentPropertiesResponse.AppMetrics = envLevelMetrics.AppMetrics - } + environmentPropertiesResponse.AppMetrics = &isAppMetricsEnabled return environmentPropertiesResponse, nil } @@ -233,11 +199,11 @@ func (impl PropertiesConfigServiceImpl) CreateEnvironmentProperties(appId int, e if environmentProperties.AppMetrics != nil { appMetrics = *environmentProperties.AppMetrics } - envOverride, err := impl.CreateIfRequired(chart, environmentProperties.EnvironmentId, environmentProperties.UserId, environmentProperties.ManualReviewed, models.CHARTSTATUS_SUCCESS, true, appMetrics, environmentProperties.Namespace, environmentProperties.IsBasicViewLocked, environmentProperties.CurrentViewEditor, nil) + envOverride, appMetrics, err := impl.CreateIfRequired(chart, environmentProperties.EnvironmentId, environmentProperties.UserId, environmentProperties.ManualReviewed, models.CHARTSTATUS_SUCCESS, true, appMetrics, environmentProperties.Namespace, environmentProperties.IsBasicViewLocked, environmentProperties.CurrentViewEditor, nil) if err != nil { return nil, err } - + environmentProperties.AppMetrics = &appMetrics r := json.RawMessage{} err = r.UnmarshalJSON([]byte(envOverride.EnvOverrideValues)) if err != nil { @@ -260,31 +226,10 @@ func (impl PropertiesConfigServiceImpl) CreateEnvironmentProperties(appId int, e ChartRefId: environmentProperties.ChartRefId, IsOverride: envOverride.IsOverride, } - if err != nil { impl.logger.Errorw("chart version parsing", "err", err, "chartVersion", chart.ChartVersion) return nil, err } - chartRefValue, err := impl.chartRefRepository.FindById(environmentProperties.ChartRefId) - if err != nil { - impl.logger.Errorw("error in finding ref chart by id", "err", err) - return nil, err - } - if !(chartRefValue.IsAppMetricsSupported) { - appMetricsRequest := chartService.AppMetricEnableDisableRequest{UserId: environmentProperties.UserId, AppId: appId, EnvironmentId: environmentProperties.EnvironmentId, IsAppMetricsEnabled: false} - _, err = impl.EnvMetricsEnableDisable(&appMetricsRequest) - if err != nil { - impl.logger.Errorw("err while disable app metrics", "err", err, "appId", appId, "chartVersion", chart.ChartVersion) - return nil, err - } - } else { - appMetricsRequest := chartService.AppMetricEnableDisableRequest{UserId: environmentProperties.UserId, AppId: appId, EnvironmentId: environmentProperties.EnvironmentId, IsAppMetricsEnabled: appMetrics} - _, err = impl.EnvMetricsEnableDisable(&appMetricsRequest) - if err != nil { - impl.logger.Errorw("err while updating app metrics", "err", err) - return nil, err - } - } return environmentProperties, nil } @@ -357,26 +302,18 @@ func (impl PropertiesConfigServiceImpl) UpdateEnvironmentProperties(appId int, p if propertiesRequest.AppMetrics != nil { isAppMetricsEnabled = *propertiesRequest.AppMetrics } - chartRefValue, err := impl.chartRefRepository.FindById(oldEnvOverride.Chart.ChartRefId) + envLevelMetricsUpdateReq := &bean2.DeployedAppMetricsRequest{ + EnableMetrics: isAppMetricsEnabled, + AppId: appId, + EnvId: oldEnvOverride.TargetEnvironment, + ChartRefId: oldEnvOverride.Chart.ChartRefId, + UserId: propertiesRequest.UserId, + } + err = impl.deployedAppMetricsService.CreateOrUpdateAppOrEnvLevelMetrics(context.Background(), envLevelMetricsUpdateReq) if err != nil { - impl.logger.Errorw("error in finding ref chart by id", "err", err) + impl.logger.Errorw("error, CheckAndUpdateAppOrEnvLevelMetrics", "err", err, "req", envLevelMetricsUpdateReq) return nil, err } - if !(chartRefValue.IsAppMetricsSupported) { - appMetricsRequest := chartService.AppMetricEnableDisableRequest{UserId: propertiesRequest.UserId, AppId: appId, EnvironmentId: oldEnvOverride.TargetEnvironment, IsAppMetricsEnabled: false} - _, err = impl.EnvMetricsEnableDisable(&appMetricsRequest) - if err != nil { - impl.logger.Errorw("err while disable app metrics for lower versions", err) - return nil, err - } - } else { - appMetricsRequest := chartService.AppMetricEnableDisableRequest{UserId: propertiesRequest.UserId, AppId: appId, EnvironmentId: oldEnvOverride.TargetEnvironment, IsAppMetricsEnabled: isAppMetricsEnabled} - _, err = impl.EnvMetricsEnableDisable(&appMetricsRequest) - if err != nil { - impl.logger.Errorw("err while updating app metrics", "err", err) - return nil, err - } - } //creating history err = impl.deploymentTemplateHistoryService.CreateDeploymentTemplateHistoryFromEnvOverrideTemplate(override, nil, isAppMetricsEnabled, 0) @@ -393,38 +330,43 @@ func (impl PropertiesConfigServiceImpl) UpdateEnvironmentProperties(appId int, p return propertiesRequest, err } -func (impl PropertiesConfigServiceImpl) buildAppMetricsJson() ([]byte, error) { - appMetricsEnabled := chartService.AppMetricsEnabled{ - AppMetrics: true, - } - appMetricsJson, err := json.Marshal(appMetricsEnabled) - if err != nil { - impl.logger.Error(err) - return nil, err - } - return appMetricsJson, nil -} - -func (impl PropertiesConfigServiceImpl) CreateIfRequired(chart *chartRepoRepository.Chart, environmentId int, userId int32, manualReviewed bool, chartStatus models.ChartStatus, isOverride, isAppMetricsEnabled bool, namespace string, IsBasicViewLocked bool, CurrentViewEditor models.ChartsViewEditorType, tx *pg.Tx) (*chartConfig.EnvConfigOverride, error) { +func (impl PropertiesConfigServiceImpl) CreateIfRequired(chart *chartRepoRepository.Chart, environmentId int, userId int32, manualReviewed bool, chartStatus models.ChartStatus, isOverride, isAppMetricsEnabled bool, namespace string, IsBasicViewLocked bool, CurrentViewEditor models.ChartsViewEditorType, tx *pg.Tx) (*chartConfig.EnvConfigOverride, bool, error) { env, err := impl.environmentRepository.FindById(environmentId) if err != nil { - return nil, err + return nil, isAppMetricsEnabled, err } if env != nil && len(env.Namespace) > 0 { namespace = env.Namespace } + if isOverride { //case of override, to do app metrics operation + envLevelMetricsUpdateReq := &bean2.DeployedAppMetricsRequest{ + EnableMetrics: isAppMetricsEnabled, + AppId: chart.AppId, + EnvId: environmentId, + ChartRefId: chart.ChartRefId, + UserId: userId, + } + err = impl.deployedAppMetricsService.CreateOrUpdateAppOrEnvLevelMetrics(context.Background(), envLevelMetricsUpdateReq) + if err != nil { + impl.logger.Errorw("error, CheckAndUpdateAppOrEnvLevelMetrics", "err", err, "req", envLevelMetricsUpdateReq) + return nil, isAppMetricsEnabled, err + } + //updating metrics flag because it might be possible that the chartRef used was not supported and that could have override the metrics flag got in request + isAppMetricsEnabled = envLevelMetricsUpdateReq.EnableMetrics + } + envOverride, err := impl.envConfigRepo.GetByChartAndEnvironment(chart.Id, environmentId) if err != nil && !errors.IsNotFound(err) { - return nil, err + return nil, isAppMetricsEnabled, err } if errors.IsNotFound(err) { if isOverride { // before creating new entry, remove previous one from latest tag envOverrideExisting, err := impl.envConfigRepo.FindLatestChartForAppByAppIdAndEnvId(chart.AppId, environmentId) if err != nil && !errors.IsNotFound(err) { - return nil, err + return nil, isAppMetricsEnabled, err } if envOverrideExisting != nil { envOverrideExisting.Latest = false @@ -440,7 +382,7 @@ func (impl PropertiesConfigServiceImpl) CreateIfRequired(chart *chartRepoReposit envOverrideExisting, err = impl.envConfigRepo.Update(envOverrideExisting) } if err != nil { - return nil, err + return nil, isAppMetricsEnabled, err } } } @@ -473,23 +415,23 @@ func (impl PropertiesConfigServiceImpl) CreateIfRequired(chart *chartRepoReposit } if err != nil { impl.logger.Errorw("error in creating envconfig", "data", envOverride, "error", err) - return nil, err + return nil, isAppMetricsEnabled, err } err = impl.deploymentTemplateHistoryService.CreateDeploymentTemplateHistoryFromEnvOverrideTemplate(envOverride, tx, isAppMetricsEnabled, 0) if err != nil { impl.logger.Errorw("error in creating entry for env deployment template history", "err", err, "envOverride", envOverride) - return nil, err + return nil, isAppMetricsEnabled, err } //VARIABLE_MAPPING_UPDATE if envOverride.EnvOverrideValues != "{}" { err = impl.scopedVariableManager.ExtractAndMapVariables(envOverride.EnvOverrideValues, envOverride.Id, repository5.EntityTypeDeploymentTemplateEnvLevel, envOverride.CreatedBy, tx) if err != nil { - return nil, err + return nil, isAppMetricsEnabled, err } } } - return envOverride, nil + return envOverride, isAppMetricsEnabled, nil } func (impl PropertiesConfigServiceImpl) GetEnvironmentPropertiesById(envId int) ([]bean.EnvironmentProperties, error) { @@ -525,10 +467,6 @@ func (impl PropertiesConfigServiceImpl) GetAppIdByChartEnvId(chartEnvId int) (*c return envOverride, nil } -func (impl PropertiesConfigServiceImpl) FindEnvLevelAppMetricsByAppIdAndEnvId(appId int, envId int) (*repository.EnvLevelAppMetrics, error) { - return impl.envLevelAppMetricsRepository.FindByAppIdAndEnvId(appId, envId) -} - func (impl PropertiesConfigServiceImpl) GetLatestEnvironmentProperties(appId, environmentId int) (environmentProperties *bean.EnvironmentProperties, err error) { env, err := impl.environmentRepository.FindById(environmentId) if err != nil { @@ -583,18 +521,11 @@ func (impl PropertiesConfigServiceImpl) ResetEnvironmentProperties(id int) (bool if err != nil { impl.logger.Warnw("error in update envOverride", "envOverrideId", id) } - envLevelAppMetrics, err := impl.envLevelAppMetricsRepository.FindByAppIdAndEnvId(envOverride.Chart.AppId, envOverride.TargetEnvironment) - if err != nil && !util.IsErrNoRows(err) { - impl.logger.Errorw("error while fetching env level app metric", "err", err) + err = impl.deployedAppMetricsService.DeleteEnvLevelMetricsIfPresent(envOverride.Chart.AppId, envOverride.TargetEnvironment) + if err != nil { + impl.logger.Errorw("error, DeleteEnvLevelMetricsIfPresent", "err", err, "appId", envOverride.Chart.AppId, "envId", envOverride.TargetEnvironment) return false, err } - if envLevelAppMetrics.Id > 0 { - err = impl.envLevelAppMetricsRepository.Delete(envLevelAppMetrics) - if err != nil { - impl.logger.Errorw("error while deletion of app metric at env level", "err", err) - return false, err - } - } //VARIABLES err = impl.scopedVariableManager.RemoveMappedVariables(envOverride.Id, repository5.EntityTypeDeploymentTemplateEnvLevel, envOverride.UpdatedBy, nil) if err != nil { @@ -623,10 +554,11 @@ func (impl PropertiesConfigServiceImpl) CreateEnvironmentPropertiesWithNamespace if environmentProperties.AppMetrics != nil { appMetrics = *environmentProperties.AppMetrics } - envOverride, err = impl.CreateIfRequired(chart, environmentProperties.EnvironmentId, environmentProperties.UserId, environmentProperties.ManualReviewed, models.CHARTSTATUS_SUCCESS, false, appMetrics, environmentProperties.Namespace, environmentProperties.IsBasicViewLocked, environmentProperties.CurrentViewEditor, nil) + envOverride, appMetrics, err = impl.CreateIfRequired(chart, environmentProperties.EnvironmentId, environmentProperties.UserId, environmentProperties.ManualReviewed, models.CHARTSTATUS_SUCCESS, false, appMetrics, environmentProperties.Namespace, environmentProperties.IsBasicViewLocked, environmentProperties.CurrentViewEditor, nil) if err != nil { return nil, err } + environmentProperties.AppMetrics = &appMetrics } else { envOverride, err = impl.envConfigRepo.Get(environmentProperties.Id) if err != nil { @@ -666,83 +598,3 @@ func (impl PropertiesConfigServiceImpl) CreateEnvironmentPropertiesWithNamespace } return environmentProperties, nil } - -//below method is deprecated - -func (impl PropertiesConfigServiceImpl) EnvMetricsEnableDisable(appMetricRequest *chartService.AppMetricEnableDisableRequest) (*chartService.AppMetricEnableDisableRequest, error) { - // validate app metrics compatibility - var currentChart *chartConfig.EnvConfigOverride - var err error - currentChart, err = impl.envConfigRepo.FindLatestChartForAppByAppIdAndEnvId(appMetricRequest.AppId, appMetricRequest.EnvironmentId) - if err != nil && !errors.IsNotFound(err) { - impl.logger.Error(err) - return nil, err - } - if errors.IsNotFound(err) { - impl.logger.Errorw("no chart configured for this app", "appId", appMetricRequest.AppId) - err = &util.ApiError{ - InternalMessage: "no chart configured for this app", - UserMessage: "no chart configured for this app", - } - return nil, err - } - if appMetricRequest.IsAppMetricsEnabled == true { - chartRefValue, err := impl.chartRefRepository.FindById(currentChart.Chart.ChartRefId) - if err != nil { - impl.logger.Errorw("error in finding ref chart by id", "err", err) - return nil, err - } - if !(chartRefValue.IsAppMetricsSupported) { - err = &util.ApiError{ - InternalMessage: "chart version in not compatible for app metrics", - UserMessage: "chart version in not compatible for app metrics", - } - return nil, err - } - } - // update and create env level app metrics - envLevelAppMetrics, err := impl.envLevelAppMetricsRepository.FindByAppIdAndEnvId(appMetricRequest.AppId, appMetricRequest.EnvironmentId) - if err != nil && !util.IsErrNoRows(err) { - impl.logger.Error("err", err) - return nil, err - } - if envLevelAppMetrics == nil || envLevelAppMetrics.Id == 0 { - infraMetrics := true - envLevelAppMetrics = &repository.EnvLevelAppMetrics{ - AppId: appMetricRequest.AppId, - EnvId: appMetricRequest.EnvironmentId, - AppMetrics: &appMetricRequest.IsAppMetricsEnabled, - InfraMetrics: &infraMetrics, - AuditLog: sql.AuditLog{ - CreatedOn: time.Now(), - UpdatedOn: time.Now(), - CreatedBy: appMetricRequest.UserId, - UpdatedBy: appMetricRequest.UserId, - }, - } - err = impl.envLevelAppMetricsRepository.Save(envLevelAppMetrics) - if err != nil { - impl.logger.Error("err", err) - return nil, err - } - } else { - envLevelAppMetrics.AppMetrics = &appMetricRequest.IsAppMetricsEnabled - envLevelAppMetrics.UpdatedOn = time.Now() - envLevelAppMetrics.UpdatedBy = appMetricRequest.UserId - err = impl.envLevelAppMetricsRepository.Update(envLevelAppMetrics) - if err != nil { - impl.logger.Error("err", err) - return nil, err - } - } - //updating audit log details of chart as history service uses it - currentChart.UpdatedOn = time.Now() - currentChart.UpdatedBy = appMetricRequest.UserId - //creating history entry - err = impl.deploymentTemplateHistoryService.CreateDeploymentTemplateHistoryFromEnvOverrideTemplate(currentChart, nil, appMetricRequest.IsAppMetricsEnabled, 0) - if err != nil { - impl.logger.Errorw("error in creating entry for env deployment template history", "err", err, "envOverride", currentChart) - return nil, err - } - return appMetricRequest, err -} diff --git a/pkg/pipeline/WorkflowDagExecutor.go b/pkg/pipeline/WorkflowDagExecutor.go index ea063464834..02a44d41d0d 100644 --- a/pkg/pipeline/WorkflowDagExecutor.go +++ b/pkg/pipeline/WorkflowDagExecutor.go @@ -22,6 +22,11 @@ import ( "encoding/json" errors3 "errors" "fmt" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deployedAppMetrics" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/chartRef" + bean5 "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/chartRef/bean" "path" "strconv" "strings" @@ -41,10 +46,8 @@ import ( application2 "github.com/devtron-labs/devtron/client/argocdServer/application" gitSensorClient "github.com/devtron-labs/devtron/client/gitSensor" "github.com/devtron-labs/devtron/internal/middleware" - app2 "github.com/devtron-labs/devtron/internal/sql/repository/app" bean4 "github.com/devtron-labs/devtron/pkg/app/bean" "github.com/devtron-labs/devtron/pkg/app/status" - "github.com/devtron-labs/devtron/pkg/auth/authorisation/casbin" "github.com/devtron-labs/devtron/pkg/auth/user" "github.com/devtron-labs/devtron/pkg/chartRepo/repository" "github.com/devtron-labs/devtron/pkg/dockerRegistry" @@ -132,7 +135,6 @@ type WorkflowDagExecutorImpl struct { pipelineOverrideRepository chartConfig.PipelineOverrideRepository ciArtifactRepository repository.CiArtifactRepository user user.UserService - enforcer casbin.Enforcer enforcerUtil rbac.EnforcerUtil groupRepository repository.DeploymentGroupRepository envRepository repository2.EnvironmentRepository @@ -150,7 +152,6 @@ type WorkflowDagExecutorImpl struct { appLabelRepository pipelineConfig.AppLabelRepository gitSensorGrpcClient gitSensorClient.Client k8sCommonService k8s.K8sCommonService - pipelineStageRepository repository4.PipelineStageRepository pipelineStageService PipelineStageService config *types.CdConfig appServiceConfig *app.AppServiceConfig @@ -178,26 +179,22 @@ type WorkflowDagExecutorImpl struct { chartRepository chartRepoRepository.ChartRepository chartTemplateService util.ChartTemplateService strategyHistoryRepository repository3.PipelineStrategyHistoryRepository - appRepository app2.AppRepository deploymentTemplateHistoryRepository repository3.DeploymentTemplateHistoryRepository argoK8sClient argocdServer.ArgoK8sClient configMapRepository chartConfig.ConfigMapRepository configMapHistoryRepository repository3.ConfigMapHistoryRepository - refChartDir chartRepoRepository.RefChartDir helmAppService client2.HelmAppService helmAppClient client2.HelmAppClient - chartRefRepository chartRepoRepository.ChartRefRepository environmentConfigRepository chartConfig.EnvConfigOverrideRepository - appLevelMetricsRepository repository.AppLevelMetricsRepository - envLevelMetricsRepository repository.EnvLevelAppMetricsRepository mergeUtil *util.MergeUtil - gitOpsConfigRepository repository.GitOpsConfigRepository - gitFactory *util.GitFactory acdClient application2.ServiceClient argoClientWrapperService argocdServer.ArgoClientWrapperService - pipelineConfigListenerService PipelineConfigListenerService customTagService CustomTagService ACDConfig *argocdServer.ACDConfig + deployedAppMetricsService deployedAppMetrics.DeployedAppMetricsService + chartRefService chartRef.ChartRefService + gitOpsConfigReadService config.GitOpsConfigReadService + gitOperationService git.GitOperationService imageDigestPolicyService imageDigestPolicy.ImageDigestPolicyService } @@ -273,7 +270,7 @@ func NewWorkflowDagExecutorImpl(Logger *zap.SugaredLogger, pipelineRepository pi user user.UserService, groupRepository repository.DeploymentGroupRepository, envRepository repository2.EnvironmentRepository, - enforcer casbin.Enforcer, enforcerUtil rbac.EnforcerUtil, eventFactory client.EventFactory, + enforcerUtil rbac.EnforcerUtil, eventFactory client.EventFactory, eventClient client.EventClient, cvePolicyRepository security.CvePolicyRepository, scanResultRepository security.ImageScanResultRepository, appWorkflowRepository appWorkflow.AppWorkflowRepository, @@ -303,26 +300,23 @@ func NewWorkflowDagExecutorImpl(Logger *zap.SugaredLogger, pipelineRepository pi chartRepository chartRepoRepository.ChartRepository, chartTemplateService util.ChartTemplateService, strategyHistoryRepository repository3.PipelineStrategyHistoryRepository, - appRepository app2.AppRepository, deploymentTemplateHistoryRepository repository3.DeploymentTemplateHistoryRepository, ArgoK8sClient argocdServer.ArgoK8sClient, configMapRepository chartConfig.ConfigMapRepository, configMapHistoryRepository repository3.ConfigMapHistoryRepository, - refChartDir chartRepoRepository.RefChartDir, helmAppService client2.HelmAppService, helmAppClient client2.HelmAppClient, - chartRefRepository chartRepoRepository.ChartRefRepository, environmentConfigRepository chartConfig.EnvConfigOverrideRepository, - appLevelMetricsRepository repository.AppLevelMetricsRepository, - envLevelMetricsRepository repository.EnvLevelAppMetricsRepository, mergeUtil *util.MergeUtil, - gitOpsConfigRepository repository.GitOpsConfigRepository, - gitFactory *util.GitFactory, acdClient application2.ServiceClient, argoClientWrapperService argocdServer.ArgoClientWrapperService, pipelineConfigListenerService PipelineConfigListenerService, customTagService CustomTagService, ACDConfig *argocdServer.ACDConfig, + deployedAppMetricsService deployedAppMetrics.DeployedAppMetricsService, + chartRefService chartRef.ChartRefService, + gitOpsConfigReadService config.GitOpsConfigReadService, + gitOperationService git.GitOperationService, imageDigestPolicyService imageDigestPolicy.ImageDigestPolicyService, ) *WorkflowDagExecutorImpl { wde := &WorkflowDagExecutorImpl{logger: Logger, @@ -336,7 +330,6 @@ func NewWorkflowDagExecutorImpl(Logger *zap.SugaredLogger, pipelineRepository pi materialRepository: materialRepository, pipelineOverrideRepository: pipelineOverrideRepository, user: user, - enforcer: enforcer, enforcerUtil: enforcerUtil, groupRepository: groupRepository, envRepository: envRepository, @@ -378,26 +371,22 @@ func NewWorkflowDagExecutorImpl(Logger *zap.SugaredLogger, pipelineRepository pi chartRepository: chartRepository, chartTemplateService: chartTemplateService, strategyHistoryRepository: strategyHistoryRepository, - appRepository: appRepository, deploymentTemplateHistoryRepository: deploymentTemplateHistoryRepository, argoK8sClient: ArgoK8sClient, configMapRepository: configMapRepository, configMapHistoryRepository: configMapHistoryRepository, - refChartDir: refChartDir, helmAppService: helmAppService, helmAppClient: helmAppClient, - chartRefRepository: chartRefRepository, environmentConfigRepository: environmentConfigRepository, - appLevelMetricsRepository: appLevelMetricsRepository, - envLevelMetricsRepository: envLevelMetricsRepository, mergeUtil: mergeUtil, - gitOpsConfigRepository: gitOpsConfigRepository, - gitFactory: gitFactory, acdClient: acdClient, argoClientWrapperService: argoClientWrapperService, - pipelineConfigListenerService: pipelineConfigListenerService, customTagService: customTagService, ACDConfig: ACDConfig, + deployedAppMetricsService: deployedAppMetricsService, + chartRefService: chartRefService, + gitOpsConfigReadService: gitOpsConfigReadService, + gitOperationService: gitOperationService, imageDigestPolicyService: imageDigestPolicyService, } config, err := types.GetCdConfig() @@ -3678,7 +3667,7 @@ func (impl *WorkflowDagExecutorImpl) createHelmAppForCdPipeline(overrideRequest Name: pipeline.App.AppName, Version: envOverride.Chart.ChartVersion, } - referenceTemplatePath := path.Join(string(impl.refChartDir), envOverride.Chart.ReferenceTemplate) + referenceTemplatePath := path.Join(bean5.RefChartDirPath, envOverride.Chart.ReferenceTemplate) if util.IsHelmApp(pipeline.DeploymentAppType) { referenceChartByte := envOverride.Chart.ReferenceChart @@ -3860,7 +3849,7 @@ func (impl *WorkflowDagExecutorImpl) GetEnvOverrideByTriggerType(overrideRequest } //getting chart_ref by id _, span = otel.Tracer("orchestrator").Start(ctx, "chartRefRepository.FindByVersionAndName") - chartRef, err := impl.chartRefRepository.FindByVersionAndName(templateName, templateVersion) + chartRefDto, err := impl.chartRefService.FindByVersionAndName(templateName, templateVersion) span.End() if err != nil { impl.logger.Errorw("error in getting chartRef by version and name", "err", err, "version", templateVersion, "name", templateName) @@ -3868,10 +3857,10 @@ func (impl *WorkflowDagExecutorImpl) GetEnvOverrideByTriggerType(overrideRequest } //assuming that if a chartVersion is deployed then it's envConfigOverride will be available _, span = otel.Tracer("orchestrator").Start(ctx, "environmentConfigRepository.GetByAppIdEnvIdAndChartRefId") - envOverride, err = impl.environmentConfigRepository.GetByAppIdEnvIdAndChartRefId(overrideRequest.AppId, overrideRequest.EnvId, chartRef.Id) + envOverride, err = impl.environmentConfigRepository.GetByAppIdEnvIdAndChartRefId(overrideRequest.AppId, overrideRequest.EnvId, chartRefDto.Id) span.End() if err != nil { - impl.logger.Errorw("error in getting envConfigOverride for pipeline for specific chartVersion", "err", err, "appId", overrideRequest.AppId, "envId", overrideRequest.EnvId, "chartRefId", chartRef.Id) + impl.logger.Errorw("error in getting envConfigOverride for pipeline for specific chartVersion", "err", err, "appId", overrideRequest.AppId, "envId", overrideRequest.EnvId, "chartRefId", chartRefDto.Id) return nil, err } @@ -4013,25 +4002,14 @@ func (impl *WorkflowDagExecutorImpl) GetAppMetricsByTriggerType(overrideRequest appMetrics = deploymentTemplateHistory.IsAppMetricsEnabled } else if overrideRequest.DeploymentWithConfig == bean.DEPLOYMENT_CONFIG_TYPE_LAST_SAVED { - _, span := otel.Tracer("orchestrator").Start(ctx, "appLevelMetricsRepository.FindByAppId") - appLevelMetrics, err := impl.appLevelMetricsRepository.FindByAppId(overrideRequest.AppId) - span.End() - if err != nil && !util.IsErrNoRows(err) { - impl.logger.Errorw("err", err) - return appMetrics, &util.ApiError{InternalMessage: "unable to fetch app level metrics flag"} + _, span := otel.Tracer("orchestrator").Start(ctx, "deployedAppMetricsService.GetMetricsFlagForAPipelineByAppIdAndEnvId") + isAppMetricsEnabled, err := impl.deployedAppMetricsService.GetMetricsFlagForAPipelineByAppIdAndEnvId(overrideRequest.AppId, overrideRequest.EnvId) + if err != nil { + impl.logger.Errorw("error, GetMetricsFlagForAPipelineByAppIdAndEnvId", "err", err, "appId", overrideRequest.AppId, "envId", overrideRequest.EnvId) + return appMetrics, err } - appMetrics = appLevelMetrics.AppMetrics - - _, span = otel.Tracer("orchestrator").Start(ctx, "envLevelMetricsRepository.FindByAppIdAndEnvId") - envLevelMetrics, err := impl.envLevelMetricsRepository.FindByAppIdAndEnvId(overrideRequest.AppId, overrideRequest.EnvId) span.End() - if err != nil && !util.IsErrNoRows(err) { - impl.logger.Errorw("err", err) - return appMetrics, &util.ApiError{InternalMessage: "unable to fetch env level metrics flag"} - } - if envLevelMetrics.Id != 0 && envLevelMetrics.AppMetrics != nil { - appMetrics = *envLevelMetrics.AppMetrics - } + appMetrics = isAppMetricsEnabled } return appMetrics, nil } diff --git a/pkg/pipeline/history/DeploymentTemplateHistoryService.go b/pkg/pipeline/history/DeploymentTemplateHistoryService.go index 645d42c1cfc..8871f9cd98c 100644 --- a/pkg/pipeline/history/DeploymentTemplateHistoryService.go +++ b/pkg/pipeline/history/DeploymentTemplateHistoryService.go @@ -2,9 +2,10 @@ package history import ( "context" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deployedAppMetrics" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/chartRef" "time" - repository2 "github.com/devtron-labs/devtron/internal/sql/repository" "github.com/devtron-labs/devtron/internal/sql/repository/chartConfig" "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig" "github.com/devtron-labs/devtron/pkg/auth/user" @@ -38,35 +39,28 @@ type DeploymentTemplateHistoryServiceImpl struct { deploymentTemplateHistoryRepository repository.DeploymentTemplateHistoryRepository pipelineRepository pipelineConfig.PipelineRepository chartRepository chartRepoRepository.ChartRepository - chartRefRepository chartRepoRepository.ChartRefRepository - envLevelAppMetricsRepository repository2.EnvLevelAppMetricsRepository - appLevelMetricsRepository repository2.AppLevelMetricsRepository userService user.UserService cdWorkflowRepository pipelineConfig.CdWorkflowRepository scopedVariableManager variables.ScopedVariableManager + deployedAppMetricsService deployedAppMetrics.DeployedAppMetricsService + chartRefService chartRef.ChartRefService } func NewDeploymentTemplateHistoryServiceImpl(logger *zap.SugaredLogger, deploymentTemplateHistoryRepository repository.DeploymentTemplateHistoryRepository, - pipelineRepository pipelineConfig.PipelineRepository, - chartRepository chartRepoRepository.ChartRepository, - chartRefRepository chartRepoRepository.ChartRefRepository, - envLevelAppMetricsRepository repository2.EnvLevelAppMetricsRepository, - appLevelMetricsRepository repository2.AppLevelMetricsRepository, - userService user.UserService, - cdWorkflowRepository pipelineConfig.CdWorkflowRepository, - scopedVariableManager variables.ScopedVariableManager, -) *DeploymentTemplateHistoryServiceImpl { + pipelineRepository pipelineConfig.PipelineRepository, chartRepository chartRepoRepository.ChartRepository, + userService user.UserService, cdWorkflowRepository pipelineConfig.CdWorkflowRepository, + scopedVariableManager variables.ScopedVariableManager, deployedAppMetricsService deployedAppMetrics.DeployedAppMetricsService, + chartRefService chartRef.ChartRefService) *DeploymentTemplateHistoryServiceImpl { return &DeploymentTemplateHistoryServiceImpl{ logger: logger, deploymentTemplateHistoryRepository: deploymentTemplateHistoryRepository, pipelineRepository: pipelineRepository, chartRepository: chartRepository, - chartRefRepository: chartRefRepository, - envLevelAppMetricsRepository: envLevelAppMetricsRepository, - appLevelMetricsRepository: appLevelMetricsRepository, userService: userService, cdWorkflowRepository: cdWorkflowRepository, scopedVariableManager: scopedVariableManager, + deployedAppMetricsService: deployedAppMetricsService, + chartRefService: chartRefService, } } @@ -77,22 +71,19 @@ func (impl DeploymentTemplateHistoryServiceImpl) CreateDeploymentTemplateHistory impl.logger.Errorw("err in getting pipelines, CreateDeploymentTemplateHistoryFromGlobalTemplate", "err", err, "chart", chart) return err } - chartRef, err := impl.chartRefRepository.FindById(chart.ChartRefId) + chartRefDto, err := impl.chartRefService.FindById(chart.ChartRefId) if err != nil { impl.logger.Errorw("err in getting chartRef, CreateDeploymentTemplateHistoryFromGlobalTemplate", "err", err, "chart", chart) return err } - if len(chartRef.Name) == 0 { - chartRef.Name = "Rollout Deployment" - } //creating history without pipeline id historyModel := &repository.DeploymentTemplateHistory{ AppId: chart.AppId, ImageDescriptorTemplate: chart.ImageDescriptorTemplate, Template: chart.GlobalOverride, Deployed: false, - TemplateName: chartRef.Name, - TemplateVersion: chartRef.Version, + TemplateName: chartRefDto.Name, + TemplateVersion: chartRefDto.Version, IsAppMetricsEnabled: IsAppMetricsEnabled, AuditLog: sql.AuditLog{ CreatedOn: chart.CreatedOn, @@ -118,8 +109,8 @@ func (impl DeploymentTemplateHistoryServiceImpl) CreateDeploymentTemplateHistory ImageDescriptorTemplate: chart.ImageDescriptorTemplate, Template: chart.GlobalOverride, Deployed: false, - TemplateName: chartRef.Name, - TemplateVersion: chartRef.Version, + TemplateName: chartRefDto.Name, + TemplateVersion: chartRefDto.Version, IsAppMetricsEnabled: IsAppMetricsEnabled, AuditLog: sql.AuditLog{ CreatedOn: chart.CreatedOn, @@ -148,14 +139,11 @@ func (impl DeploymentTemplateHistoryServiceImpl) CreateDeploymentTemplateHistory impl.logger.Errorw("err in getting global deployment template", "err", err, "chart", chart) return err } - chartRef, err := impl.chartRefRepository.FindById(chart.ChartRefId) + chartRefDto, err := impl.chartRefService.FindById(chart.ChartRefId) if err != nil { - impl.logger.Errorw("err in getting chartRef, CreateDeploymentTemplateHistoryFromGlobalTemplate", "err", err, "chartRef", chartRef) + impl.logger.Errorw("err in getting chartRef, CreateDeploymentTemplateHistoryFromGlobalTemplate", "err", err, "chartRef", chartRefDto) return err } - if len(chartRef.Name) == 0 { - chartRef.Name = "Rollout Deployment" - } if pipelineId == 0 { pipeline, err := impl.pipelineRepository.GetByEnvOverrideIdAndEnvId(envOverride.Id, envOverride.TargetEnvironment) if err != nil && err != pg.ErrNoRows { @@ -170,8 +158,8 @@ func (impl DeploymentTemplateHistoryServiceImpl) CreateDeploymentTemplateHistory ImageDescriptorTemplate: chart.ImageDescriptorTemplate, TargetEnvironment: envOverride.TargetEnvironment, Deployed: false, - TemplateName: chartRef.Name, - TemplateVersion: chartRef.Version, + TemplateName: chartRefDto.Name, + TemplateVersion: chartRefDto.Version, IsAppMetricsEnabled: IsAppMetricsEnabled, AuditLog: sql.AuditLog{ CreatedOn: envOverride.CreatedOn, @@ -200,29 +188,15 @@ func (impl DeploymentTemplateHistoryServiceImpl) CreateDeploymentTemplateHistory } func (impl DeploymentTemplateHistoryServiceImpl) CreateDeploymentTemplateHistoryForDeploymentTrigger(pipeline *pipelineConfig.Pipeline, envOverride *chartConfig.EnvConfigOverride, renderedImageTemplate string, deployedOn time.Time, deployedBy int32) (*repository.DeploymentTemplateHistory, error) { - chartRef, err := impl.chartRefRepository.FindById(envOverride.Chart.ChartRefId) + chartRefDto, err := impl.chartRefService.FindById(envOverride.Chart.ChartRefId) if err != nil { - impl.logger.Errorw("err in getting chartRef, CreateDeploymentTemplateHistoryFromGlobalTemplate", "err", err, "chartRef", chartRef) + impl.logger.Errorw("err in getting chartRef, CreateDeploymentTemplateHistoryFromGlobalTemplate", "err", err, "chartRef", chartRefDto) return nil, err } - if len(chartRef.Name) == 0 { - chartRef.Name = "Rollout Deployment" - } - isAppMetricsEnabled := false - envLevelAppMetrics, err := impl.envLevelAppMetricsRepository.FindByAppIdAndEnvId(pipeline.AppId, pipeline.EnvironmentId) - if err != nil && err != pg.ErrNoRows { - impl.logger.Errorw("error in getting env level app metrics", "err", err, "appId", pipeline.AppId, "envId", pipeline.EnvironmentId) + isAppMetricsEnabled, err := impl.deployedAppMetricsService.GetMetricsFlagForAPipelineByAppIdAndEnvId(pipeline.AppId, pipeline.EnvironmentId) + if err != nil { + impl.logger.Errorw("error, GetMetricsFlagForAPipelineByAppIdAndEnvId", "err", err, "appId", pipeline.AppId, "envId", pipeline.EnvironmentId) return nil, err - } else if err == pg.ErrNoRows { - appLevelAppMetrics, err := impl.appLevelMetricsRepository.FindByAppId(pipeline.AppId) - if err != nil && err != pg.ErrNoRows { - impl.logger.Errorw("error in getting app level app metrics", "err", err, "appId", pipeline.AppId) - return nil, err - } else if err == nil { - isAppMetricsEnabled = appLevelAppMetrics.AppMetrics - } - } else { - isAppMetricsEnabled = *envLevelAppMetrics.AppMetrics } historyModel := &repository.DeploymentTemplateHistory{ AppId: pipeline.AppId, @@ -232,8 +206,8 @@ func (impl DeploymentTemplateHistoryServiceImpl) CreateDeploymentTemplateHistory Deployed: true, DeployedBy: deployedBy, DeployedOn: deployedOn, - TemplateName: chartRef.Name, - TemplateVersion: chartRef.Version, + TemplateName: chartRefDto.Name, + TemplateVersion: chartRefDto.Version, IsAppMetricsEnabled: isAppMetricsEnabled, AuditLog: sql.AuditLog{ CreatedOn: deployedOn, diff --git a/util/argo/ArgoUserService.go b/util/argo/ArgoUserService.go index 80af547c6cf..75715dd7049 100644 --- a/util/argo/ArgoUserService.go +++ b/util/argo/ArgoUserService.go @@ -9,10 +9,9 @@ import ( "github.com/devtron-labs/devtron/client/argocdServer" "github.com/devtron-labs/devtron/client/argocdServer/connection" "github.com/devtron-labs/devtron/client/argocdServer/session" - "github.com/devtron-labs/devtron/internal/sql/repository" "github.com/devtron-labs/devtron/pkg/cluster" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config" util2 "github.com/devtron-labs/devtron/util" - "github.com/go-pg/pg" "go.uber.org/zap" "golang.org/x/crypto/bcrypt" apiv1 "k8s.io/api/core/v1" @@ -48,22 +47,25 @@ type ArgoUserServiceImpl struct { clusterService cluster.ClusterService devtronSecretConfig *util2.DevtronSecretConfig runTimeConfig *client.RuntimeConfig - gitOpsRepository repository.GitOpsConfigRepository argoCDConnectionManager connection.ArgoCDConnectionManager versionService argocdServer.VersionService k8sUtil *k8s.K8sServiceImpl + gitOpsConfigReadService config.GitOpsConfigReadService } -func NewArgoUserServiceImpl(Logger *zap.SugaredLogger, clusterService cluster.ClusterService, devtronSecretConfig *util2.DevtronSecretConfig, runTimeConfig *client.RuntimeConfig, gitOpsRepository repository.GitOpsConfigRepository, argoCDConnectionManager connection.ArgoCDConnectionManager, versionService argocdServer.VersionService, k8sUtil *k8s.K8sServiceImpl) (*ArgoUserServiceImpl, error) { +func NewArgoUserServiceImpl(Logger *zap.SugaredLogger, clusterService cluster.ClusterService, + devtronSecretConfig *util2.DevtronSecretConfig, runTimeConfig *client.RuntimeConfig, + argoCDConnectionManager connection.ArgoCDConnectionManager, versionService argocdServer.VersionService, + k8sUtil *k8s.K8sServiceImpl, gitOpsConfigReadService config.GitOpsConfigReadService) (*ArgoUserServiceImpl, error) { argoUserServiceImpl := &ArgoUserServiceImpl{ logger: Logger, clusterService: clusterService, devtronSecretConfig: devtronSecretConfig, runTimeConfig: runTimeConfig, - gitOpsRepository: gitOpsRepository, argoCDConnectionManager: argoCDConnectionManager, versionService: versionService, k8sUtil: k8sUtil, + gitOpsConfigReadService: gitOpsConfigReadService, } if !runTimeConfig.LocalDevMode { go argoUserServiceImpl.ValidateGitOpsAndGetOrUpdateArgoCdUserDetail() @@ -72,7 +74,7 @@ func NewArgoUserServiceImpl(Logger *zap.SugaredLogger, clusterService cluster.Cl } func (impl *ArgoUserServiceImpl) ValidateGitOpsAndGetOrUpdateArgoCdUserDetail() string { - isGitOpsConfigured, err := impl.gitOpsRepository.IsGitOpsConfigured() + isGitOpsConfigured, err := impl.gitOpsConfigReadService.IsGitOpsConfigured() if err != nil || !isGitOpsConfigured { return "" } @@ -163,15 +165,11 @@ func (impl *ArgoUserServiceImpl) createNewArgoCdTokenForDevtron(username, passwo // note: this function also called for no gitops case, where apps are installed via helm func (impl *ArgoUserServiceImpl) GetLatestDevtronArgoCdUserToken() (string, error) { - isGitOpsConfigured := false - gitOpsConfig, err := impl.gitOpsRepository.GetGitOpsConfigActive() - if err != nil && err != pg.ErrNoRows { - impl.logger.Errorw("GetGitOpsConfigActive, error while getting", "err", err) + isGitOpsConfigured, err := impl.gitOpsConfigReadService.IsGitOpsConfigured() + if err != nil { + impl.logger.Errorw("error while checking if gitOps is configured", "err", err) return "", err } - if gitOpsConfig != nil && gitOpsConfig.Id > 0 { - isGitOpsConfigured = true - } if !isGitOpsConfigured { //here acd token only required in context for argo cd calls return "", nil diff --git a/wire_gen.go b/wire_gen.go index 33907b59b9f..1c0ba9a9bfd 100644 --- a/wire_gen.go +++ b/wire_gen.go @@ -47,7 +47,7 @@ import ( "github.com/devtron-labs/devtron/client/argocdServer/application" "github.com/devtron-labs/devtron/client/argocdServer/cluster" "github.com/devtron-labs/devtron/client/argocdServer/connection" - repository9 "github.com/devtron-labs/devtron/client/argocdServer/repository" + repository13 "github.com/devtron-labs/devtron/client/argocdServer/repository" cron2 "github.com/devtron-labs/devtron/client/cron" "github.com/devtron-labs/devtron/client/dashboard" "github.com/devtron-labs/devtron/client/events" @@ -76,19 +76,18 @@ import ( "github.com/devtron-labs/devtron/pkg/appClone" "github.com/devtron-labs/devtron/pkg/appClone/batch" appStatus2 "github.com/devtron-labs/devtron/pkg/appStatus" - "github.com/devtron-labs/devtron/pkg/appStore/bean" "github.com/devtron-labs/devtron/pkg/appStore/chartGroup" - repository11 "github.com/devtron-labs/devtron/pkg/appStore/chartGroup/repository" + repository15 "github.com/devtron-labs/devtron/pkg/appStore/chartGroup/repository" "github.com/devtron-labs/devtron/pkg/appStore/chartProvider" "github.com/devtron-labs/devtron/pkg/appStore/deployment/common" "github.com/devtron-labs/devtron/pkg/appStore/deployment/fullMode" repository3 "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" - "github.com/devtron-labs/devtron/pkg/appStore/deployment/service" + service2 "github.com/devtron-labs/devtron/pkg/appStore/deployment/service" "github.com/devtron-labs/devtron/pkg/appStore/deployment/tool" "github.com/devtron-labs/devtron/pkg/appStore/discover/repository" service3 "github.com/devtron-labs/devtron/pkg/appStore/discover/service" "github.com/devtron-labs/devtron/pkg/appStore/values/repository" - service2 "github.com/devtron-labs/devtron/pkg/appStore/values/service" + "github.com/devtron-labs/devtron/pkg/appStore/values/service" appWorkflow2 "github.com/devtron-labs/devtron/pkg/appWorkflow" "github.com/devtron-labs/devtron/pkg/attributes" "github.com/devtron-labs/devtron/pkg/auth/authentication" @@ -105,15 +104,21 @@ import ( "github.com/devtron-labs/devtron/pkg/clusterTerminalAccess" "github.com/devtron-labs/devtron/pkg/commonService" delete2 "github.com/devtron-labs/devtron/pkg/delete" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deployedAppMetrics" + repository11 "github.com/devtron-labs/devtron/pkg/deployment/manifest/deployedAppMetrics/repository" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate" + "github.com/devtron-labs/devtron/pkg/deployment/manifest/deploymentTemplate/chartRef" "github.com/devtron-labs/devtron/pkg/deploymentGroup" "github.com/devtron-labs/devtron/pkg/devtronResource" - repository8 "github.com/devtron-labs/devtron/pkg/devtronResource/repository" + repository7 "github.com/devtron-labs/devtron/pkg/devtronResource/repository" "github.com/devtron-labs/devtron/pkg/dockerRegistry" "github.com/devtron-labs/devtron/pkg/externalLink" "github.com/devtron-labs/devtron/pkg/generateManifest" "github.com/devtron-labs/devtron/pkg/genericNotes" - repository10 "github.com/devtron-labs/devtron/pkg/genericNotes/repository" - "github.com/devtron-labs/devtron/pkg/git" + repository12 "github.com/devtron-labs/devtron/pkg/genericNotes/repository" + git2 "github.com/devtron-labs/devtron/pkg/git" "github.com/devtron-labs/devtron/pkg/gitops" "github.com/devtron-labs/devtron/pkg/imageDigestPolicy" k8s2 "github.com/devtron-labs/devtron/pkg/k8s" @@ -121,7 +126,7 @@ import ( "github.com/devtron-labs/devtron/pkg/k8s/capacity" "github.com/devtron-labs/devtron/pkg/k8s/informer" "github.com/devtron-labs/devtron/pkg/kubernetesResourceAuditLogs" - repository15 "github.com/devtron-labs/devtron/pkg/kubernetesResourceAuditLogs/repository" + repository16 "github.com/devtron-labs/devtron/pkg/kubernetesResourceAuditLogs/repository" "github.com/devtron-labs/devtron/pkg/module" "github.com/devtron-labs/devtron/pkg/module/repo" "github.com/devtron-labs/devtron/pkg/module/store" @@ -129,11 +134,11 @@ import ( "github.com/devtron-labs/devtron/pkg/pipeline" "github.com/devtron-labs/devtron/pkg/pipeline/executors" "github.com/devtron-labs/devtron/pkg/pipeline/history" - repository6 "github.com/devtron-labs/devtron/pkg/pipeline/history/repository" - repository12 "github.com/devtron-labs/devtron/pkg/pipeline/repository" + repository8 "github.com/devtron-labs/devtron/pkg/pipeline/history/repository" + repository9 "github.com/devtron-labs/devtron/pkg/pipeline/repository" "github.com/devtron-labs/devtron/pkg/pipeline/types" "github.com/devtron-labs/devtron/pkg/plugin" - repository13 "github.com/devtron-labs/devtron/pkg/plugin/repository" + repository10 "github.com/devtron-labs/devtron/pkg/plugin/repository" resourceGroup2 "github.com/devtron-labs/devtron/pkg/resourceGroup" "github.com/devtron-labs/devtron/pkg/resourceQualifiers" security2 "github.com/devtron-labs/devtron/pkg/security" @@ -143,12 +148,12 @@ import ( "github.com/devtron-labs/devtron/pkg/sql" "github.com/devtron-labs/devtron/pkg/team" "github.com/devtron-labs/devtron/pkg/terminal" - util2 "github.com/devtron-labs/devtron/pkg/util" + util3 "github.com/devtron-labs/devtron/pkg/util" "github.com/devtron-labs/devtron/pkg/variables" "github.com/devtron-labs/devtron/pkg/variables/parsers" - repository7 "github.com/devtron-labs/devtron/pkg/variables/repository" + repository6 "github.com/devtron-labs/devtron/pkg/variables/repository" "github.com/devtron-labs/devtron/pkg/webhook/helm" - util3 "github.com/devtron-labs/devtron/util" + util2 "github.com/devtron-labs/devtron/util" "github.com/devtron-labs/devtron/util/argo" "github.com/devtron-labs/devtron/util/cron" "github.com/devtron-labs/devtron/util/rbac" @@ -167,11 +172,11 @@ func InitializeApp() (*App, error) { if err != nil { return nil, err } - config, err := sql.GetConfig() + sqlConfig, err := sql.GetConfig() if err != nil { return nil, err } - db, err := sql.NewDbConnection(config, sugaredLogger) + db, err := sql.NewDbConnection(sqlConfig, sugaredLogger) if err != nil { return nil, err } @@ -180,7 +185,6 @@ func InitializeApp() (*App, error) { mergeUtil := &util.MergeUtil{ Logger: sugaredLogger, } - ciArtifactRepositoryImpl := repository.NewCiArtifactRepositoryImpl(db, sugaredLogger) pipelineRepositoryImpl := pipelineConfig.NewPipelineRepositoryImpl(db, sugaredLogger) httpClient := util.NewHttpClient() eventClientConfig, err := client.GetEventClientConfig() @@ -226,24 +230,12 @@ func InitializeApp() (*App, error) { serviceClientImpl := cluster.NewServiceClientImpl(sugaredLogger, argoCDConnectionManagerImpl) v := informer.NewGlobalMapClusterNamespace() k8sInformerFactoryImpl := informer.NewK8sInformerFactoryImpl(sugaredLogger, v, runtimeConfig, k8sServiceImpl) - gitOpsConfigRepositoryImpl := repository.NewGitOpsConfigRepositoryImpl(sugaredLogger, db) defaultAuthPolicyRepositoryImpl := repository4.NewDefaultAuthPolicyRepositoryImpl(db, sugaredLogger) defaultAuthRoleRepositoryImpl := repository4.NewDefaultAuthRoleRepositoryImpl(db, sugaredLogger) userAuthRepositoryImpl := repository4.NewUserAuthRepositoryImpl(db, sugaredLogger, defaultAuthPolicyRepositoryImpl, defaultAuthRoleRepositoryImpl) userRepositoryImpl := repository4.NewUserRepositoryImpl(db, sugaredLogger) roleGroupRepositoryImpl := repository4.NewRoleGroupRepositoryImpl(db, sugaredLogger) - clusterServiceImplExtended := cluster2.NewClusterServiceImplExtended(clusterRepositoryImpl, environmentRepositoryImpl, grafanaClientImpl, sugaredLogger, installedAppRepositoryImpl, k8sServiceImpl, serviceClientImpl, k8sInformerFactoryImpl, gitOpsConfigRepositoryImpl, userAuthRepositoryImpl, userRepositoryImpl, roleGroupRepositoryImpl) - helmClientConfig, err := client3.GetConfig() - if err != nil { - return nil, err - } - helmAppClientImpl := client3.NewHelmAppClientImpl(sugaredLogger, helmClientConfig) - pumpImpl := connector.NewPumpImpl(sugaredLogger) - teamRepositoryImpl := team.NewTeamRepositoryImpl(db) - appRepositoryImpl := app.NewAppRepositoryImpl(db, sugaredLogger) - enforcerUtilHelmImpl := rbac.NewEnforcerUtilHelmImpl(sugaredLogger, clusterRepositoryImpl, teamRepositoryImpl, appRepositoryImpl, environmentRepositoryImpl, installedAppRepositoryImpl) - serverDataStoreServerDataStore := serverDataStore.InitServerDataStore() - appStoreApplicationVersionRepositoryImpl := appStoreDiscoverRepository.NewAppStoreApplicationVersionRepositoryImpl(sugaredLogger, db) + gitOpsConfigRepositoryImpl := repository.NewGitOpsConfigRepositoryImpl(sugaredLogger, db) k8sClient, err := client2.NewK8sClient(runtimeConfig) if err != nil { return nil, err @@ -258,7 +250,6 @@ func InitializeApp() (*App, error) { } apiTokenSecretStore := apiTokenAuth.InitApiTokenSecretStore() sessionManager := middleware.NewSessionManager(settings, dexConfig, apiTokenSecretStore) - loginService := middleware.NewUserLogin(sessionManager, k8sClient) rbacPolicyDataRepositoryImpl := repository4.NewRbacPolicyDataRepositoryImpl(sugaredLogger, db) rbacRoleDataRepositoryImpl := repository4.NewRbacRoleDataRepositoryImpl(sugaredLogger, db) rbacDataCacheFactoryImpl := repository4.NewRbacDataCacheFactoryImpl(sugaredLogger, rbacPolicyDataRepositoryImpl, rbacRoleDataRepositoryImpl) @@ -266,6 +257,24 @@ func InitializeApp() (*App, error) { userAuditRepositoryImpl := repository4.NewUserAuditRepositoryImpl(db) userAuditServiceImpl := user.NewUserAuditServiceImpl(sugaredLogger, userAuditRepositoryImpl) userServiceImpl := user.NewUserServiceImpl(userAuthRepositoryImpl, sugaredLogger, userRepositoryImpl, roleGroupRepositoryImpl, sessionManager, userCommonServiceImpl, userAuditServiceImpl) + globalEnvVariables, err := util2.GetGlobalEnvVariables() + if err != nil { + return nil, err + } + gitOpsConfigReadServiceImpl := config.NewGitOpsConfigReadServiceImpl(sugaredLogger, gitOpsConfigRepositoryImpl, userServiceImpl, globalEnvVariables) + clusterServiceImplExtended := cluster2.NewClusterServiceImplExtended(clusterRepositoryImpl, environmentRepositoryImpl, grafanaClientImpl, sugaredLogger, installedAppRepositoryImpl, k8sServiceImpl, serviceClientImpl, k8sInformerFactoryImpl, userAuthRepositoryImpl, userRepositoryImpl, roleGroupRepositoryImpl, gitOpsConfigReadServiceImpl) + helmClientConfig, err := client3.GetConfig() + if err != nil { + return nil, err + } + helmAppClientImpl := client3.NewHelmAppClientImpl(sugaredLogger, helmClientConfig) + pumpImpl := connector.NewPumpImpl(sugaredLogger) + teamRepositoryImpl := team.NewTeamRepositoryImpl(db) + appRepositoryImpl := app.NewAppRepositoryImpl(db, sugaredLogger) + enforcerUtilHelmImpl := rbac.NewEnforcerUtilHelmImpl(sugaredLogger, clusterRepositoryImpl, teamRepositoryImpl, appRepositoryImpl, environmentRepositoryImpl, installedAppRepositoryImpl) + serverDataStoreServerDataStore := serverDataStore.InitServerDataStore() + appStoreApplicationVersionRepositoryImpl := appStoreDiscoverRepository.NewAppStoreApplicationVersionRepositoryImpl(sugaredLogger, db) + loginService := middleware.NewUserLogin(sessionManager, k8sClient) userAuthServiceImpl := user.NewUserAuthServiceImpl(userAuthRepositoryImpl, sessionManager, loginService, sugaredLogger, userRepositoryImpl, roleGroupRepositoryImpl, userServiceImpl) environmentServiceImpl := cluster2.NewEnvironmentServiceImpl(environmentRepositoryImpl, clusterServiceImplExtended, sugaredLogger, k8sServiceImpl, k8sInformerFactoryImpl, userAuthServiceImpl, attributesRepositoryImpl) helmReleaseConfig, err := client3.GetHelmReleaseConfig() @@ -294,43 +303,45 @@ func InitializeApp() (*App, error) { cdWorkflowRepositoryImpl := pipelineConfig.NewCdWorkflowRepositoryImpl(db, sugaredLogger) ciWorkflowRepositoryImpl := pipelineConfig.NewCiWorkflowRepositoryImpl(db, sugaredLogger) ciPipelineMaterialRepositoryImpl := pipelineConfig.NewCiPipelineMaterialRepositoryImpl(db, sugaredLogger) + ciArtifactRepositoryImpl := repository.NewCiArtifactRepositoryImpl(db, sugaredLogger) eventSimpleFactoryImpl := client.NewEventSimpleFactoryImpl(sugaredLogger, cdWorkflowRepositoryImpl, pipelineOverrideRepositoryImpl, ciWorkflowRepositoryImpl, ciPipelineMaterialRepositoryImpl, ciPipelineRepositoryImpl, pipelineRepositoryImpl, userRepositoryImpl, ciArtifactRepositoryImpl) applicationServiceClientImpl := application.NewApplicationClientImpl(sugaredLogger, argoCDConnectionManagerImpl) - acdAuthConfig, err := util2.GetACDAuthConfig() - if err != nil { - return nil, err - } - tokenCache := util2.NewTokenCache(sugaredLogger, acdAuthConfig, userAuthServiceImpl) - syncedEnforcer := casbin.Create() - enforcerImpl := casbin.NewEnforcerImpl(syncedEnforcer, sessionManager, sugaredLogger) - enforcerUtilImpl := rbac.NewEnforcerUtilImpl(sugaredLogger, teamRepositoryImpl, appRepositoryImpl, environmentRepositoryImpl, pipelineRepositoryImpl, ciPipelineRepositoryImpl, clusterRepositoryImpl, enforcerImpl) - appListingRepositoryQueryBuilder := helper.NewAppListingRepositoryQueryBuilder(sugaredLogger) - appListingRepositoryImpl := repository.NewAppListingRepositoryImpl(sugaredLogger, db, appListingRepositoryQueryBuilder, environmentRepositoryImpl) - pipelineConfigRepositoryImpl := chartConfig.NewPipelineConfigRepository(db) configMapRepositoryImpl := chartConfig.NewConfigMapRepositoryImpl(sugaredLogger, db) - appLevelMetricsRepositoryImpl := repository.NewAppLevelMetricsRepositoryImpl(db, sugaredLogger) - envLevelAppMetricsRepositoryImpl := repository.NewEnvLevelAppMetricsRepositoryImpl(db, sugaredLogger) chartRepositoryImpl := chartRepoRepository.NewChartRepository(db) dockerArtifactStoreRepositoryImpl := repository5.NewDockerArtifactStoreRepositoryImpl(db) gitProviderRepositoryImpl := repository.NewGitProviderRepositoryImpl(db) - commonServiceImpl := commonService.NewCommonServiceImpl(sugaredLogger, chartRepositoryImpl, envConfigOverrideRepositoryImpl, gitOpsConfigRepositoryImpl, dockerArtifactStoreRepositoryImpl, attributesRepositoryImpl, gitProviderRepositoryImpl, environmentRepositoryImpl, teamRepositoryImpl, appRepositoryImpl) - imageScanDeployInfoRepositoryImpl := security.NewImageScanDeployInfoRepositoryImpl(db, sugaredLogger) - imageScanHistoryRepositoryImpl := security.NewImageScanHistoryRepositoryImpl(db, sugaredLogger) - argoK8sClientImpl := argocdServer.NewArgoK8sClientImpl(sugaredLogger) - gitCliUtil := util.NewGitCliUtil(sugaredLogger) - gitFactory, err := util.NewGitFactory(sugaredLogger, gitOpsConfigRepositoryImpl, gitCliUtil) + commonServiceImpl := commonService.NewCommonServiceImpl(sugaredLogger, chartRepositoryImpl, envConfigOverrideRepositoryImpl, dockerArtifactStoreRepositoryImpl, attributesRepositoryImpl, gitProviderRepositoryImpl, environmentRepositoryImpl, teamRepositoryImpl, appRepositoryImpl) + chartTemplateServiceImpl := util.NewChartTemplateServiceImpl(sugaredLogger) + devtronSecretConfig, err := util2.GetDevtronSecretName() if err != nil { return nil, err } - pipelineStrategyHistoryRepositoryImpl := repository6.NewPipelineStrategyHistoryRepositoryImpl(sugaredLogger, db) - pipelineStrategyHistoryServiceImpl := history.NewPipelineStrategyHistoryServiceImpl(sugaredLogger, pipelineStrategyHistoryRepositoryImpl, userServiceImpl) - configMapHistoryRepositoryImpl := repository6.NewConfigMapHistoryRepositoryImpl(sugaredLogger, db) - scopedVariableRepositoryImpl := repository7.NewScopedVariableRepository(db, sugaredLogger) + versionServiceImpl := argocdServer.NewVersionServiceImpl(sugaredLogger, argoCDConnectionManagerImpl) + argoUserServiceImpl, err := argo.NewArgoUserServiceImpl(sugaredLogger, clusterServiceImplExtended, devtronSecretConfig, runtimeConfig, argoCDConnectionManagerImpl, versionServiceImpl, k8sServiceImpl, gitOpsConfigReadServiceImpl) + if err != nil { + return nil, err + } + pipelineStatusTimelineRepositoryImpl := pipelineConfig.NewPipelineStatusTimelineRepositoryImpl(db, sugaredLogger) + pipelineStatusTimelineResourcesRepositoryImpl := pipelineConfig.NewPipelineStatusTimelineResourcesRepositoryImpl(db, sugaredLogger) + pipelineStatusTimelineResourcesServiceImpl := status.NewPipelineStatusTimelineResourcesServiceImpl(db, sugaredLogger, pipelineStatusTimelineResourcesRepositoryImpl) + pipelineStatusSyncDetailRepositoryImpl := pipelineConfig.NewPipelineStatusSyncDetailRepositoryImpl(db, sugaredLogger) + pipelineStatusSyncDetailServiceImpl := status.NewPipelineStatusSyncDetailServiceImpl(sugaredLogger, pipelineStatusSyncDetailRepositoryImpl) + installedAppVersionHistoryRepositoryImpl := repository3.NewInstalledAppVersionHistoryRepositoryImpl(sugaredLogger, db) + pipelineStatusTimelineServiceImpl := status.NewPipelineStatusTimelineServiceImpl(sugaredLogger, pipelineStatusTimelineRepositoryImpl, cdWorkflowRepositoryImpl, userServiceImpl, pipelineStatusTimelineResourcesServiceImpl, pipelineStatusSyncDetailServiceImpl, installedAppRepositoryImpl, installedAppVersionHistoryRepositoryImpl) + appServiceConfig, err := app2.GetAppServiceConfig() + if err != nil { + return nil, err + } + syncedEnforcer := casbin.Create() + enforcerImpl := casbin.NewEnforcerImpl(syncedEnforcer, sessionManager, sugaredLogger) + enforcerUtilImpl := rbac.NewEnforcerUtilImpl(sugaredLogger, teamRepositoryImpl, appRepositoryImpl, environmentRepositoryImpl, pipelineRepositoryImpl, ciPipelineRepositoryImpl, clusterRepositoryImpl, enforcerImpl) + appStatusServiceImpl := appStatus2.NewAppStatusServiceImpl(appStatusRepositoryImpl, sugaredLogger, enforcerImpl, enforcerUtilImpl) + scopedVariableRepositoryImpl := repository6.NewScopedVariableRepository(db, sugaredLogger) qualifiersMappingRepositoryImpl, err := resourceQualifiers.NewQualifiersMappingRepositoryImpl(db, sugaredLogger) if err != nil { return nil, err } - devtronResourceSearchableKeyRepositoryImpl := repository8.NewDevtronResourceSearchableKeyRepositoryImpl(sugaredLogger, db) + devtronResourceSearchableKeyRepositoryImpl := repository7.NewDevtronResourceSearchableKeyRepositoryImpl(sugaredLogger, db) devtronResourceSearchableKeyServiceImpl, err := devtronResource.NewDevtronResourceSearchableKeyServiceImpl(sugaredLogger, devtronResourceSearchableKeyRepositoryImpl) if err != nil { return nil, err @@ -343,9 +354,9 @@ func InitializeApp() (*App, error) { if err != nil { return nil, err } - variableEntityMappingRepositoryImpl := repository7.NewVariableEntityMappingRepository(sugaredLogger, db) + variableEntityMappingRepositoryImpl := repository6.NewVariableEntityMappingRepository(sugaredLogger, db) variableEntityMappingServiceImpl := variables.NewVariableEntityMappingServiceImpl(variableEntityMappingRepositoryImpl, sugaredLogger) - variableSnapshotHistoryRepositoryImpl := repository7.NewVariableSnapshotHistoryRepository(sugaredLogger, db) + variableSnapshotHistoryRepositoryImpl := repository6.NewVariableSnapshotHistoryRepository(sugaredLogger, db) variableSnapshotHistoryServiceImpl := variables.NewVariableSnapshotHistoryServiceImpl(variableSnapshotHistoryRepositoryImpl, sugaredLogger) variableTemplateParserImpl, err := parsers.NewVariableTemplateParserImpl(sugaredLogger) if err != nil { @@ -355,81 +366,22 @@ func InitializeApp() (*App, error) { if err != nil { return nil, err } - configMapHistoryServiceImpl := history.NewConfigMapHistoryServiceImpl(sugaredLogger, configMapHistoryRepositoryImpl, pipelineRepositoryImpl, configMapRepositoryImpl, userServiceImpl, scopedVariableCMCSManagerImpl) - deploymentTemplateHistoryRepositoryImpl := repository6.NewDeploymentTemplateHistoryRepositoryImpl(sugaredLogger, db) - chartRefRepositoryImpl := chartRepoRepository.NewChartRefRepositoryImpl(db) - scopedVariableManagerImpl, err := variables.NewScopedVariableManagerImpl(sugaredLogger, scopedVariableServiceImpl, variableEntityMappingServiceImpl, variableSnapshotHistoryServiceImpl, variableTemplateParserImpl) - if err != nil { - return nil, err - } - deploymentTemplateHistoryServiceImpl := history.NewDeploymentTemplateHistoryServiceImpl(sugaredLogger, deploymentTemplateHistoryRepositoryImpl, pipelineRepositoryImpl, chartRepositoryImpl, chartRefRepositoryImpl, envLevelAppMetricsRepositoryImpl, appLevelMetricsRepositoryImpl, userServiceImpl, cdWorkflowRepositoryImpl, scopedVariableManagerImpl) - chartWorkingDir := _wireChartWorkingDirValue - globalEnvVariables, err := util3.GetGlobalEnvVariables() + acdConfig, err := argocdServer.GetACDDeploymentConfig() if err != nil { return nil, err } - chartTemplateServiceImpl := util.NewChartTemplateServiceImpl(sugaredLogger, chartWorkingDir, httpClient, gitFactory, globalEnvVariables, gitOpsConfigRepositoryImpl, userRepositoryImpl, chartRepositoryImpl) - refChartDir := _wireRefChartDirValue - chartRepoRepositoryImpl := chartRepoRepository.NewChartRepoRepositoryImpl(db) - defaultChart := _wireDefaultChartValue + chartRefRepositoryImpl := chartRepoRepository.NewChartRefRepositoryImpl(db) utilMergeUtil := util.MergeUtil{ Logger: sugaredLogger, } - repositoryServiceClientImpl := repository9.NewServiceClientImpl(sugaredLogger, argoCDConnectionManagerImpl) - chartServiceImpl := chart.NewChartServiceImpl(chartRepositoryImpl, sugaredLogger, chartTemplateServiceImpl, chartRepoRepositoryImpl, appRepositoryImpl, refChartDir, defaultChart, utilMergeUtil, repositoryServiceClientImpl, chartRefRepositoryImpl, envConfigOverrideRepositoryImpl, pipelineConfigRepositoryImpl, configMapRepositoryImpl, environmentRepositoryImpl, pipelineRepositoryImpl, appLevelMetricsRepositoryImpl, envLevelAppMetricsRepositoryImpl, httpClient, deploymentTemplateHistoryServiceImpl, scopedVariableManagerImpl) - devtronSecretConfig, err := util3.GetDevtronSecretName() + chartRefServiceImpl := chartRef.NewChartRefServiceImpl(sugaredLogger, chartRefRepositoryImpl, chartTemplateServiceImpl, utilMergeUtil) + gitCliUtil := git.NewGitCliUtil(sugaredLogger) + gitFactory, err := git.NewGitFactory(sugaredLogger, gitOpsConfigRepositoryImpl, gitCliUtil) if err != nil { return nil, err } - versionServiceImpl := argocdServer.NewVersionServiceImpl(sugaredLogger, argoCDConnectionManagerImpl) - argoUserServiceImpl, err := argo.NewArgoUserServiceImpl(sugaredLogger, clusterServiceImplExtended, devtronSecretConfig, runtimeConfig, gitOpsConfigRepositoryImpl, argoCDConnectionManagerImpl, versionServiceImpl, k8sServiceImpl) - if err != nil { - return nil, err - } - pipelineStatusTimelineRepositoryImpl := pipelineConfig.NewPipelineStatusTimelineRepositoryImpl(db, sugaredLogger) - appLabelRepositoryImpl := pipelineConfig.NewAppLabelRepositoryImpl(db) - genericNoteRepositoryImpl := repository10.NewGenericNoteRepositoryImpl(db) - genericNoteHistoryRepositoryImpl := repository10.NewGenericNoteHistoryRepositoryImpl(db) - genericNoteHistoryServiceImpl := genericNotes.NewGenericNoteHistoryServiceImpl(genericNoteHistoryRepositoryImpl, sugaredLogger) - genericNoteServiceImpl := genericNotes.NewGenericNoteServiceImpl(genericNoteRepositoryImpl, genericNoteHistoryServiceImpl, userRepositoryImpl, sugaredLogger) - materialRepositoryImpl := pipelineConfig.NewMaterialRepositoryImpl(db) - appCrudOperationServiceImpl := app2.NewAppCrudOperationServiceImpl(appLabelRepositoryImpl, sugaredLogger, appRepositoryImpl, userRepositoryImpl, installedAppRepositoryImpl, genericNoteServiceImpl, materialRepositoryImpl) - dockerRegistryIpsConfigRepositoryImpl := repository5.NewDockerRegistryIpsConfigRepositoryImpl(db) - ciTemplateOverrideRepositoryImpl := pipelineConfig.NewCiTemplateOverrideRepositoryImpl(db, sugaredLogger) - dockerRegistryIpsConfigServiceImpl := dockerRegistry.NewDockerRegistryIpsConfigServiceImpl(sugaredLogger, dockerRegistryIpsConfigRepositoryImpl, k8sServiceImpl, clusterServiceImplExtended, ciPipelineRepositoryImpl, dockerArtifactStoreRepositoryImpl, ciTemplateOverrideRepositoryImpl) - pipelineStatusTimelineResourcesRepositoryImpl := pipelineConfig.NewPipelineStatusTimelineResourcesRepositoryImpl(db, sugaredLogger) - pipelineStatusTimelineResourcesServiceImpl := status.NewPipelineStatusTimelineResourcesServiceImpl(db, sugaredLogger, pipelineStatusTimelineResourcesRepositoryImpl) - pipelineStatusSyncDetailRepositoryImpl := pipelineConfig.NewPipelineStatusSyncDetailRepositoryImpl(db, sugaredLogger) - pipelineStatusSyncDetailServiceImpl := status.NewPipelineStatusSyncDetailServiceImpl(sugaredLogger, pipelineStatusSyncDetailRepositoryImpl) - installedAppVersionHistoryRepositoryImpl := repository3.NewInstalledAppVersionHistoryRepositoryImpl(sugaredLogger, db) - pipelineStatusTimelineServiceImpl := status.NewPipelineStatusTimelineServiceImpl(sugaredLogger, pipelineStatusTimelineRepositoryImpl, cdWorkflowRepositoryImpl, userServiceImpl, pipelineStatusTimelineResourcesServiceImpl, pipelineStatusSyncDetailServiceImpl, installedAppRepositoryImpl, installedAppVersionHistoryRepositoryImpl) - appServiceConfig, err := app2.GetAppServiceConfig() - if err != nil { - return nil, err - } - appStatusServiceImpl := appStatus2.NewAppStatusServiceImpl(appStatusRepositoryImpl, sugaredLogger, enforcerImpl, enforcerUtilImpl) - chartGroupDeploymentRepositoryImpl := repository11.NewChartGroupDeploymentRepositoryImpl(db, sugaredLogger) - clusterInstalledAppsRepositoryImpl := repository3.NewClusterInstalledAppsRepositoryImpl(db, sugaredLogger) - refChartProxyDir := _wireRefChartProxyDirValue - appStoreDeploymentCommonServiceImpl := appStoreDeploymentCommon.NewAppStoreDeploymentCommonServiceImpl(sugaredLogger, installedAppRepositoryImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl, chartTemplateServiceImpl, refChartProxyDir, gitFactory, gitOpsConfigRepositoryImpl) - ociRegistryConfigRepositoryImpl := repository5.NewOCIRegistryConfigRepositoryImpl(db) - appStoreDeploymentHelmServiceImpl := appStoreDeploymentTool.NewAppStoreDeploymentHelmServiceImpl(sugaredLogger, helmAppServiceImpl, appStoreApplicationVersionRepositoryImpl, helmAppClientImpl, installedAppRepositoryImpl, appStoreDeploymentCommonServiceImpl, ociRegistryConfigRepositoryImpl) - acdConfig, err := argocdServer.GetACDDeploymentConfig() - if err != nil { - return nil, err - } - argoClientWrapperServiceImpl := argocdServer.NewArgoClientWrapperServiceImpl(sugaredLogger, applicationServiceClientImpl, acdConfig) - appStoreDeploymentFullModeServiceImpl := appStoreDeploymentFullMode.NewAppStoreDeploymentFullModeServiceImpl(sugaredLogger, chartTemplateServiceImpl, repositoryServiceClientImpl, applicationServiceClientImpl, argoK8sClientImpl, acdAuthConfig, argoUserServiceImpl, pipelineStatusTimelineServiceImpl, appStoreDeploymentCommonServiceImpl, argoClientWrapperServiceImpl, pubSubClientServiceImpl, installedAppVersionHistoryRepositoryImpl, acdConfig) - appStoreDeploymentArgoCdServiceImpl := appStoreDeploymentTool.NewAppStoreDeploymentArgoCdServiceImpl(sugaredLogger, appStoreDeploymentFullModeServiceImpl, applicationServiceClientImpl, chartGroupDeploymentRepositoryImpl, installedAppRepositoryImpl, installedAppVersionHistoryRepositoryImpl, gitFactory, appStoreDeploymentCommonServiceImpl, helmAppServiceImpl, appStatusServiceImpl, pipelineStatusTimelineServiceImpl, pipelineStatusTimelineRepositoryImpl, userServiceImpl, appStoreApplicationVersionRepositoryImpl, argoClientWrapperServiceImpl, acdConfig) - deploymentServiceTypeConfig, err := service.GetDeploymentServiceTypeConfig() - if err != nil { - return nil, err - } - appStoreDeploymentServiceImpl := service.NewAppStoreDeploymentServiceImpl(sugaredLogger, installedAppRepositoryImpl, chartGroupDeploymentRepositoryImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl, clusterInstalledAppsRepositoryImpl, appRepositoryImpl, appStoreDeploymentHelmServiceImpl, appStoreDeploymentArgoCdServiceImpl, environmentServiceImpl, clusterServiceImplExtended, helmAppServiceImpl, appStoreDeploymentCommonServiceImpl, installedAppVersionHistoryRepositoryImpl, gitOpsConfigRepositoryImpl, attributesServiceImpl, deploymentServiceTypeConfig, chartTemplateServiceImpl, acdConfig) - k8sCommonServiceImpl := k8s2.NewK8sCommonServiceImpl(sugaredLogger, k8sServiceImpl, clusterServiceImplExtended) - manifestPushConfigRepositoryImpl := repository12.NewManifestPushConfigRepository(sugaredLogger, db) - gitOpsManifestPushServiceImpl := app2.NewGitOpsManifestPushServiceImpl(sugaredLogger, chartTemplateServiceImpl, chartServiceImpl, gitOpsConfigRepositoryImpl, gitFactory, pipelineStatusTimelineServiceImpl, pipelineStatusTimelineRepositoryImpl, acdConfig) - appServiceImpl := app2.NewAppService(envConfigOverrideRepositoryImpl, pipelineOverrideRepositoryImpl, mergeUtil, sugaredLogger, ciArtifactRepositoryImpl, pipelineRepositoryImpl, eventRESTClientImpl, eventSimpleFactoryImpl, applicationServiceClientImpl, tokenCache, acdAuthConfig, enforcerImpl, enforcerUtilImpl, userServiceImpl, appListingRepositoryImpl, appRepositoryImpl, environmentRepositoryImpl, pipelineConfigRepositoryImpl, configMapRepositoryImpl, appLevelMetricsRepositoryImpl, envLevelAppMetricsRepositoryImpl, chartRepositoryImpl, ciPipelineMaterialRepositoryImpl, cdWorkflowRepositoryImpl, commonServiceImpl, imageScanDeployInfoRepositoryImpl, imageScanHistoryRepositoryImpl, argoK8sClientImpl, gitFactory, pipelineStrategyHistoryServiceImpl, configMapHistoryServiceImpl, deploymentTemplateHistoryServiceImpl, chartTemplateServiceImpl, refChartDir, chartRefRepositoryImpl, chartServiceImpl, helmAppClientImpl, argoUserServiceImpl, pipelineStatusTimelineRepositoryImpl, appCrudOperationServiceImpl, configMapHistoryRepositoryImpl, pipelineStrategyHistoryRepositoryImpl, deploymentTemplateHistoryRepositoryImpl, dockerRegistryIpsConfigServiceImpl, pipelineStatusTimelineResourcesServiceImpl, pipelineStatusSyncDetailServiceImpl, pipelineStatusTimelineServiceImpl, appServiceConfig, gitOpsConfigRepositoryImpl, appStatusServiceImpl, installedAppRepositoryImpl, appStoreDeploymentServiceImpl, k8sCommonServiceImpl, installedAppVersionHistoryRepositoryImpl, globalEnvVariables, helmAppServiceImpl, manifestPushConfigRepositoryImpl, gitOpsManifestPushServiceImpl, argoClientWrapperServiceImpl, scopedVariableCMCSManagerImpl, acdConfig) + gitOperationServiceImpl := git.NewGitOperationServiceImpl(sugaredLogger, gitFactory, gitOpsConfigReadServiceImpl, chartTemplateServiceImpl) + appServiceImpl := app2.NewAppService(envConfigOverrideRepositoryImpl, pipelineOverrideRepositoryImpl, mergeUtil, sugaredLogger, pipelineRepositoryImpl, eventRESTClientImpl, eventSimpleFactoryImpl, applicationServiceClientImpl, appRepositoryImpl, configMapRepositoryImpl, chartRepositoryImpl, cdWorkflowRepositoryImpl, commonServiceImpl, chartTemplateServiceImpl, argoUserServiceImpl, pipelineStatusTimelineRepositoryImpl, pipelineStatusTimelineResourcesServiceImpl, pipelineStatusSyncDetailServiceImpl, pipelineStatusTimelineServiceImpl, appServiceConfig, appStatusServiceImpl, installedAppRepositoryImpl, installedAppVersionHistoryRepositoryImpl, globalEnvVariables, scopedVariableCMCSManagerImpl, acdConfig, chartRefServiceImpl, gitOpsConfigReadServiceImpl, gitOperationServiceImpl) validate, err := util.IntValidator() if err != nil { return nil, err @@ -442,17 +394,22 @@ func InitializeApp() (*App, error) { globalCMCSServiceImpl := pipeline.NewGlobalCMCSServiceImpl(sugaredLogger, globalCMCSRepositoryImpl) argoWorkflowExecutorImpl := executors.NewArgoWorkflowExecutorImpl(sugaredLogger) systemWorkflowExecutorImpl := executors.NewSystemWorkflowExecutorImpl(sugaredLogger, k8sServiceImpl) + k8sCommonServiceImpl := k8s2.NewK8sCommonServiceImpl(sugaredLogger, k8sServiceImpl, clusterServiceImplExtended) workflowServiceImpl, err := pipeline.NewWorkflowServiceImpl(sugaredLogger, environmentRepositoryImpl, ciCdConfig, appServiceImpl, globalCMCSServiceImpl, argoWorkflowExecutorImpl, k8sServiceImpl, systemWorkflowExecutorImpl, k8sCommonServiceImpl) if err != nil { return nil, err } + materialRepositoryImpl := pipelineConfig.NewMaterialRepositoryImpl(db) deploymentGroupRepositoryImpl := repository.NewDeploymentGroupRepositoryImpl(sugaredLogger, db) cvePolicyRepositoryImpl := security.NewPolicyRepositoryImpl(db) imageScanResultRepositoryImpl := security.NewImageScanResultRepositoryImpl(db, sugaredLogger) appWorkflowRepositoryImpl := appWorkflow.NewAppWorkflowRepositoryImpl(sugaredLogger, db) - prePostCdScriptHistoryRepositoryImpl := repository6.NewPrePostCdScriptHistoryRepositoryImpl(sugaredLogger, db) + prePostCdScriptHistoryRepositoryImpl := repository8.NewPrePostCdScriptHistoryRepositoryImpl(sugaredLogger, db) + configMapHistoryRepositoryImpl := repository8.NewConfigMapHistoryRepositoryImpl(sugaredLogger, db) + configMapHistoryServiceImpl := history.NewConfigMapHistoryServiceImpl(sugaredLogger, configMapHistoryRepositoryImpl, pipelineRepositoryImpl, configMapRepositoryImpl, userServiceImpl, scopedVariableCMCSManagerImpl) prePostCdScriptHistoryServiceImpl := history.NewPrePostCdScriptHistoryServiceImpl(sugaredLogger, prePostCdScriptHistoryRepositoryImpl, configMapRepositoryImpl, configMapHistoryServiceImpl) ciTemplateRepositoryImpl := pipelineConfig.NewCiTemplateRepositoryImpl(db, sugaredLogger) + appLabelRepositoryImpl := pipelineConfig.NewAppLabelRepositoryImpl(db) clientConfig, err := gitSensor.GetConfig() if err != nil { return nil, err @@ -461,39 +418,70 @@ func InitializeApp() (*App, error) { if err != nil { return nil, err } - pipelineStageRepositoryImpl := repository12.NewPipelineStageRepository(sugaredLogger, db) - globalPluginRepositoryImpl := repository13.NewGlobalPluginRepository(sugaredLogger, db) + pipelineStageRepositoryImpl := repository9.NewPipelineStageRepository(sugaredLogger, db) + globalPluginRepositoryImpl := repository10.NewGlobalPluginRepository(sugaredLogger, db) + scopedVariableManagerImpl, err := variables.NewScopedVariableManagerImpl(sugaredLogger, scopedVariableServiceImpl, variableEntityMappingServiceImpl, variableSnapshotHistoryServiceImpl, variableTemplateParserImpl) + if err != nil { + return nil, err + } pipelineStageServiceImpl := pipeline.NewPipelineStageService(sugaredLogger, pipelineStageRepositoryImpl, globalPluginRepositoryImpl, pipelineRepositoryImpl, scopedVariableManagerImpl) globalPluginServiceImpl := plugin.NewGlobalPluginService(sugaredLogger, globalPluginRepositoryImpl, pipelineStageRepositoryImpl) + dockerRegistryIpsConfigRepositoryImpl := repository5.NewDockerRegistryIpsConfigRepositoryImpl(db) + ociRegistryConfigRepositoryImpl := repository5.NewOCIRegistryConfigRepositoryImpl(db) dockerRegistryConfigImpl := pipeline.NewDockerRegistryConfigImpl(sugaredLogger, helmAppServiceImpl, dockerArtifactStoreRepositoryImpl, dockerRegistryIpsConfigRepositoryImpl, ociRegistryConfigRepositoryImpl) imageTagRepositoryImpl := repository.NewImageTagRepository(db, sugaredLogger) customTagServiceImpl := pipeline.NewCustomTagService(sugaredLogger, imageTagRepositoryImpl) pluginInputVariableParserImpl := pipeline.NewPluginInputVariableParserImpl(sugaredLogger, dockerRegistryConfigImpl, customTagServiceImpl) + deploymentTemplateHistoryRepositoryImpl := repository8.NewDeploymentTemplateHistoryRepositoryImpl(sugaredLogger, db) + appLevelMetricsRepositoryImpl := repository11.NewAppLevelMetricsRepositoryImpl(db, sugaredLogger) + envLevelAppMetricsRepositoryImpl := repository11.NewEnvLevelAppMetricsRepositoryImpl(db, sugaredLogger) + deployedAppMetricsServiceImpl := deployedAppMetrics.NewDeployedAppMetricsServiceImpl(sugaredLogger, appLevelMetricsRepositoryImpl, envLevelAppMetricsRepositoryImpl, chartRefServiceImpl) + deploymentTemplateHistoryServiceImpl := history.NewDeploymentTemplateHistoryServiceImpl(sugaredLogger, deploymentTemplateHistoryRepositoryImpl, pipelineRepositoryImpl, chartRepositoryImpl, userServiceImpl, cdWorkflowRepositoryImpl, scopedVariableManagerImpl, deployedAppMetricsServiceImpl, chartRefServiceImpl) + pipelineStrategyHistoryRepositoryImpl := repository8.NewPipelineStrategyHistoryRepositoryImpl(sugaredLogger, db) + pipelineStrategyHistoryServiceImpl := history.NewPipelineStrategyHistoryServiceImpl(sugaredLogger, pipelineStrategyHistoryRepositoryImpl, userServiceImpl) + manifestPushConfigRepositoryImpl := repository9.NewManifestPushConfigRepository(sugaredLogger, db) + gitOpsManifestPushServiceImpl := app2.NewGitOpsManifestPushServiceImpl(sugaredLogger, pipelineStatusTimelineServiceImpl, pipelineStatusTimelineRepositoryImpl, acdConfig, chartRefServiceImpl, gitOpsConfigReadServiceImpl, gitOperationServiceImpl) + imageScanHistoryRepositoryImpl := security.NewImageScanHistoryRepositoryImpl(db, sugaredLogger) + imageScanDeployInfoRepositoryImpl := security.NewImageScanDeployInfoRepositoryImpl(db, sugaredLogger) + genericNoteRepositoryImpl := repository12.NewGenericNoteRepositoryImpl(db) + genericNoteHistoryRepositoryImpl := repository12.NewGenericNoteHistoryRepositoryImpl(db) + genericNoteHistoryServiceImpl := genericNotes.NewGenericNoteHistoryServiceImpl(genericNoteHistoryRepositoryImpl, sugaredLogger) + genericNoteServiceImpl := genericNotes.NewGenericNoteServiceImpl(genericNoteRepositoryImpl, genericNoteHistoryServiceImpl, userRepositoryImpl, sugaredLogger) + appCrudOperationServiceImpl := app2.NewAppCrudOperationServiceImpl(appLabelRepositoryImpl, sugaredLogger, appRepositoryImpl, userRepositoryImpl, installedAppRepositoryImpl, genericNoteServiceImpl, materialRepositoryImpl) + pipelineConfigRepositoryImpl := chartConfig.NewPipelineConfigRepository(db) + ciTemplateOverrideRepositoryImpl := pipelineConfig.NewCiTemplateOverrideRepositoryImpl(db, sugaredLogger) + dockerRegistryIpsConfigServiceImpl := dockerRegistry.NewDockerRegistryIpsConfigServiceImpl(sugaredLogger, dockerRegistryIpsConfigRepositoryImpl, k8sServiceImpl, clusterServiceImplExtended, ciPipelineRepositoryImpl, dockerArtifactStoreRepositoryImpl, ciTemplateOverrideRepositoryImpl) + argoK8sClientImpl := argocdServer.NewArgoK8sClientImpl(sugaredLogger) + repositoryServiceClientImpl := repository13.NewServiceClientImpl(sugaredLogger, argoCDConnectionManagerImpl) + argoClientWrapperServiceImpl := argocdServer.NewArgoClientWrapperServiceImpl(sugaredLogger, applicationServiceClientImpl, acdConfig, repositoryServiceClientImpl) pipelineConfigListenerServiceImpl := pipeline.NewPipelineConfigListenerServiceImpl(sugaredLogger) imageDigestPolicyServiceImpl := imageDigestPolicy.NewImageDigestPolicyServiceImpl(sugaredLogger, qualifierMappingServiceImpl, devtronResourceSearchableKeyServiceImpl) - workflowDagExecutorImpl := pipeline.NewWorkflowDagExecutorImpl(sugaredLogger, pipelineRepositoryImpl, cdWorkflowRepositoryImpl, pubSubClientServiceImpl, appServiceImpl, workflowServiceImpl, ciArtifactRepositoryImpl, ciPipelineRepositoryImpl, materialRepositoryImpl, pipelineOverrideRepositoryImpl, userServiceImpl, deploymentGroupRepositoryImpl, environmentRepositoryImpl, enforcerImpl, enforcerUtilImpl, eventSimpleFactoryImpl, eventRESTClientImpl, cvePolicyRepositoryImpl, imageScanResultRepositoryImpl, appWorkflowRepositoryImpl, prePostCdScriptHistoryServiceImpl, argoUserServiceImpl, pipelineStatusTimelineRepositoryImpl, pipelineStatusTimelineServiceImpl, ciTemplateRepositoryImpl, ciWorkflowRepositoryImpl, appLabelRepositoryImpl, clientImpl, pipelineStageServiceImpl, k8sCommonServiceImpl, globalPluginServiceImpl, pluginInputVariableParserImpl, scopedVariableCMCSManagerImpl, deploymentTemplateHistoryServiceImpl, configMapHistoryServiceImpl, pipelineStrategyHistoryServiceImpl, manifestPushConfigRepositoryImpl, gitOpsManifestPushServiceImpl, ciPipelineMaterialRepositoryImpl, imageScanHistoryRepositoryImpl, imageScanDeployInfoRepositoryImpl, appCrudOperationServiceImpl, pipelineConfigRepositoryImpl, dockerRegistryIpsConfigServiceImpl, chartRepositoryImpl, chartTemplateServiceImpl, pipelineStrategyHistoryRepositoryImpl, appRepositoryImpl, deploymentTemplateHistoryRepositoryImpl, argoK8sClientImpl, configMapRepositoryImpl, configMapHistoryRepositoryImpl, refChartDir, helmAppServiceImpl, helmAppClientImpl, chartRefRepositoryImpl, envConfigOverrideRepositoryImpl, appLevelMetricsRepositoryImpl, envLevelAppMetricsRepositoryImpl, mergeUtil, gitOpsConfigRepositoryImpl, gitFactory, applicationServiceClientImpl, argoClientWrapperServiceImpl, pipelineConfigListenerServiceImpl, customTagServiceImpl, acdConfig, imageDigestPolicyServiceImpl) + workflowDagExecutorImpl := pipeline.NewWorkflowDagExecutorImpl(sugaredLogger, pipelineRepositoryImpl, cdWorkflowRepositoryImpl, pubSubClientServiceImpl, appServiceImpl, workflowServiceImpl, ciArtifactRepositoryImpl, ciPipelineRepositoryImpl, materialRepositoryImpl, pipelineOverrideRepositoryImpl, userServiceImpl, deploymentGroupRepositoryImpl, environmentRepositoryImpl, enforcerUtilImpl, eventSimpleFactoryImpl, eventRESTClientImpl, cvePolicyRepositoryImpl, imageScanResultRepositoryImpl, appWorkflowRepositoryImpl, prePostCdScriptHistoryServiceImpl, argoUserServiceImpl, pipelineStatusTimelineRepositoryImpl, pipelineStatusTimelineServiceImpl, ciTemplateRepositoryImpl, ciWorkflowRepositoryImpl, appLabelRepositoryImpl, clientImpl, pipelineStageServiceImpl, k8sCommonServiceImpl, globalPluginServiceImpl, pluginInputVariableParserImpl, scopedVariableCMCSManagerImpl, deploymentTemplateHistoryServiceImpl, configMapHistoryServiceImpl, pipelineStrategyHistoryServiceImpl, manifestPushConfigRepositoryImpl, gitOpsManifestPushServiceImpl, ciPipelineMaterialRepositoryImpl, imageScanHistoryRepositoryImpl, imageScanDeployInfoRepositoryImpl, appCrudOperationServiceImpl, pipelineConfigRepositoryImpl, dockerRegistryIpsConfigServiceImpl, chartRepositoryImpl, chartTemplateServiceImpl, pipelineStrategyHistoryRepositoryImpl, deploymentTemplateHistoryRepositoryImpl, argoK8sClientImpl, configMapRepositoryImpl, configMapHistoryRepositoryImpl, helmAppServiceImpl, helmAppClientImpl, envConfigOverrideRepositoryImpl, mergeUtil, applicationServiceClientImpl, argoClientWrapperServiceImpl, pipelineConfigListenerServiceImpl, customTagServiceImpl, acdConfig, deployedAppMetricsServiceImpl, chartRefServiceImpl, gitOpsConfigReadServiceImpl, gitOperationServiceImpl, imageDigestPolicyServiceImpl) deploymentGroupAppRepositoryImpl := repository.NewDeploymentGroupAppRepositoryImpl(sugaredLogger, db) deploymentGroupServiceImpl := deploymentGroup.NewDeploymentGroupServiceImpl(appRepositoryImpl, sugaredLogger, pipelineRepositoryImpl, ciPipelineRepositoryImpl, deploymentGroupRepositoryImpl, environmentRepositoryImpl, deploymentGroupAppRepositoryImpl, ciArtifactRepositoryImpl, appWorkflowRepositoryImpl, workflowDagExecutorImpl) - deploymentConfigServiceImpl := pipeline.NewDeploymentConfigServiceImpl(sugaredLogger, envConfigOverrideRepositoryImpl, chartRepositoryImpl, pipelineRepositoryImpl, envLevelAppMetricsRepositoryImpl, appLevelMetricsRepositoryImpl, pipelineConfigRepositoryImpl, configMapRepositoryImpl, configMapHistoryServiceImpl, chartRefRepositoryImpl, scopedVariableCMCSManagerImpl) + deploymentConfigServiceImpl := pipeline.NewDeploymentConfigServiceImpl(sugaredLogger, envConfigOverrideRepositoryImpl, chartRepositoryImpl, pipelineRepositoryImpl, pipelineConfigRepositoryImpl, configMapRepositoryImpl, configMapHistoryServiceImpl, scopedVariableCMCSManagerImpl, deployedAppMetricsServiceImpl, chartRefServiceImpl) pipelineTriggerRestHandlerImpl := restHandler.NewPipelineRestHandler(appServiceImpl, userServiceImpl, validate, enforcerImpl, teamServiceImpl, sugaredLogger, enforcerUtilImpl, workflowDagExecutorImpl, deploymentGroupServiceImpl, argoUserServiceImpl, deploymentConfigServiceImpl) sseSSE := sse.NewSSE() pipelineTriggerRouterImpl := router.NewPipelineTriggerRouter(pipelineTriggerRestHandlerImpl, sseSSE) - prePostCiScriptHistoryRepositoryImpl := repository6.NewPrePostCiScriptHistoryRepositoryImpl(sugaredLogger, db) + appListingRepositoryQueryBuilder := helper.NewAppListingRepositoryQueryBuilder(sugaredLogger) + appListingRepositoryImpl := repository.NewAppListingRepositoryImpl(sugaredLogger, db, appListingRepositoryQueryBuilder, environmentRepositoryImpl) + prePostCiScriptHistoryRepositoryImpl := repository8.NewPrePostCiScriptHistoryRepositoryImpl(sugaredLogger, db) prePostCiScriptHistoryServiceImpl := history.NewPrePostCiScriptHistoryServiceImpl(sugaredLogger, prePostCiScriptHistoryRepositoryImpl) - gitMaterialHistoryRepositoryImpl := repository6.NewGitMaterialHistoryRepositoyImpl(db) + gitMaterialHistoryRepositoryImpl := repository8.NewGitMaterialHistoryRepositoyImpl(db) gitMaterialHistoryServiceImpl := history.NewGitMaterialHistoryServiceImpl(gitMaterialHistoryRepositoryImpl, sugaredLogger) - ciPipelineHistoryRepositoryImpl := repository6.NewCiPipelineHistoryRepositoryImpl(db, sugaredLogger) + ciPipelineHistoryRepositoryImpl := repository8.NewCiPipelineHistoryRepositoryImpl(db, sugaredLogger) ciPipelineHistoryServiceImpl := history.NewCiPipelineHistoryServiceImpl(ciPipelineHistoryRepositoryImpl, sugaredLogger, ciPipelineRepositoryImpl) ciBuildConfigRepositoryImpl := pipelineConfig.NewCiBuildConfigRepositoryImpl(db, sugaredLogger) ciBuildConfigServiceImpl := pipeline.NewCiBuildConfigServiceImpl(sugaredLogger, ciBuildConfigRepositoryImpl) ciTemplateServiceImpl := pipeline.NewCiTemplateServiceImpl(sugaredLogger, ciBuildConfigServiceImpl, ciTemplateRepositoryImpl, ciTemplateOverrideRepositoryImpl) + chartRepoRepositoryImpl := chartRepoRepository.NewChartRepoRepositoryImpl(db) configMapServiceImpl := pipeline.NewConfigMapServiceImpl(chartRepositoryImpl, sugaredLogger, chartRepoRepositoryImpl, utilMergeUtil, pipelineConfigRepositoryImpl, configMapRepositoryImpl, envConfigOverrideRepositoryImpl, commonServiceImpl, appRepositoryImpl, configMapHistoryServiceImpl, environmentRepositoryImpl, scopedVariableCMCSManagerImpl) ciCdPipelineOrchestratorImpl := pipeline.NewCiCdPipelineOrchestrator(appRepositoryImpl, sugaredLogger, materialRepositoryImpl, pipelineRepositoryImpl, ciPipelineRepositoryImpl, ciPipelineMaterialRepositoryImpl, clientImpl, ciCdConfig, appWorkflowRepositoryImpl, environmentRepositoryImpl, attributesServiceImpl, appListingRepositoryImpl, appCrudOperationServiceImpl, userAuthServiceImpl, prePostCdScriptHistoryServiceImpl, prePostCiScriptHistoryServiceImpl, pipelineStageServiceImpl, ciTemplateOverrideRepositoryImpl, gitMaterialHistoryServiceImpl, ciPipelineHistoryServiceImpl, ciTemplateServiceImpl, dockerArtifactStoreRepositoryImpl, ciArtifactRepositoryImpl, configMapServiceImpl, customTagServiceImpl, genericNoteServiceImpl) ecrConfig, err := pipeline.GetEcrConfig() if err != nil { return nil, err } - ciTemplateHistoryRepositoryImpl := repository6.NewCiTemplateHistoryRepositoryImpl(db, sugaredLogger) + ciTemplateHistoryRepositoryImpl := repository8.NewCiTemplateHistoryRepositoryImpl(db, sugaredLogger) ciTemplateHistoryServiceImpl := history.NewCiTemplateHistoryServiceImpl(ciTemplateHistoryRepositoryImpl, sugaredLogger) resourceGroupRepositoryImpl := resourceGroup.NewResourceGroupRepositoryImpl(db) resourceGroupMappingRepositoryImpl := resourceGroup.NewResourceGroupMappingRepositoryImpl(db) @@ -503,20 +491,21 @@ func InitializeApp() (*App, error) { ciMaterialConfigServiceImpl := pipeline.NewCiMaterialConfigServiceImpl(sugaredLogger, materialRepositoryImpl, ciTemplateServiceImpl, ciCdPipelineOrchestratorImpl, ciPipelineRepositoryImpl, gitMaterialHistoryServiceImpl, pipelineRepositoryImpl, ciPipelineMaterialRepositoryImpl) imageTaggingRepositoryImpl := repository14.NewImageTaggingRepositoryImpl(db) imageTaggingServiceImpl := pipeline.NewImageTaggingServiceImpl(imageTaggingRepositoryImpl, ciPipelineRepositoryImpl, pipelineRepositoryImpl, environmentRepositoryImpl, sugaredLogger) - chartDeploymentServiceImpl := util.NewChartDeploymentServiceImpl(sugaredLogger, repositoryServiceClientImpl) - propertiesConfigServiceImpl := pipeline.NewPropertiesConfigServiceImpl(sugaredLogger, envConfigOverrideRepositoryImpl, chartRepositoryImpl, chartRefRepositoryImpl, utilMergeUtil, environmentRepositoryImpl, ciCdPipelineOrchestratorImpl, applicationServiceClientImpl, envLevelAppMetricsRepositoryImpl, appLevelMetricsRepositoryImpl, deploymentTemplateHistoryServiceImpl, scopedVariableManagerImpl) - pipelineDeploymentServiceTypeConfig, err := pipeline.GetDeploymentServiceTypeConfig() + propertiesConfigServiceImpl := pipeline.NewPropertiesConfigServiceImpl(sugaredLogger, envConfigOverrideRepositoryImpl, chartRepositoryImpl, environmentRepositoryImpl, deploymentTemplateHistoryServiceImpl, scopedVariableManagerImpl, deployedAppMetricsServiceImpl) + deploymentServiceTypeConfig, err := pipeline.GetDeploymentServiceTypeConfig() if err != nil { return nil, err } devtronAppCMCSServiceImpl := pipeline.NewDevtronAppCMCSServiceImpl(sugaredLogger, appServiceImpl, attributesRepositoryImpl) - cdPipelineConfigServiceImpl := pipeline.NewCdPipelineConfigServiceImpl(sugaredLogger, pipelineRepositoryImpl, environmentRepositoryImpl, pipelineConfigRepositoryImpl, appWorkflowRepositoryImpl, pipelineStageServiceImpl, appRepositoryImpl, appServiceImpl, deploymentGroupRepositoryImpl, ciCdPipelineOrchestratorImpl, appStatusRepositoryImpl, ciPipelineRepositoryImpl, prePostCdScriptHistoryServiceImpl, clusterRepositoryImpl, helmAppServiceImpl, enforcerUtilImpl, gitOpsConfigRepositoryImpl, pipelineStrategyHistoryServiceImpl, chartRepositoryImpl, resourceGroupServiceImpl, chartDeploymentServiceImpl, chartTemplateServiceImpl, propertiesConfigServiceImpl, appLevelMetricsRepositoryImpl, deploymentTemplateHistoryServiceImpl, scopedVariableManagerImpl, pipelineDeploymentServiceTypeConfig, applicationServiceClientImpl, customTagServiceImpl, pipelineConfigListenerServiceImpl, devtronAppCMCSServiceImpl, ciPipelineConfigServiceImpl, buildPipelineSwitchServiceImpl, imageDigestPolicyServiceImpl) + cdPipelineConfigServiceImpl := pipeline.NewCdPipelineConfigServiceImpl(sugaredLogger, pipelineRepositoryImpl, environmentRepositoryImpl, pipelineConfigRepositoryImpl, appWorkflowRepositoryImpl, pipelineStageServiceImpl, appRepositoryImpl, appServiceImpl, deploymentGroupRepositoryImpl, ciCdPipelineOrchestratorImpl, appStatusRepositoryImpl, ciPipelineRepositoryImpl, prePostCdScriptHistoryServiceImpl, clusterRepositoryImpl, helmAppServiceImpl, enforcerUtilImpl, pipelineStrategyHistoryServiceImpl, chartRepositoryImpl, resourceGroupServiceImpl, propertiesConfigServiceImpl, deploymentTemplateHistoryServiceImpl, scopedVariableManagerImpl, deploymentServiceTypeConfig, applicationServiceClientImpl, customTagServiceImpl, pipelineConfigListenerServiceImpl, devtronAppCMCSServiceImpl, ciPipelineConfigServiceImpl, buildPipelineSwitchServiceImpl, argoClientWrapperServiceImpl, deployedAppMetricsServiceImpl, gitOpsConfigReadServiceImpl, gitOperationServiceImpl, imageDigestPolicyServiceImpl) appArtifactManagerImpl := pipeline.NewAppArtifactManagerImpl(sugaredLogger, cdWorkflowRepositoryImpl, userServiceImpl, imageTaggingServiceImpl, ciArtifactRepositoryImpl, ciWorkflowRepositoryImpl, pipelineStageServiceImpl, cdPipelineConfigServiceImpl, dockerArtifactStoreRepositoryImpl, ciPipelineRepositoryImpl, ciTemplateServiceImpl) globalStrategyMetadataChartRefMappingRepositoryImpl := chartRepoRepository.NewGlobalStrategyMetadataChartRefMappingRepositoryImpl(db, sugaredLogger) devtronAppStrategyServiceImpl := pipeline.NewDevtronAppStrategyServiceImpl(sugaredLogger, chartRepositoryImpl, globalStrategyMetadataChartRefMappingRepositoryImpl, ciCdPipelineOrchestratorImpl, cdPipelineConfigServiceImpl) - appDeploymentTypeChangeManagerImpl := pipeline.NewAppDeploymentTypeChangeManagerImpl(sugaredLogger, pipelineRepositoryImpl, workflowDagExecutorImpl, appServiceImpl, chartTemplateServiceImpl, appStatusRepositoryImpl, helmAppServiceImpl, applicationServiceClientImpl, appArtifactManagerImpl, cdPipelineConfigServiceImpl) + chartServiceImpl := chart.NewChartServiceImpl(chartRepositoryImpl, sugaredLogger, chartTemplateServiceImpl, chartRepoRepositoryImpl, appRepositoryImpl, utilMergeUtil, envConfigOverrideRepositoryImpl, pipelineConfigRepositoryImpl, environmentRepositoryImpl, deploymentTemplateHistoryServiceImpl, scopedVariableManagerImpl, deployedAppMetricsServiceImpl, chartRefServiceImpl) + appDeploymentTypeChangeManagerImpl := pipeline.NewAppDeploymentTypeChangeManagerImpl(sugaredLogger, pipelineRepositoryImpl, workflowDagExecutorImpl, appServiceImpl, appStatusRepositoryImpl, helmAppServiceImpl, applicationServiceClientImpl, appArtifactManagerImpl, cdPipelineConfigServiceImpl, gitOpsConfigReadServiceImpl, chartServiceImpl) devtronAppConfigServiceImpl := pipeline.NewDevtronAppConfigServiceImpl(sugaredLogger, ciCdPipelineOrchestratorImpl, appRepositoryImpl, pipelineRepositoryImpl, resourceGroupServiceImpl, enforcerUtilImpl, ciMaterialConfigServiceImpl) pipelineBuilderImpl := pipeline.NewPipelineBuilderImpl(sugaredLogger, materialRepositoryImpl, chartRepositoryImpl, ciPipelineConfigServiceImpl, ciMaterialConfigServiceImpl, appArtifactManagerImpl, devtronAppCMCSServiceImpl, devtronAppStrategyServiceImpl, appDeploymentTypeChangeManagerImpl, cdPipelineConfigServiceImpl, devtronAppConfigServiceImpl) + deploymentTemplateValidationServiceImpl := deploymentTemplate.NewDeploymentTemplateValidationServiceImpl(sugaredLogger, chartRefServiceImpl, scopedVariableManagerImpl) ciServiceImpl := pipeline.NewCiServiceImpl(sugaredLogger, workflowServiceImpl, ciPipelineMaterialRepositoryImpl, ciWorkflowRepositoryImpl, eventRESTClientImpl, eventSimpleFactoryImpl, mergeUtil, ciPipelineRepositoryImpl, prePostCiScriptHistoryServiceImpl, pipelineStageServiceImpl, userServiceImpl, ciTemplateServiceImpl, appCrudOperationServiceImpl, environmentRepositoryImpl, appRepositoryImpl, scopedVariableManagerImpl, customTagServiceImpl, pluginInputVariableParserImpl, globalPluginServiceImpl) ciLogServiceImpl, err := pipeline.NewCiLogServiceImpl(sugaredLogger, ciServiceImpl, k8sServiceImpl) if err != nil { @@ -527,17 +516,17 @@ func InitializeApp() (*App, error) { gitRegistryConfigImpl := pipeline.NewGitRegistryConfigImpl(sugaredLogger, gitProviderRepositoryImpl, clientImpl) appListingViewBuilderImpl := app2.NewAppListingViewBuilderImpl(sugaredLogger) linkoutsRepositoryImpl := repository.NewLinkoutsRepositoryImpl(sugaredLogger, db) - appListingServiceImpl := app2.NewAppListingServiceImpl(sugaredLogger, appListingRepositoryImpl, applicationServiceClientImpl, appRepositoryImpl, appListingViewBuilderImpl, pipelineRepositoryImpl, linkoutsRepositoryImpl, appLevelMetricsRepositoryImpl, envLevelAppMetricsRepositoryImpl, cdWorkflowRepositoryImpl, pipelineOverrideRepositoryImpl, environmentRepositoryImpl, argoUserServiceImpl, envConfigOverrideRepositoryImpl, chartRepositoryImpl, ciPipelineRepositoryImpl, dockerRegistryIpsConfigServiceImpl, userRepositoryImpl) + appListingServiceImpl := app2.NewAppListingServiceImpl(sugaredLogger, appListingRepositoryImpl, applicationServiceClientImpl, appRepositoryImpl, appListingViewBuilderImpl, pipelineRepositoryImpl, linkoutsRepositoryImpl, cdWorkflowRepositoryImpl, pipelineOverrideRepositoryImpl, environmentRepositoryImpl, argoUserServiceImpl, envConfigOverrideRepositoryImpl, chartRepositoryImpl, ciPipelineRepositoryImpl, dockerRegistryIpsConfigServiceImpl, userRepositoryImpl, deployedAppMetricsServiceImpl) deploymentEventHandlerImpl := app2.NewDeploymentEventHandlerImpl(sugaredLogger, appListingServiceImpl, eventRESTClientImpl, eventSimpleFactoryImpl) cdHandlerImpl := pipeline.NewCdHandlerImpl(sugaredLogger, userServiceImpl, cdWorkflowRepositoryImpl, ciLogServiceImpl, ciArtifactRepositoryImpl, ciPipelineMaterialRepositoryImpl, pipelineRepositoryImpl, environmentRepositoryImpl, ciWorkflowRepositoryImpl, helmAppServiceImpl, pipelineOverrideRepositoryImpl, workflowDagExecutorImpl, appListingServiceImpl, appListingRepositoryImpl, pipelineStatusTimelineRepositoryImpl, applicationServiceClientImpl, argoUserServiceImpl, deploymentEventHandlerImpl, eventRESTClientImpl, pipelineStatusTimelineResourcesServiceImpl, pipelineStatusSyncDetailServiceImpl, pipelineStatusTimelineServiceImpl, appServiceImpl, appStatusServiceImpl, enforcerUtilImpl, installedAppRepositoryImpl, installedAppVersionHistoryRepositoryImpl, appRepositoryImpl, resourceGroupServiceImpl, imageTaggingServiceImpl, k8sServiceImpl, workflowServiceImpl, clusterServiceImplExtended, blobStorageConfigServiceImpl, customTagServiceImpl, argoClientWrapperServiceImpl, appServiceConfig, acdConfig) appWorkflowServiceImpl := appWorkflow2.NewAppWorkflowServiceImpl(sugaredLogger, appWorkflowRepositoryImpl, ciCdPipelineOrchestratorImpl, ciPipelineRepositoryImpl, pipelineRepositoryImpl, enforcerUtilImpl, resourceGroupServiceImpl, appRepositoryImpl, userAuthServiceImpl) - appCloneServiceImpl := appClone.NewAppCloneServiceImpl(sugaredLogger, pipelineBuilderImpl, materialRepositoryImpl, chartServiceImpl, configMapServiceImpl, appWorkflowServiceImpl, appListingServiceImpl, propertiesConfigServiceImpl, ciTemplateOverrideRepositoryImpl, pipelineStageServiceImpl, ciTemplateServiceImpl, appRepositoryImpl, ciPipelineRepositoryImpl, pipelineRepositoryImpl, appWorkflowRepositoryImpl, ciPipelineConfigServiceImpl) + appCloneServiceImpl := appClone.NewAppCloneServiceImpl(sugaredLogger, pipelineBuilderImpl, chartServiceImpl, configMapServiceImpl, appWorkflowServiceImpl, appListingServiceImpl, propertiesConfigServiceImpl, pipelineStageServiceImpl, ciTemplateServiceImpl, appRepositoryImpl, ciPipelineRepositoryImpl, pipelineRepositoryImpl, ciPipelineConfigServiceImpl, gitOpsConfigReadServiceImpl) deploymentTemplateRepositoryImpl := repository.NewDeploymentTemplateRepositoryImpl(db, sugaredLogger) - deploymentTemplateServiceImpl := generateManifest.NewDeploymentTemplateServiceImpl(sugaredLogger, chartServiceImpl, appListingServiceImpl, appListingRepositoryImpl, deploymentTemplateRepositoryImpl, helmAppServiceImpl, chartRepositoryImpl, chartTemplateServiceImpl, helmAppClientImpl, k8sServiceImpl, propertiesConfigServiceImpl, deploymentTemplateHistoryServiceImpl, environmentRepositoryImpl, appRepositoryImpl, scopedVariableManagerImpl) + deploymentTemplateServiceImpl := generateManifest.NewDeploymentTemplateServiceImpl(sugaredLogger, chartServiceImpl, appListingServiceImpl, appListingRepositoryImpl, deploymentTemplateRepositoryImpl, helmAppServiceImpl, chartRepositoryImpl, chartTemplateServiceImpl, helmAppClientImpl, k8sServiceImpl, propertiesConfigServiceImpl, deploymentTemplateHistoryServiceImpl, environmentRepositoryImpl, appRepositoryImpl, scopedVariableManagerImpl, chartRefServiceImpl) imageScanObjectMetaRepositoryImpl := security.NewImageScanObjectMetaRepositoryImpl(db, sugaredLogger) cveStoreRepositoryImpl := security.NewCveStoreRepositoryImpl(db, sugaredLogger) policyServiceImpl := security2.NewPolicyServiceImpl(environmentServiceImpl, sugaredLogger, appRepositoryImpl, pipelineOverrideRepositoryImpl, cvePolicyRepositoryImpl, clusterServiceImplExtended, pipelineRepositoryImpl, imageScanResultRepositoryImpl, imageScanDeployInfoRepositoryImpl, imageScanObjectMetaRepositoryImpl, httpClient, ciArtifactRepositoryImpl, ciCdConfig, imageScanHistoryRepositoryImpl, cveStoreRepositoryImpl, ciTemplateRepositoryImpl) - pipelineConfigRestHandlerImpl := app3.NewPipelineRestHandlerImpl(pipelineBuilderImpl, sugaredLogger, chartServiceImpl, propertiesConfigServiceImpl, applicationServiceClientImpl, userServiceImpl, teamServiceImpl, enforcerImpl, ciHandlerImpl, validate, clientImpl, ciPipelineRepositoryImpl, pipelineRepositoryImpl, enforcerUtilImpl, environmentServiceImpl, gitRegistryConfigImpl, dockerRegistryConfigImpl, cdHandlerImpl, appCloneServiceImpl, deploymentTemplateServiceImpl, appWorkflowServiceImpl, materialRepositoryImpl, policyServiceImpl, imageScanResultRepositoryImpl, gitProviderRepositoryImpl, argoUserServiceImpl, ciPipelineMaterialRepositoryImpl, imageTaggingServiceImpl, ciArtifactRepositoryImpl) + pipelineConfigRestHandlerImpl := app3.NewPipelineRestHandlerImpl(pipelineBuilderImpl, sugaredLogger, deploymentTemplateValidationServiceImpl, chartServiceImpl, propertiesConfigServiceImpl, userServiceImpl, teamServiceImpl, enforcerImpl, ciHandlerImpl, validate, clientImpl, ciPipelineRepositoryImpl, pipelineRepositoryImpl, enforcerUtilImpl, environmentServiceImpl, gitRegistryConfigImpl, dockerRegistryConfigImpl, cdHandlerImpl, appCloneServiceImpl, deploymentTemplateServiceImpl, appWorkflowServiceImpl, materialRepositoryImpl, policyServiceImpl, imageScanResultRepositoryImpl, gitProviderRepositoryImpl, argoUserServiceImpl, ciPipelineMaterialRepositoryImpl, imageTaggingServiceImpl, ciArtifactRepositoryImpl, deployedAppMetricsServiceImpl, chartRefServiceImpl) appWorkflowRestHandlerImpl := restHandler.NewAppWorkflowRestHandlerImpl(sugaredLogger, userServiceImpl, appWorkflowServiceImpl, teamServiceImpl, enforcerImpl, pipelineBuilderImpl, appRepositoryImpl, enforcerUtilImpl) webhookEventDataRepositoryImpl := repository.NewWebhookEventDataRepositoryImpl(db) webhookEventDataConfigImpl := pipeline.NewWebhookEventDataConfigImpl(sugaredLogger, webhookEventDataRepositoryImpl) @@ -547,8 +536,23 @@ func InitializeApp() (*App, error) { pipelineStatusTimelineRestHandlerImpl := restHandler.NewPipelineStatusTimelineRestHandlerImpl(sugaredLogger, pipelineStatusTimelineServiceImpl, enforcerUtilImpl, enforcerImpl) pipelineConfigRouterImpl := router.NewPipelineRouterImpl(pipelineConfigRestHandlerImpl, appWorkflowRestHandlerImpl, webhookDataRestHandlerImpl, pipelineHistoryRestHandlerImpl, pipelineStatusTimelineRestHandlerImpl) appStoreVersionValuesRepositoryImpl := appStoreValuesRepository.NewAppStoreVersionValuesRepositoryImpl(sugaredLogger, db) - appStoreValuesServiceImpl := service2.NewAppStoreValuesServiceImpl(sugaredLogger, appStoreApplicationVersionRepositoryImpl, installedAppRepositoryImpl, appStoreVersionValuesRepositoryImpl, userServiceImpl) - k8sResourceHistoryRepositoryImpl := repository15.NewK8sResourceHistoryRepositoryImpl(db, sugaredLogger) + appStoreValuesServiceImpl := service.NewAppStoreValuesServiceImpl(sugaredLogger, appStoreApplicationVersionRepositoryImpl, installedAppRepositoryImpl, appStoreVersionValuesRepositoryImpl, userServiceImpl) + chartGroupDeploymentRepositoryImpl := repository15.NewChartGroupDeploymentRepositoryImpl(db, sugaredLogger) + acdAuthConfig, err := util3.GetACDAuthConfig() + if err != nil { + return nil, err + } + appStoreDeploymentCommonServiceImpl := appStoreDeploymentCommon.NewAppStoreDeploymentCommonServiceImpl(sugaredLogger, installedAppRepositoryImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl, chartTemplateServiceImpl, gitFactory, gitOpsConfigReadServiceImpl, gitOperationServiceImpl) + appStoreDeploymentFullModeServiceImpl := appStoreDeploymentFullMode.NewAppStoreDeploymentFullModeServiceImpl(sugaredLogger, applicationServiceClientImpl, argoK8sClientImpl, acdAuthConfig, argoUserServiceImpl, pipelineStatusTimelineServiceImpl, appStoreDeploymentCommonServiceImpl, argoClientWrapperServiceImpl, pubSubClientServiceImpl, installedAppVersionHistoryRepositoryImpl, acdConfig, gitOpsConfigReadServiceImpl, gitOperationServiceImpl) + clusterInstalledAppsRepositoryImpl := repository3.NewClusterInstalledAppsRepositoryImpl(db, sugaredLogger) + appStoreDeploymentHelmServiceImpl := appStoreDeploymentTool.NewAppStoreDeploymentHelmServiceImpl(sugaredLogger, helmAppServiceImpl, appStoreApplicationVersionRepositoryImpl, helmAppClientImpl, installedAppRepositoryImpl, appStoreDeploymentCommonServiceImpl, ociRegistryConfigRepositoryImpl, gitOperationServiceImpl) + appStoreDeploymentArgoCdServiceImpl := appStoreDeploymentTool.NewAppStoreDeploymentArgoCdServiceImpl(sugaredLogger, appStoreDeploymentFullModeServiceImpl, applicationServiceClientImpl, chartGroupDeploymentRepositoryImpl, installedAppRepositoryImpl, installedAppVersionHistoryRepositoryImpl, appStoreDeploymentCommonServiceImpl, helmAppServiceImpl, appStatusServiceImpl, pipelineStatusTimelineServiceImpl, userServiceImpl, pipelineStatusTimelineRepositoryImpl, appStoreApplicationVersionRepositoryImpl, argoClientWrapperServiceImpl, acdConfig, gitOperationServiceImpl) + serviceDeploymentServiceTypeConfig, err := service2.GetDeploymentServiceTypeConfig() + if err != nil { + return nil, err + } + appStoreDeploymentServiceImpl := service2.NewAppStoreDeploymentServiceImpl(sugaredLogger, installedAppRepositoryImpl, chartGroupDeploymentRepositoryImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl, clusterInstalledAppsRepositoryImpl, appRepositoryImpl, appStoreDeploymentHelmServiceImpl, appStoreDeploymentArgoCdServiceImpl, environmentServiceImpl, clusterServiceImplExtended, helmAppServiceImpl, appStoreDeploymentCommonServiceImpl, installedAppVersionHistoryRepositoryImpl, serviceDeploymentServiceTypeConfig, acdConfig, gitOpsConfigReadServiceImpl, gitOperationServiceImpl) + k8sResourceHistoryRepositoryImpl := repository16.NewK8sResourceHistoryRepositoryImpl(db, sugaredLogger) k8sResourceHistoryServiceImpl := kubernetesResourceAuditLogs.Newk8sResourceHistoryServiceImpl(k8sResourceHistoryRepositoryImpl, sugaredLogger, appRepositoryImpl, environmentRepositoryImpl) ephemeralContainersRepositoryImpl := repository2.NewEphemeralContainersRepositoryImpl(db) ephemeralContainerServiceImpl := cluster2.NewEphemeralContainerServiceImpl(ephemeralContainersRepositoryImpl, sugaredLogger) @@ -557,7 +561,7 @@ func InitializeApp() (*App, error) { if err != nil { return nil, err } - installedAppServiceImpl, err := service.NewInstalledAppServiceImpl(sugaredLogger, installedAppRepositoryImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl, teamRepositoryImpl, appRepositoryImpl, applicationServiceClientImpl, appStoreValuesServiceImpl, pubSubClientServiceImpl, chartGroupDeploymentRepositoryImpl, environmentServiceImpl, gitFactory, acdAuthConfig, gitOpsConfigRepositoryImpl, userServiceImpl, appStoreDeploymentFullModeServiceImpl, appStoreDeploymentServiceImpl, installedAppVersionHistoryRepositoryImpl, argoUserServiceImpl, helmAppClientImpl, helmAppServiceImpl, appStatusServiceImpl, k8sServiceImpl, pipelineStatusTimelineServiceImpl, appStoreDeploymentCommonServiceImpl, k8sCommonServiceImpl, k8sApplicationServiceImpl, acdConfig) + installedAppServiceImpl, err := service2.NewInstalledAppServiceImpl(sugaredLogger, installedAppRepositoryImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl, teamRepositoryImpl, appRepositoryImpl, applicationServiceClientImpl, appStoreValuesServiceImpl, pubSubClientServiceImpl, chartGroupDeploymentRepositoryImpl, environmentServiceImpl, acdAuthConfig, userServiceImpl, appStoreDeploymentFullModeServiceImpl, appStoreDeploymentServiceImpl, installedAppVersionHistoryRepositoryImpl, argoUserServiceImpl, helmAppClientImpl, helmAppServiceImpl, appStatusServiceImpl, k8sServiceImpl, pipelineStatusTimelineServiceImpl, appStoreDeploymentCommonServiceImpl, k8sCommonServiceImpl, k8sApplicationServiceImpl, acdConfig, gitOpsConfigReadServiceImpl, gitOperationServiceImpl) if err != nil { return nil, err } @@ -574,7 +578,7 @@ func InitializeApp() (*App, error) { clusterRestHandlerImpl := cluster3.NewClusterRestHandlerImpl(clusterServiceImplExtended, genericNoteServiceImpl, clusterDescriptionServiceImpl, sugaredLogger, userServiceImpl, validate, enforcerImpl, deleteServiceExtendedImpl, argoUserServiceImpl, environmentServiceImpl, clusterRbacServiceImpl) clusterRouterImpl := cluster3.NewClusterRouterImpl(clusterRestHandlerImpl) gitWebhookRepositoryImpl := repository.NewGitWebhookRepositoryImpl(db) - gitWebhookServiceImpl := git.NewGitWebhookServiceImpl(sugaredLogger, ciHandlerImpl, gitWebhookRepositoryImpl) + gitWebhookServiceImpl := git2.NewGitWebhookServiceImpl(sugaredLogger, ciHandlerImpl, gitWebhookRepositoryImpl) gitWebhookRestHandlerImpl := restHandler.NewGitWebhookRestHandlerImpl(sugaredLogger, gitWebhookServiceImpl) webhookServiceImpl := pipeline.NewWebhookServiceImpl(ciArtifactRepositoryImpl, sugaredLogger, ciPipelineRepositoryImpl, appServiceImpl, eventRESTClientImpl, eventSimpleFactoryImpl, ciWorkflowRepositoryImpl, workflowDagExecutorImpl, ciHandlerImpl, pipelineStageRepositoryImpl, globalPluginRepositoryImpl, customTagServiceImpl) ciEventConfig, err := pubsub.GetCiEventConfig() @@ -637,7 +641,7 @@ func InitializeApp() (*App, error) { roleGroupServiceImpl := user.NewRoleGroupServiceImpl(userAuthRepositoryImpl, sugaredLogger, userRepositoryImpl, roleGroupRepositoryImpl, userCommonServiceImpl) userRestHandlerImpl := user2.NewUserRestHandlerImpl(userServiceImpl, validate, sugaredLogger, enforcerImpl, roleGroupServiceImpl, userCommonServiceImpl) userRouterImpl := user2.NewUserRouterImpl(userRestHandlerImpl) - chartRefRestHandlerImpl := restHandler.NewChartRefRestHandlerImpl(chartServiceImpl, sugaredLogger) + chartRefRestHandlerImpl := restHandler.NewChartRefRestHandlerImpl(sugaredLogger, chartRefServiceImpl, chartServiceImpl) chartRefRouterImpl := router.NewChartRefRouterImpl(chartRefRestHandlerImpl) configMapRestHandlerImpl := restHandler.NewConfigMapRestHandlerImpl(pipelineBuilderImpl, sugaredLogger, chartServiceImpl, userServiceImpl, teamServiceImpl, enforcerImpl, pipelineRepositoryImpl, enforcerUtilImpl, configMapServiceImpl) configMapRouterImpl := router.NewConfigMapRouterImpl(configMapRestHandlerImpl) @@ -653,7 +657,7 @@ func InitializeApp() (*App, error) { appStoreDeploymentRouterImpl := appStoreDeployment.NewAppStoreDeploymentRouterImpl(appStoreDeploymentRestHandlerImpl) appStoreStatusTimelineRestHandlerImpl := appStore.NewAppStoreStatusTimelineRestHandlerImpl(sugaredLogger, pipelineStatusTimelineServiceImpl, enforcerUtilImpl, enforcerImpl) appStoreRouterImpl := appStore.NewAppStoreRouterImpl(installedAppRestHandlerImpl, appStoreValuesRouterImpl, appStoreDiscoverRouterImpl, chartProviderRouterImpl, appStoreDeploymentRouterImpl, appStoreStatusTimelineRestHandlerImpl) - chartRepositoryRestHandlerImpl := chartRepo2.NewChartRepositoryRestHandlerImpl(sugaredLogger, userServiceImpl, chartRepositoryServiceImpl, enforcerImpl, validate, deleteServiceExtendedImpl, chartRefRepositoryImpl, refChartDir, attributesServiceImpl) + chartRepositoryRestHandlerImpl := chartRepo2.NewChartRepositoryRestHandlerImpl(sugaredLogger, userServiceImpl, chartRepositoryServiceImpl, enforcerImpl, validate, deleteServiceExtendedImpl, attributesServiceImpl) chartRepositoryRouterImpl := chartRepo2.NewChartRepositoryRouterImpl(chartRepositoryRestHandlerImpl) lensConfig, err := lens.GetLensConfig() if err != nil { @@ -675,8 +679,8 @@ func InitializeApp() (*App, error) { workflowActionImpl := batch.NewWorkflowActionImpl(sugaredLogger, appRepositoryImpl, appWorkflowServiceImpl, buildActionImpl, deploymentActionImpl) batchOperationRestHandlerImpl := restHandler.NewBatchOperationRestHandlerImpl(userServiceImpl, enforcerImpl, workflowActionImpl, teamServiceImpl, sugaredLogger, enforcerUtilImpl, argoUserServiceImpl) batchOperationRouterImpl := router.NewBatchOperationRouterImpl(batchOperationRestHandlerImpl, sugaredLogger) - chartGroupEntriesRepositoryImpl := repository11.NewChartGroupEntriesRepositoryImpl(db, sugaredLogger) - chartGroupReposotoryImpl := repository11.NewChartGroupReposotoryImpl(db, sugaredLogger) + chartGroupEntriesRepositoryImpl := repository15.NewChartGroupEntriesRepositoryImpl(db, sugaredLogger) + chartGroupReposotoryImpl := repository15.NewChartGroupReposotoryImpl(db, sugaredLogger) chartGroupServiceImpl := chartGroup.NewChartGroupServiceImpl(chartGroupEntriesRepositoryImpl, chartGroupReposotoryImpl, sugaredLogger, chartGroupDeploymentRepositoryImpl, installedAppRepositoryImpl, appStoreVersionValuesRepositoryImpl, userAuthServiceImpl) chartGroupRestHandlerImpl := chartGroup2.NewChartGroupRestHandlerImpl(chartGroupServiceImpl, sugaredLogger, userServiceImpl, enforcerImpl, validate) chartGroupRouterImpl := chartGroup2.NewChartGroupRouterImpl(chartGroupRestHandlerImpl) @@ -686,8 +690,8 @@ func InitializeApp() (*App, error) { imageScanRouterImpl := router.NewImageScanRouterImpl(imageScanRestHandlerImpl) policyRestHandlerImpl := restHandler.NewPolicyRestHandlerImpl(sugaredLogger, policyServiceImpl, userServiceImpl, userAuthServiceImpl, enforcerImpl, enforcerUtilImpl, environmentServiceImpl) policyRouterImpl := router.NewPolicyRouterImpl(policyRestHandlerImpl) - gitOpsConfigServiceImpl := gitops.NewGitOpsConfigServiceImpl(sugaredLogger, globalEnvVariables, gitOpsConfigRepositoryImpl, k8sServiceImpl, acdAuthConfig, clusterServiceImplExtended, environmentServiceImpl, versionServiceImpl, gitFactory, chartTemplateServiceImpl, argoUserServiceImpl, serviceClientImpl) - gitOpsConfigRestHandlerImpl := restHandler.NewGitOpsConfigRestHandlerImpl(sugaredLogger, gitOpsConfigServiceImpl, userServiceImpl, validate, enforcerImpl, teamServiceImpl, gitOpsConfigRepositoryImpl) + gitOpsConfigServiceImpl := gitops.NewGitOpsConfigServiceImpl(sugaredLogger, globalEnvVariables, gitOpsConfigRepositoryImpl, k8sServiceImpl, acdAuthConfig, clusterServiceImplExtended, gitFactory, argoUserServiceImpl, serviceClientImpl, gitOpsConfigReadServiceImpl) + gitOpsConfigRestHandlerImpl := restHandler.NewGitOpsConfigRestHandlerImpl(sugaredLogger, gitOpsConfigServiceImpl, userServiceImpl, validate, enforcerImpl, teamServiceImpl) gitOpsConfigRouterImpl := router.NewGitOpsConfigRouterImpl(gitOpsConfigRestHandlerImpl) dashboardConfig, err := dashboard.GetConfig() if err != nil { @@ -700,7 +704,7 @@ func InitializeApp() (*App, error) { userAttributesServiceImpl := attributes.NewUserAttributesServiceImpl(sugaredLogger, userAttributesRepositoryImpl) userAttributesRestHandlerImpl := restHandler.NewUserAttributesRestHandlerImpl(sugaredLogger, enforcerImpl, userServiceImpl, userAttributesServiceImpl) userAttributesRouterImpl := router.NewUserAttributesRouterImpl(userAttributesRestHandlerImpl) - commonRestHanlderImpl := restHandler.NewCommonRestHanlderImpl(sugaredLogger, gitOpsConfigServiceImpl, userServiceImpl, validate, enforcerImpl, commonServiceImpl) + commonRestHanlderImpl := restHandler.NewCommonRestHanlderImpl(sugaredLogger, userServiceImpl, commonServiceImpl) commonRouterImpl := router.NewCommonRouterImpl(commonRestHanlderImpl) grafanaConfig, err := grafana.GetConfig() if err != nil { @@ -716,25 +720,25 @@ func InitializeApp() (*App, error) { return nil, err } providerIdentifierServiceImpl := providerIdentifier.NewProviderIdentifierServiceImpl(sugaredLogger) - telemetryEventClientImplExtended, err := telemetry.NewTelemetryEventClientImplExtended(sugaredLogger, httpClient, clusterServiceImplExtended, k8sServiceImpl, acdAuthConfig, environmentServiceImpl, userServiceImpl, appListingRepositoryImpl, posthogClient, ciPipelineRepositoryImpl, pipelineRepositoryImpl, gitOpsConfigRepositoryImpl, gitProviderRepositoryImpl, attributesRepositoryImpl, ssoLoginServiceImpl, appRepositoryImpl, ciWorkflowRepositoryImpl, cdWorkflowRepositoryImpl, dockerArtifactStoreRepositoryImpl, materialRepositoryImpl, ciTemplateRepositoryImpl, chartRepositoryImpl, userAuditServiceImpl, ciBuildConfigServiceImpl, moduleRepositoryImpl, serverDataStoreServerDataStore, helmAppClientImpl, installedAppRepositoryImpl, userAttributesRepositoryImpl, providerIdentifierServiceImpl, cronLoggerImpl) + telemetryEventClientImplExtended, err := telemetry.NewTelemetryEventClientImplExtended(sugaredLogger, httpClient, clusterServiceImplExtended, k8sServiceImpl, acdAuthConfig, environmentServiceImpl, userServiceImpl, appListingRepositoryImpl, posthogClient, ciPipelineRepositoryImpl, pipelineRepositoryImpl, gitProviderRepositoryImpl, attributesRepositoryImpl, ssoLoginServiceImpl, appRepositoryImpl, ciWorkflowRepositoryImpl, cdWorkflowRepositoryImpl, dockerArtifactStoreRepositoryImpl, materialRepositoryImpl, ciTemplateRepositoryImpl, chartRepositoryImpl, userAuditServiceImpl, ciBuildConfigServiceImpl, moduleRepositoryImpl, serverDataStoreServerDataStore, helmAppClientImpl, installedAppRepositoryImpl, userAttributesRepositoryImpl, providerIdentifierServiceImpl, cronLoggerImpl, gitOpsConfigReadServiceImpl) if err != nil { return nil, err } telemetryRestHandlerImpl := restHandler.NewTelemetryRestHandlerImpl(sugaredLogger, telemetryEventClientImplExtended, enforcerImpl, userServiceImpl) telemetryRouterImpl := router.NewTelemetryRouterImpl(sugaredLogger, telemetryRestHandlerImpl) bulkUpdateRepositoryImpl := bulkUpdate.NewBulkUpdateRepository(db, sugaredLogger) - bulkUpdateServiceImpl, err := bulkAction.NewBulkUpdateServiceImpl(bulkUpdateRepositoryImpl, chartRepositoryImpl, sugaredLogger, chartTemplateServiceImpl, chartRepoRepositoryImpl, defaultChart, utilMergeUtil, repositoryServiceClientImpl, chartRefRepositoryImpl, envConfigOverrideRepositoryImpl, pipelineConfigRepositoryImpl, configMapRepositoryImpl, environmentRepositoryImpl, pipelineRepositoryImpl, appLevelMetricsRepositoryImpl, envLevelAppMetricsRepositoryImpl, httpClient, appRepositoryImpl, deploymentTemplateHistoryServiceImpl, configMapHistoryServiceImpl, workflowDagExecutorImpl, cdWorkflowRepositoryImpl, pipelineBuilderImpl, helmAppServiceImpl, enforcerUtilImpl, enforcerUtilHelmImpl, ciHandlerImpl, ciPipelineRepositoryImpl, appWorkflowRepositoryImpl, appWorkflowServiceImpl, pubSubClientServiceImpl, argoUserServiceImpl, scopedVariableManagerImpl) + bulkUpdateServiceImpl, err := bulkAction.NewBulkUpdateServiceImpl(bulkUpdateRepositoryImpl, chartRepositoryImpl, sugaredLogger, environmentRepositoryImpl, pipelineRepositoryImpl, appRepositoryImpl, deploymentTemplateHistoryServiceImpl, configMapHistoryServiceImpl, workflowDagExecutorImpl, pipelineBuilderImpl, enforcerUtilImpl, ciHandlerImpl, ciPipelineRepositoryImpl, appWorkflowRepositoryImpl, appWorkflowServiceImpl, pubSubClientServiceImpl, argoUserServiceImpl, scopedVariableManagerImpl, deployedAppMetricsServiceImpl, chartRefServiceImpl) if err != nil { return nil, err } bulkUpdateRestHandlerImpl := restHandler.NewBulkUpdateRestHandlerImpl(pipelineBuilderImpl, sugaredLogger, bulkUpdateServiceImpl, chartServiceImpl, propertiesConfigServiceImpl, applicationServiceClientImpl, userServiceImpl, teamServiceImpl, enforcerImpl, ciHandlerImpl, validate, clientImpl, ciPipelineRepositoryImpl, pipelineRepositoryImpl, enforcerUtilImpl, environmentServiceImpl, gitRegistryConfigImpl, dockerRegistryConfigImpl, cdHandlerImpl, appCloneServiceImpl, appWorkflowServiceImpl, materialRepositoryImpl, policyServiceImpl, imageScanResultRepositoryImpl, argoUserServiceImpl) bulkUpdateRouterImpl := router.NewBulkUpdateRouterImpl(bulkUpdateRestHandlerImpl) - webhookSecretValidatorImpl := git.NewWebhookSecretValidatorImpl(sugaredLogger) + webhookSecretValidatorImpl := git2.NewWebhookSecretValidatorImpl(sugaredLogger) webhookEventHandlerImpl := restHandler.NewWebhookEventHandlerImpl(sugaredLogger, gitHostConfigImpl, eventRESTClientImpl, webhookSecretValidatorImpl, webhookEventDataConfigImpl) webhookListenerRouterImpl := router.NewWebhookListenerRouterImpl(webhookEventHandlerImpl) appRestHandlerImpl := restHandler.NewAppRestHandlerImpl(sugaredLogger, appCrudOperationServiceImpl, userServiceImpl, validate, enforcerUtilImpl, enforcerImpl, helmAppServiceImpl, enforcerUtilHelmImpl, genericNoteServiceImpl) appRouterImpl := router.NewAppRouterImpl(sugaredLogger, appRestHandlerImpl) - coreAppRestHandlerImpl := restHandler.NewCoreAppRestHandlerImpl(sugaredLogger, userServiceImpl, validate, enforcerUtilImpl, enforcerImpl, appCrudOperationServiceImpl, pipelineBuilderImpl, gitRegistryConfigImpl, chartServiceImpl, configMapServiceImpl, appListingServiceImpl, propertiesConfigServiceImpl, appWorkflowServiceImpl, materialRepositoryImpl, gitProviderRepositoryImpl, appWorkflowRepositoryImpl, environmentRepositoryImpl, configMapRepositoryImpl, envConfigOverrideRepositoryImpl, chartRepositoryImpl, teamServiceImpl, argoUserServiceImpl, pipelineStageServiceImpl, ciPipelineRepositoryImpl) + coreAppRestHandlerImpl := restHandler.NewCoreAppRestHandlerImpl(sugaredLogger, userServiceImpl, validate, enforcerUtilImpl, enforcerImpl, appCrudOperationServiceImpl, pipelineBuilderImpl, gitRegistryConfigImpl, chartServiceImpl, configMapServiceImpl, appListingServiceImpl, propertiesConfigServiceImpl, appWorkflowServiceImpl, materialRepositoryImpl, gitProviderRepositoryImpl, appWorkflowRepositoryImpl, environmentRepositoryImpl, configMapRepositoryImpl, chartRepositoryImpl, teamServiceImpl, argoUserServiceImpl, pipelineStageServiceImpl, ciPipelineRepositoryImpl) coreAppRouterImpl := router.NewCoreAppRouterImpl(coreAppRestHandlerImpl) helmAppRestHandlerImpl := client3.NewHelmAppRestHandlerImpl(sugaredLogger, helmAppServiceImpl, enforcerImpl, clusterServiceImplExtended, enforcerUtilHelmImpl, appStoreDeploymentCommonServiceImpl, userServiceImpl, attributesServiceImpl, serverEnvConfigServerEnvConfig) helmAppRouterImpl := client3.NewHelmAppRouterImpl(helmAppRestHandlerImpl) @@ -742,7 +746,7 @@ func InitializeApp() (*App, error) { k8sApplicationRouterImpl := application3.NewK8sApplicationRouterImpl(k8sApplicationRestHandlerImpl) pProfRestHandlerImpl := restHandler.NewPProfRestHandler(userServiceImpl, enforcerImpl) pProfRouterImpl := router.NewPProfRouter(sugaredLogger, pProfRestHandlerImpl) - deploymentConfigRestHandlerImpl := deployment.NewDeploymentConfigRestHandlerImpl(sugaredLogger, userServiceImpl, enforcerImpl, validate, refChartDir, chartServiceImpl, chartRefRepositoryImpl) + deploymentConfigRestHandlerImpl := deployment.NewDeploymentConfigRestHandlerImpl(sugaredLogger, userServiceImpl, enforcerImpl, chartServiceImpl, chartRefServiceImpl) deploymentConfigRouterImpl := deployment.NewDeploymentRouterImpl(deploymentConfigRestHandlerImpl) dashboardTelemetryRestHandlerImpl := dashboardEvent.NewDashboardTelemetryRestHandlerImpl(sugaredLogger, telemetryEventClientImplExtended) dashboardTelemetryRouterImpl := dashboardEvent.NewDashboardTelemetryRouterImpl(dashboardTelemetryRestHandlerImpl) @@ -821,10 +825,3 @@ func InitializeApp() (*App, error) { mainApp := NewApp(muxRouter, sugaredLogger, sseSSE, syncedEnforcer, db, pubSubClientServiceImpl, sessionManager, posthogClient, loggingMiddlewareImpl) return mainApp, nil } - -var ( - _wireChartWorkingDirValue = util.ChartWorkingDir("/tmp/charts/") - _wireRefChartDirValue = chartRepoRepository.RefChartDir("scripts/devtron-reference-helm-charts") - _wireDefaultChartValue = chart.DefaultChart("reference-app-rolling") - _wireRefChartProxyDirValue = appStoreBean.RefChartProxyDir("scripts/devtron-reference-helm-charts") -) From f62c263a77118b478fbff4beff2e718511c19953 Mon Sep 17 00:00:00 2001 From: Asutosh Das Date: Mon, 5 Feb 2024 12:37:54 +0530 Subject: [PATCH 2/2] chore: App Store refactoring v2 (#4580) * removed registerInArgo multiple impls * extracted app metrics code * migrated envLevel app metrics code to new service * chore: Removed unused jira and migration integration (#4498) * removed unsued jira integration * removed test-suite-code * db migration conf removal * chore: removed unused injection * chore: removed dead code * added: migration script --------- Co-authored-by: Ash-exp * chore: App store dead code cleanup and restructuring (#4497) * moved chart-group in seperate code * removed unused dependency * removed dead code * extracted resource tree * moved notes * resource movement * removed unused code * removed unused dependency * commit methods * extracted status update * chore: clean up unused dead code * updated: EA mode docker file * updated: migration number --------- Co-authored-by: Ash-exp * chart ref refactoring * removed infra metrics db calls * moved app metrics repositories from /internal to /pkg * moved: const and types to bean * removed: unused const * review comments * migrated some methods from chartService to chartRefService * added dt validation service interface * minor refactoring * moved validation method - 1 * wip * removed redundant appMetrics req obj * moved app metrics bindings to wireset * removed multiple dead code * remove redundant dependency * moved ChartGroup router and rest handler to respective folder * stage 1 * gitOps refactoring * moved gitClient code to a common wrapper service * chore: AppStoreDeployment Install flow refactoring * review changes * wip * fix for unsupported charts * refactoring: App Store deployment services * minor cleanup * renamed remote package to git * renamed gitOpsRemoteOpService If and impl * migrated usages of gitService to gitOperationService * shifted git service and all gitOps clients to pkg * gitops repository usages refactor * refactored gitOpsRepository usages * gitlab client creation refactoring * renamed util/ChartService * reverted renaming changes * reverted renaming changes * reverted renaming changes * wip * wip * removed typo * changes * changes * chore: sanity after ent sync * added: todo comment * fix: new api added for getting ciPipelineDetails by only ciPipelineId for CLI (#3708) * new api added for getting ciPipelineDetails by only ciPipelineId * appName field added in ci-pipeline struct * appType field added in ci-pipeline struct * code review comments incorporation --------- Co-authored-by: kartik-579 Co-authored-by: Nishant <58689354+nishant-d@users.noreply.github.com> Co-authored-by: nishant Co-authored-by: Prakash --- Wire.go | 3 - api/appStore/InstalledAppRestHandler.go | 2 +- .../AppStoreDeploymentRestHandler.go | 5 +- .../deployment/CommonDeploymentRestHandler.go | 50 +- api/bean/GitOpsConfig.go | 1 + api/helm-app/HelmAppRestHandler.go | 120 ++--- api/helm-app/bean.go | 24 - api/helm-app/bean/bean.go | 82 +++ api/helm-app/{ => gRPC}/applicationClient.go | 11 +- api/helm-app/{ => gRPC}/applist.pb.go | 2 +- api/helm-app/{ => gRPC}/applist.proto | 0 api/helm-app/{ => gRPC}/applist_grpc.pb.go | 2 +- api/helm-app/mocks/HelmAppClient.go | 220 ++++---- api/helm-app/mocks/HelmAppService.go | 109 ++-- api/helm-app/{ => service}/HelmAppService.go | 146 +++--- api/helm-app/wire_helmApp.go | 14 +- .../application/k8sApplicationRestHandler.go | 2 +- api/restHandler/AppListingRestHandler.go | 28 +- api/restHandler/AppRestHandler.go | 2 +- .../app/BuildPipelineRestHandler.go | 65 +++ api/router/PipelineConfigRouter.go | 1 + client/telemetry/TelemetryEventClient.go | 10 +- .../telemetry/TelemetryEventClientExtended.go | 2 +- cmd/external-app/wire_gen.go | 64 +-- internal/util/ChartTemplateService.go | 1 + pkg/app/integrationTest/AppService_test.go | 7 +- pkg/appStore/adapter/Adapter.go | 160 ++++++ pkg/appStore/bean/bean.go | 35 +- pkg/appStore/deployment/adapter/Adapter.go | 36 ++ .../common/AppStoreDeploymentCommonService.go | 483 +----------------- .../AppStoreDeploymentFullModeService.go | 298 ----------- .../repository/InstalledAppModels.go | 69 +++ .../repository/InstalledAppRepository.go | 143 ++---- .../repository/InstalledAppVersionHistory.go | 12 + .../service/AppStoreDeploymentDBService.go | 208 ++++++++ .../service/AppStoreDeploymentService.go | 373 +++----------- .../service/AppStoreDeploymentService_test.go | 8 +- .../deployment/service/InstalledAppService.go | 101 +++- .../service/InstalledAppService_test.go | 10 +- pkg/appStore/deployment/service/Notes.go | 38 +- .../deployment/service/ResourceTree.go | 4 +- .../tool/AppStoreDeploymentArgoCdService.go | 337 +++++++----- .../tool/AppStoreDeploymentGitOpsService.go | 270 ++++++++++ .../tool/AppStoreDeploymentHelmService.go | 135 +++-- pkg/appStore/deployment/tool/bean/bean.go | 18 + pkg/appStore/util/util.go | 17 +- pkg/bean/app.go | 2 + pkg/bulkAction/BulkUpdateService.go | 2 +- pkg/chart/mocks/ChartService.go | 1 - pkg/chartRepo/ChartRepositoryService.go | 8 + .../UserTerminalAccessService.go | 2 +- .../gitOps/git/GitOperationService.go | 169 ++++-- pkg/deployment/gitOps/git/bean/bean.go | 9 + .../DeployementTemplateService.go | 18 +- .../DeployementTemplateService_test.go | 2 +- pkg/k8s/K8sCommonService.go | 4 +- pkg/k8s/application/k8sApplicationService.go | 5 +- .../application/k8sApplicationService_test.go | 2 +- .../mocks/K8sApplicationService.go | 2 +- pkg/k8s/bean.go | 2 +- .../kubernetesResourceHistoryService.go | 2 +- pkg/module/ModuleCronService.go | 23 +- pkg/module/ModuleService.go | 5 +- .../AppDeploymentTypeChangeManager.go | 10 +- pkg/pipeline/CdHandler.go | 2 +- .../DeploymentPipelineConfigService.go | 2 +- pkg/pipeline/DockerRegistryConfig.go | 5 +- pkg/pipeline/DockerRegistryConfig_test.go | 2 +- pkg/pipeline/WorkflowDagExecutor.go | 43 +- pkg/server/ServerCacheService.go | 2 +- pkg/server/ServerService.go | 5 +- pkg/sql/UtilStructs.go | 14 + pkg/webhook/helm/WebhookHelmService.go | 14 +- wire_gen.go | 38 +- 74 files changed, 2095 insertions(+), 2028 deletions(-) delete mode 100644 api/helm-app/bean.go create mode 100644 api/helm-app/bean/bean.go rename api/helm-app/{ => gRPC}/applicationClient.go (96%) rename api/helm-app/{ => gRPC}/applist.pb.go (99%) rename api/helm-app/{ => gRPC}/applist.proto (100%) rename api/helm-app/{ => gRPC}/applist_grpc.pb.go (99%) rename api/helm-app/{ => service}/HelmAppService.go (89%) create mode 100644 pkg/appStore/adapter/Adapter.go create mode 100644 pkg/appStore/deployment/adapter/Adapter.go delete mode 100644 pkg/appStore/deployment/fullMode/AppStoreDeploymentFullModeService.go create mode 100644 pkg/appStore/deployment/repository/InstalledAppModels.go create mode 100644 pkg/appStore/deployment/service/AppStoreDeploymentDBService.go create mode 100644 pkg/appStore/deployment/tool/AppStoreDeploymentGitOpsService.go create mode 100644 pkg/appStore/deployment/tool/bean/bean.go diff --git a/Wire.go b/Wire.go index eaef59be908..1a26330f4d9 100644 --- a/Wire.go +++ b/Wire.go @@ -89,7 +89,6 @@ import ( "github.com/devtron-labs/devtron/pkg/appStatus" "github.com/devtron-labs/devtron/pkg/appStore/chartGroup" repository4 "github.com/devtron-labs/devtron/pkg/appStore/chartGroup/repository" - appStoreDeploymentFullMode "github.com/devtron-labs/devtron/pkg/appStore/deployment/fullMode" "github.com/devtron-labs/devtron/pkg/appStore/deployment/service" appStoreDeploymentGitopsTool "github.com/devtron-labs/devtron/pkg/appStore/deployment/tool" "github.com/devtron-labs/devtron/pkg/appWorkflow" @@ -720,8 +719,6 @@ func InitializeApp() (*App, error) { delete2.NewDeleteServiceFullModeImpl, wire.Bind(new(delete2.DeleteServiceFullMode), new(*delete2.DeleteServiceFullModeImpl)), - appStoreDeploymentFullMode.NewAppStoreDeploymentFullModeServiceImpl, - wire.Bind(new(appStoreDeploymentFullMode.AppStoreDeploymentFullModeService), new(*appStoreDeploymentFullMode.AppStoreDeploymentFullModeServiceImpl)), appStoreDeploymentGitopsTool.NewAppStoreDeploymentArgoCdServiceImpl, wire.Bind(new(appStoreDeploymentGitopsTool.AppStoreDeploymentArgoCdService), new(*appStoreDeploymentGitopsTool.AppStoreDeploymentArgoCdServiceImpl)), // util2.NewGoJsonSchemaCustomFormatChecker, diff --git a/api/appStore/InstalledAppRestHandler.go b/api/appStore/InstalledAppRestHandler.go index c6e1427c8d9..94399e6a383 100644 --- a/api/appStore/InstalledAppRestHandler.go +++ b/api/appStore/InstalledAppRestHandler.go @@ -22,13 +22,13 @@ import ( "encoding/json" "errors" "fmt" + client "github.com/devtron-labs/devtron/api/helm-app/gRPC" "net/http" "strconv" "strings" "time" bean2 "github.com/devtron-labs/devtron/api/bean" - client "github.com/devtron-labs/devtron/api/helm-app" 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" diff --git a/api/appStore/deployment/AppStoreDeploymentRestHandler.go b/api/appStore/deployment/AppStoreDeploymentRestHandler.go index cffb21ff55b..ef8e9a28e60 100644 --- a/api/appStore/deployment/AppStoreDeploymentRestHandler.go +++ b/api/appStore/deployment/AppStoreDeploymentRestHandler.go @@ -22,6 +22,7 @@ import ( "encoding/json" "errors" "fmt" + service2 "github.com/devtron-labs/devtron/api/helm-app/service" "net/http" "strconv" "strings" @@ -67,7 +68,7 @@ type AppStoreDeploymentRestHandlerImpl struct { appStoreDeploymentService service.AppStoreDeploymentService appStoreDeploymentServiceC appStoreDeploymentCommon.AppStoreDeploymentCommonService validator *validator.Validate - helmAppService client.HelmAppService + helmAppService service2.HelmAppService helmAppRestHandler client.HelmAppRestHandler argoUserService argo.ArgoUserService attributesService attributes.AttributesService @@ -75,7 +76,7 @@ type AppStoreDeploymentRestHandlerImpl struct { func NewAppStoreDeploymentRestHandlerImpl(Logger *zap.SugaredLogger, userAuthService user.UserService, enforcer casbin.Enforcer, enforcerUtil rbac.EnforcerUtil, enforcerUtilHelm rbac.EnforcerUtilHelm, appStoreDeploymentService service.AppStoreDeploymentService, - validator *validator.Validate, helmAppService client.HelmAppService, appStoreDeploymentServiceC appStoreDeploymentCommon.AppStoreDeploymentCommonService, + validator *validator.Validate, helmAppService service2.HelmAppService, appStoreDeploymentServiceC appStoreDeploymentCommon.AppStoreDeploymentCommonService, argoUserService argo.ArgoUserService, attributesService attributes.AttributesService) *AppStoreDeploymentRestHandlerImpl { return &AppStoreDeploymentRestHandlerImpl{ Logger: Logger, diff --git a/api/appStore/deployment/CommonDeploymentRestHandler.go b/api/appStore/deployment/CommonDeploymentRestHandler.go index 16b7a871835..e6b04f65a3e 100644 --- a/api/appStore/deployment/CommonDeploymentRestHandler.go +++ b/api/appStore/deployment/CommonDeploymentRestHandler.go @@ -21,6 +21,7 @@ import ( "context" "encoding/json" "fmt" + service2 "github.com/devtron-labs/devtron/api/helm-app/service" "net/http" "strconv" "time" @@ -31,7 +32,6 @@ import ( "github.com/devtron-labs/devtron/api/restHandler/common" "github.com/devtron-labs/devtron/internal/util" appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" - appStoreDeploymentCommon "github.com/devtron-labs/devtron/pkg/appStore/deployment/common" "github.com/devtron-labs/devtron/pkg/appStore/deployment/service" "github.com/devtron-labs/devtron/pkg/auth/authorisation/casbin" "github.com/devtron-labs/devtron/pkg/auth/user" @@ -51,35 +51,33 @@ type CommonDeploymentRestHandler interface { } type CommonDeploymentRestHandlerImpl struct { - Logger *zap.SugaredLogger - userAuthService user.UserService - enforcer casbin.Enforcer - enforcerUtil rbac.EnforcerUtil - enforcerUtilHelm rbac.EnforcerUtilHelm - appStoreDeploymentService service.AppStoreDeploymentService - appStoreDeploymentServiceC appStoreDeploymentCommon.AppStoreDeploymentCommonService - validator *validator.Validate - helmAppService client.HelmAppService - helmAppRestHandler client.HelmAppRestHandler - argoUserService argo.ArgoUserService + Logger *zap.SugaredLogger + userAuthService user.UserService + enforcer casbin.Enforcer + enforcerUtil rbac.EnforcerUtil + enforcerUtilHelm rbac.EnforcerUtilHelm + appStoreDeploymentService service.AppStoreDeploymentService + validator *validator.Validate + helmAppService service2.HelmAppService + helmAppRestHandler client.HelmAppRestHandler + argoUserService argo.ArgoUserService } func NewCommonDeploymentRestHandlerImpl(Logger *zap.SugaredLogger, userAuthService user.UserService, enforcer casbin.Enforcer, enforcerUtil rbac.EnforcerUtil, enforcerUtilHelm rbac.EnforcerUtilHelm, appStoreDeploymentService service.AppStoreDeploymentService, - validator *validator.Validate, helmAppService client.HelmAppService, appStoreDeploymentServiceC appStoreDeploymentCommon.AppStoreDeploymentCommonService, + validator *validator.Validate, helmAppService service2.HelmAppService, helmAppRestHandler client.HelmAppRestHandler, argoUserService argo.ArgoUserService) *CommonDeploymentRestHandlerImpl { return &CommonDeploymentRestHandlerImpl{ - Logger: Logger, - userAuthService: userAuthService, - enforcer: enforcer, - enforcerUtil: enforcerUtil, - enforcerUtilHelm: enforcerUtilHelm, - appStoreDeploymentService: appStoreDeploymentService, - validator: validator, - helmAppService: helmAppService, - appStoreDeploymentServiceC: appStoreDeploymentServiceC, - helmAppRestHandler: helmAppRestHandler, - argoUserService: argoUserService, + Logger: Logger, + userAuthService: userAuthService, + enforcer: enforcer, + enforcerUtil: enforcerUtil, + enforcerUtilHelm: enforcerUtilHelm, + appStoreDeploymentService: appStoreDeploymentService, + validator: validator, + helmAppService: helmAppService, + helmAppRestHandler: helmAppRestHandler, + argoUserService: argoUserService, } } func (handler *CommonDeploymentRestHandlerImpl) getAppOfferingMode(installedAppId string, appId string) (string, *appStoreBean.InstallAppVersionDTO, error) { @@ -91,7 +89,7 @@ func (handler *CommonDeploymentRestHandlerImpl) getAppOfferingMode(installedAppI err = &util.ApiError{HttpStatusCode: http.StatusBadRequest, UserMessage: "invalid app id"} return appOfferingMode, installedAppDto, err } - installedAppDto, err = handler.appStoreDeploymentServiceC.GetInstalledAppByClusterNamespaceAndName(appIdentifier.ClusterId, appIdentifier.Namespace, appIdentifier.ReleaseName) + installedAppDto, err = handler.appStoreDeploymentService.GetInstalledAppByClusterNamespaceAndName(appIdentifier.ClusterId, appIdentifier.Namespace, appIdentifier.ReleaseName) if err != nil { err = &util.ApiError{HttpStatusCode: http.StatusBadRequest, UserMessage: "unable to find app in database"} return appOfferingMode, installedAppDto, err @@ -117,7 +115,7 @@ func (handler *CommonDeploymentRestHandlerImpl) getAppOfferingMode(installedAppI err = &util.ApiError{HttpStatusCode: http.StatusBadRequest, UserMessage: "invalid installed app id"} return appOfferingMode, installedAppDto, err } - installedAppDto, err = handler.appStoreDeploymentServiceC.GetInstalledAppByInstalledAppId(installedAppId) + installedAppDto, err = handler.appStoreDeploymentService.GetInstalledAppByInstalledAppId(installedAppId) if err != nil { err = &util.ApiError{HttpStatusCode: http.StatusBadRequest, UserMessage: "unable to find app in database"} return appOfferingMode, installedAppDto, err diff --git a/api/bean/GitOpsConfig.go b/api/bean/GitOpsConfig.go index 4ff2d5bd92b..1876c63fdae 100644 --- a/api/bean/GitOpsConfig.go +++ b/api/bean/GitOpsConfig.go @@ -13,6 +13,7 @@ type GitOpsConfigDto struct { BitBucketWorkspaceId string `json:"bitBucketWorkspaceId"` BitBucketProjectKey string `json:"bitBucketProjectKey"` + // TODO refactoring: create different struct for internal fields GitRepoName string `json:"gitRepoName"` UserEmailId string `json:"userEmailId"` Description string `json:"description"` diff --git a/api/helm-app/HelmAppRestHandler.go b/api/helm-app/HelmAppRestHandler.go index 92593473084..45e504c08fe 100644 --- a/api/helm-app/HelmAppRestHandler.go +++ b/api/helm-app/HelmAppRestHandler.go @@ -4,6 +4,9 @@ import ( "context" "encoding/json" "errors" + "github.com/devtron-labs/devtron/api/helm-app/bean" + service2 "github.com/devtron-labs/devtron/api/helm-app/service" + "github.com/devtron-labs/devtron/pkg/appStore/deployment/service" "net/http" "strconv" "strings" @@ -14,8 +17,6 @@ import ( openapi2 "github.com/devtron-labs/devtron/api/openapi/openapiClient" "github.com/devtron-labs/devtron/api/restHandler/common" "github.com/devtron-labs/devtron/internal/util" - appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" - appStoreDeploymentCommon "github.com/devtron-labs/devtron/pkg/appStore/deployment/common" "github.com/devtron-labs/devtron/pkg/attributes" "github.com/devtron-labs/devtron/pkg/auth/authorisation/casbin" "github.com/devtron-labs/devtron/pkg/auth/user" @@ -43,31 +44,32 @@ const HELM_APP_ACCESS_COUNTER = "HelmAppAccessCounter" const HELM_APP_UPDATE_COUNTER = "HelmAppUpdateCounter" type HelmAppRestHandlerImpl struct { - logger *zap.SugaredLogger - helmAppService HelmAppService - enforcer casbin.Enforcer - clusterService cluster.ClusterService - enforcerUtil rbac.EnforcerUtilHelm - appStoreDeploymentCommonService appStoreDeploymentCommon.AppStoreDeploymentCommonService - userAuthService user.UserService - attributesService attributes.AttributesService - serverEnvConfig *serverEnvConfig.ServerEnvConfig + logger *zap.SugaredLogger + helmAppService service2.HelmAppService + enforcer casbin.Enforcer + clusterService cluster.ClusterService + enforcerUtil rbac.EnforcerUtilHelm + appStoreDeploymentService service.AppStoreDeploymentService + userAuthService user.UserService + attributesService attributes.AttributesService + serverEnvConfig *serverEnvConfig.ServerEnvConfig } func NewHelmAppRestHandlerImpl(logger *zap.SugaredLogger, - helmAppService HelmAppService, enforcer casbin.Enforcer, - clusterService cluster.ClusterService, enforcerUtil rbac.EnforcerUtilHelm, appStoreDeploymentCommonService appStoreDeploymentCommon.AppStoreDeploymentCommonService, + helmAppService service2.HelmAppService, enforcer casbin.Enforcer, + clusterService cluster.ClusterService, enforcerUtil rbac.EnforcerUtilHelm, + appStoreDeploymentService service.AppStoreDeploymentService, userAuthService user.UserService, attributesService attributes.AttributesService, serverEnvConfig *serverEnvConfig.ServerEnvConfig) *HelmAppRestHandlerImpl { return &HelmAppRestHandlerImpl{ - logger: logger, - helmAppService: helmAppService, - enforcer: enforcer, - clusterService: clusterService, - enforcerUtil: enforcerUtil, - appStoreDeploymentCommonService: appStoreDeploymentCommonService, - userAuthService: userAuthService, - attributesService: attributesService, - serverEnvConfig: serverEnvConfig, + logger: logger, + helmAppService: helmAppService, + enforcer: enforcer, + clusterService: clusterService, + enforcerUtil: enforcerUtil, + appStoreDeploymentService: appStoreDeploymentService, + userAuthService: userAuthService, + attributesService: attributesService, + serverEnvConfig: serverEnvConfig, } } @@ -118,15 +120,15 @@ func (handler *HelmAppRestHandlerImpl) GetApplicationDetail(w http.ResponseWrite return } - installedApp, err := handler.appStoreDeploymentCommonService.GetInstalledAppByClusterNamespaceAndName(appIdentifier.ClusterId, appIdentifier.Namespace, appIdentifier.ReleaseName) + installedApp, err := handler.appStoreDeploymentService.GetInstalledAppByClusterNamespaceAndName(appIdentifier.ClusterId, appIdentifier.Namespace, appIdentifier.ReleaseName) if err != nil { common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) return } - res := &AppDetailAndInstalledAppInfo{ + res := &bean.AppDetailAndInstalledAppInfo{ AppDetail: appdetail, - InstalledAppInfo: convertToInstalledAppInfo(installedApp), + InstalledAppInfo: bean.ConvertToInstalledAppInfo(installedApp), } common.WriteJsonResp(w, err, res, http.StatusOK) @@ -219,15 +221,15 @@ func (handler *HelmAppRestHandlerImpl) GetReleaseInfo(w http.ResponseWriter, r * common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) return } - - installedApp, err := handler.appStoreDeploymentCommonService.GetInstalledAppByClusterNamespaceAndName(appIdentifier.ClusterId, appIdentifier.Namespace, appIdentifier.ReleaseName) + installedApp, err := handler.appStoreDeploymentService.GetInstalledAppByClusterNamespaceAndName(appIdentifier.ClusterId, appIdentifier.Namespace, appIdentifier.ReleaseName) if err != nil { common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) return } - res := &ReleaseAndInstalledAppInfo{ + + res := &bean.ReleaseAndInstalledAppInfo{ ReleaseInfo: releaseInfo, - InstalledAppInfo: convertToInstalledAppInfo(installedApp), + InstalledAppInfo: bean.ConvertToInstalledAppInfo(installedApp), } common.WriteJsonResp(w, err, res, http.StatusOK) @@ -306,7 +308,7 @@ func (handler *HelmAppRestHandlerImpl) DeleteApplication(w http.ResponseWriter, // validate if the devtron-operator helm release, block that for deletion if appIdentifier.ReleaseName == handler.serverEnvConfig.DevtronHelmReleaseName && appIdentifier.Namespace == handler.serverEnvConfig.DevtronHelmReleaseNamespace && - appIdentifier.ClusterId == DEFAULT_CLUSTER_ID { + appIdentifier.ClusterId == bean.DEFAULT_CLUSTER_ID { common.WriteJsonResp(w, errors.New("cannot delete this default helm app"), nil, http.StatusForbidden) return } @@ -323,7 +325,7 @@ func (handler *HelmAppRestHandlerImpl) DeleteApplication(w http.ResponseWriter, } func (handler *HelmAppRestHandlerImpl) UpdateApplication(w http.ResponseWriter, r *http.Request) { - request := &UpdateApplicationRequestDto{} + request := &bean.UpdateApplicationRequestDto{} decoder := json.NewDecoder(r.Body) err := decoder.Decode(request) if err != nil { @@ -346,7 +348,7 @@ func (handler *HelmAppRestHandlerImpl) UpdateApplication(w http.ResponseWriter, return } //RBAC enforcer Ends - request.SourceAppType = SOURCE_EXTERNAL_HELM_APP + request.SourceAppType = bean.SOURCE_EXTERNAL_HELM_APP // update application externally res, err := handler.helmAppService.UpdateApplication(r.Context(), appIdentifier, request) if err != nil { @@ -422,57 +424,3 @@ func (handler *HelmAppRestHandlerImpl) SaveHelmAppDetailsViewedTelemetryData(w h common.WriteJsonResp(w, err, nil, http.StatusOK) } - -func convertToInstalledAppInfo(installedApp *appStoreBean.InstallAppVersionDTO) *InstalledAppInfo { - if installedApp == nil { - return nil - } - - chartInfo := installedApp.InstallAppVersionChartDTO - - return &InstalledAppInfo{ - AppId: installedApp.AppId, - EnvironmentName: installedApp.EnvironmentName, - AppOfferingMode: installedApp.AppOfferingMode, - InstalledAppId: installedApp.InstalledAppId, - InstalledAppVersionId: installedApp.InstalledAppVersionId, - AppStoreChartId: chartInfo.AppStoreChartId, - ClusterId: installedApp.ClusterId, - EnvironmentId: installedApp.EnvironmentId, - AppStoreChartRepoName: chartInfo.InstallAppVersionChartRepoDTO.RepoName, - AppStoreChartName: chartInfo.ChartName, - TeamId: installedApp.TeamId, - TeamName: installedApp.TeamName, - } -} - -type AppDetailAndInstalledAppInfo struct { - InstalledAppInfo *InstalledAppInfo `json:"installedAppInfo"` - AppDetail *AppDetail `json:"appDetail"` -} - -type ReleaseAndInstalledAppInfo struct { - InstalledAppInfo *InstalledAppInfo `json:"installedAppInfo"` - ReleaseInfo *ReleaseInfo `json:"releaseInfo"` -} - -type DeploymentHistoryAndInstalledAppInfo struct { - InstalledAppInfo *InstalledAppInfo `json:"installedAppInfo"` - DeploymentHistory []*HelmAppDeploymentDetail `json:"deploymentHistory"` -} - -type InstalledAppInfo struct { - AppId int `json:"appId"` - InstalledAppId int `json:"installedAppId"` - InstalledAppVersionId int `json:"installedAppVersionId"` - AppStoreChartId int `json:"appStoreChartId"` - EnvironmentName string `json:"environmentName"` - AppOfferingMode string `json:"appOfferingMode"` - ClusterId int `json:"clusterId"` - EnvironmentId int `json:"environmentId"` - AppStoreChartRepoName string `json:"appStoreChartRepoName"` - AppStoreChartName string `json:"appStoreChartName"` - TeamId int `json:"teamId"` - TeamName string `json:"teamName"` - DeploymentType string `json:"deploymentType"` -} diff --git a/api/helm-app/bean.go b/api/helm-app/bean.go deleted file mode 100644 index bd006b6e363..00000000000 --- a/api/helm-app/bean.go +++ /dev/null @@ -1,24 +0,0 @@ -package client - -import openapi "github.com/devtron-labs/devtron/api/helm-app/openapiClient" - -const ( - DEFAULT_CLUSTER_ID = 1 - SOURCE_DEVTRON_APP SourceAppType = "devtron-app" - SOURCE_HELM_APP SourceAppType = "helm-app" - SOURCE_EXTERNAL_HELM_APP SourceAppType = "external-helm-app" - SOURCE_UNKNOWN SourceAppType = "unknown" - ErrReleaseNotFound string = "release: not found" -) - -type SourceAppType string - -type UpdateApplicationRequestDto struct { - *openapi.UpdateReleaseRequest - SourceAppType SourceAppType `json:"-"` -} - -type UpdateApplicationWithChartInfoRequestDto struct { - *InstallReleaseRequest - SourceAppType SourceAppType `json:"-"` -} diff --git a/api/helm-app/bean/bean.go b/api/helm-app/bean/bean.go new file mode 100644 index 00000000000..f1222946e5a --- /dev/null +++ b/api/helm-app/bean/bean.go @@ -0,0 +1,82 @@ +package bean + +import ( + "github.com/devtron-labs/devtron/api/helm-app/gRPC" + openapi "github.com/devtron-labs/devtron/api/helm-app/openapiClient" + "github.com/devtron-labs/devtron/pkg/appStore/bean" +) + +const ( + DEFAULT_CLUSTER_ID = 1 + SOURCE_DEVTRON_APP SourceAppType = "devtron-app" + SOURCE_HELM_APP SourceAppType = "helm-app" + SOURCE_EXTERNAL_HELM_APP SourceAppType = "external-helm-app" + SOURCE_UNKNOWN SourceAppType = "unknown" + ErrReleaseNotFound string = "release: not found" +) + +type SourceAppType string + +type UpdateApplicationRequestDto struct { + *openapi.UpdateReleaseRequest + SourceAppType SourceAppType `json:"-"` +} + +type UpdateApplicationWithChartInfoRequestDto struct { + *gRPC.InstallReleaseRequest + SourceAppType SourceAppType `json:"-"` +} + +func ConvertToInstalledAppInfo(installedApp *appStoreBean.InstallAppVersionDTO) *InstalledAppInfo { + if installedApp == nil { + return nil + } + + chartInfo := installedApp.InstallAppVersionChartDTO + + return &InstalledAppInfo{ + AppId: installedApp.AppId, + EnvironmentName: installedApp.EnvironmentName, + AppOfferingMode: installedApp.AppOfferingMode, + InstalledAppId: installedApp.InstalledAppId, + InstalledAppVersionId: installedApp.InstalledAppVersionId, + AppStoreChartId: chartInfo.AppStoreChartId, + ClusterId: installedApp.ClusterId, + EnvironmentId: installedApp.EnvironmentId, + AppStoreChartRepoName: chartInfo.InstallAppVersionChartRepoDTO.RepoName, + AppStoreChartName: chartInfo.ChartName, + TeamId: installedApp.TeamId, + TeamName: installedApp.TeamName, + } +} + +type AppDetailAndInstalledAppInfo struct { + InstalledAppInfo *InstalledAppInfo `json:"installedAppInfo"` + AppDetail *gRPC.AppDetail `json:"appDetail"` +} + +type ReleaseAndInstalledAppInfo struct { + InstalledAppInfo *InstalledAppInfo `json:"installedAppInfo"` + ReleaseInfo *gRPC.ReleaseInfo `json:"releaseInfo"` +} + +type DeploymentHistoryAndInstalledAppInfo struct { + InstalledAppInfo *InstalledAppInfo `json:"installedAppInfo"` + DeploymentHistory []*gRPC.HelmAppDeploymentDetail `json:"deploymentHistory"` +} + +type InstalledAppInfo struct { + AppId int `json:"appId"` + InstalledAppId int `json:"installedAppId"` + InstalledAppVersionId int `json:"installedAppVersionId"` + AppStoreChartId int `json:"appStoreChartId"` + EnvironmentName string `json:"environmentName"` + AppOfferingMode string `json:"appOfferingMode"` + ClusterId int `json:"clusterId"` + EnvironmentId int `json:"environmentId"` + AppStoreChartRepoName string `json:"appStoreChartRepoName"` + AppStoreChartName string `json:"appStoreChartName"` + TeamId int `json:"teamId"` + TeamName string `json:"teamName"` + DeploymentType string `json:"deploymentType"` +} diff --git a/api/helm-app/applicationClient.go b/api/helm-app/gRPC/applicationClient.go similarity index 96% rename from api/helm-app/applicationClient.go rename to api/helm-app/gRPC/applicationClient.go index 884f088f1b6..7f540df584a 100644 --- a/api/helm-app/applicationClient.go +++ b/api/helm-app/gRPC/applicationClient.go @@ -1,11 +1,9 @@ -package client +package gRPC import ( "context" "fmt" "github.com/caarlos0/env" - "github.com/devtron-labs/devtron/internal/constants" - "github.com/devtron-labs/devtron/internal/util" "go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc" "go.uber.org/zap" "google.golang.org/grpc" @@ -158,13 +156,6 @@ func (impl *HelmAppClientImpl) GetDeploymentHistory(ctx context.Context, in *App } history, err := applicationClient.GetDeploymentHistory(ctx, in) if err != nil { - if util.GetGRPCErrorDetailedMessage(err) == ErrReleaseNotFound { - err = &util.ApiError{ - Code: constants.HelmReleaseNotFound, - InternalMessage: ErrReleaseNotFound, - UserMessage: fmt.Sprintf("no release found with release name '%s'", in.ReleaseName), - } - } return nil, err } return history, nil diff --git a/api/helm-app/applist.pb.go b/api/helm-app/gRPC/applist.pb.go similarity index 99% rename from api/helm-app/applist.pb.go rename to api/helm-app/gRPC/applist.pb.go index c3f9f1f7c10..918a92a433e 100644 --- a/api/helm-app/applist.pb.go +++ b/api/helm-app/gRPC/applist.pb.go @@ -4,7 +4,7 @@ // protoc v3.9.1 // source: api/helm-app/applist.proto -package client +package gRPC import ( timestamp "github.com/golang/protobuf/ptypes/timestamp" diff --git a/api/helm-app/applist.proto b/api/helm-app/gRPC/applist.proto similarity index 100% rename from api/helm-app/applist.proto rename to api/helm-app/gRPC/applist.proto diff --git a/api/helm-app/applist_grpc.pb.go b/api/helm-app/gRPC/applist_grpc.pb.go similarity index 99% rename from api/helm-app/applist_grpc.pb.go rename to api/helm-app/gRPC/applist_grpc.pb.go index 4cc1bfa04fe..8367a07b69f 100644 --- a/api/helm-app/applist_grpc.pb.go +++ b/api/helm-app/gRPC/applist_grpc.pb.go @@ -4,7 +4,7 @@ // - protoc v3.9.1 // source: api/helm-app/applist.proto -package client +package gRPC import ( context "context" diff --git a/api/helm-app/mocks/HelmAppClient.go b/api/helm-app/mocks/HelmAppClient.go index 155cff8d8b6..ac80fdd6a9e 100644 --- a/api/helm-app/mocks/HelmAppClient.go +++ b/api/helm-app/mocks/HelmAppClient.go @@ -4,9 +4,7 @@ package mocks import ( context "context" - - client "github.com/devtron-labs/devtron/api/helm-app" - + "github.com/devtron-labs/devtron/api/helm-app/gRPC" mock "github.com/stretchr/testify/mock" ) @@ -16,23 +14,23 @@ type HelmAppClient struct { } // DeleteApplication provides a mock function with given fields: ctx, in -func (_m *HelmAppClient) DeleteApplication(ctx context.Context, in *client.ReleaseIdentifier) (*client.UninstallReleaseResponse, error) { +func (_m *HelmAppClient) DeleteApplication(ctx context.Context, in *gRPC.ReleaseIdentifier) (*gRPC.UninstallReleaseResponse, error) { ret := _m.Called(ctx, in) - var r0 *client.UninstallReleaseResponse + var r0 *gRPC.UninstallReleaseResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *client.ReleaseIdentifier) (*client.UninstallReleaseResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.ReleaseIdentifier) (*gRPC.UninstallReleaseResponse, error)); ok { return rf(ctx, in) } - if rf, ok := ret.Get(0).(func(context.Context, *client.ReleaseIdentifier) *client.UninstallReleaseResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.ReleaseIdentifier) *gRPC.UninstallReleaseResponse); ok { r0 = rf(ctx, in) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*client.UninstallReleaseResponse) + r0 = ret.Get(0).(*gRPC.UninstallReleaseResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *client.ReleaseIdentifier) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *gRPC.ReleaseIdentifier) error); ok { r1 = rf(ctx, in) } else { r1 = ret.Error(1) @@ -42,23 +40,23 @@ func (_m *HelmAppClient) DeleteApplication(ctx context.Context, in *client.Relea } // GetAppDetail provides a mock function with given fields: ctx, in -func (_m *HelmAppClient) GetAppDetail(ctx context.Context, in *client.AppDetailRequest) (*client.AppDetail, error) { +func (_m *HelmAppClient) GetAppDetail(ctx context.Context, in *gRPC.AppDetailRequest) (*gRPC.AppDetail, error) { ret := _m.Called(ctx, in) - var r0 *client.AppDetail + var r0 *gRPC.AppDetail var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *client.AppDetailRequest) (*client.AppDetail, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.AppDetailRequest) (*gRPC.AppDetail, error)); ok { return rf(ctx, in) } - if rf, ok := ret.Get(0).(func(context.Context, *client.AppDetailRequest) *client.AppDetail); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.AppDetailRequest) *gRPC.AppDetail); ok { r0 = rf(ctx, in) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*client.AppDetail) + r0 = ret.Get(0).(*gRPC.AppDetail) } } - if rf, ok := ret.Get(1).(func(context.Context, *client.AppDetailRequest) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *gRPC.AppDetailRequest) error); ok { r1 = rf(ctx, in) } else { r1 = ret.Error(1) @@ -68,23 +66,23 @@ func (_m *HelmAppClient) GetAppDetail(ctx context.Context, in *client.AppDetailR } // GetAppStatus provides a mock function with given fields: ctx, in -func (_m *HelmAppClient) GetAppStatus(ctx context.Context, in *client.AppDetailRequest) (*client.AppStatus, error) { +func (_m *HelmAppClient) GetAppStatus(ctx context.Context, in *gRPC.AppDetailRequest) (*gRPC.AppStatus, error) { ret := _m.Called(ctx, in) - var r0 *client.AppStatus + var r0 *gRPC.AppStatus var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *client.AppDetailRequest) (*client.AppStatus, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.AppDetailRequest) (*gRPC.AppStatus, error)); ok { return rf(ctx, in) } - if rf, ok := ret.Get(0).(func(context.Context, *client.AppDetailRequest) *client.AppStatus); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.AppDetailRequest) *gRPC.AppStatus); ok { r0 = rf(ctx, in) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*client.AppStatus) + r0 = ret.Get(0).(*gRPC.AppStatus) } } - if rf, ok := ret.Get(1).(func(context.Context, *client.AppDetailRequest) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *gRPC.AppDetailRequest) error); ok { r1 = rf(ctx, in) } else { r1 = ret.Error(1) @@ -94,23 +92,23 @@ func (_m *HelmAppClient) GetAppStatus(ctx context.Context, in *client.AppDetailR } // GetDeploymentDetail provides a mock function with given fields: ctx, in -func (_m *HelmAppClient) GetDeploymentDetail(ctx context.Context, in *client.DeploymentDetailRequest) (*client.DeploymentDetailResponse, error) { +func (_m *HelmAppClient) GetDeploymentDetail(ctx context.Context, in *gRPC.DeploymentDetailRequest) (*gRPC.DeploymentDetailResponse, error) { ret := _m.Called(ctx, in) - var r0 *client.DeploymentDetailResponse + var r0 *gRPC.DeploymentDetailResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *client.DeploymentDetailRequest) (*client.DeploymentDetailResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.DeploymentDetailRequest) (*gRPC.DeploymentDetailResponse, error)); ok { return rf(ctx, in) } - if rf, ok := ret.Get(0).(func(context.Context, *client.DeploymentDetailRequest) *client.DeploymentDetailResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.DeploymentDetailRequest) *gRPC.DeploymentDetailResponse); ok { r0 = rf(ctx, in) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*client.DeploymentDetailResponse) + r0 = ret.Get(0).(*gRPC.DeploymentDetailResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *client.DeploymentDetailRequest) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *gRPC.DeploymentDetailRequest) error); ok { r1 = rf(ctx, in) } else { r1 = ret.Error(1) @@ -120,23 +118,23 @@ func (_m *HelmAppClient) GetDeploymentDetail(ctx context.Context, in *client.Dep } // GetDeploymentHistory provides a mock function with given fields: ctx, in -func (_m *HelmAppClient) GetDeploymentHistory(ctx context.Context, in *client.AppDetailRequest) (*client.HelmAppDeploymentHistory, error) { +func (_m *HelmAppClient) GetDeploymentHistory(ctx context.Context, in *gRPC.AppDetailRequest) (*gRPC.HelmAppDeploymentHistory, error) { ret := _m.Called(ctx, in) - var r0 *client.HelmAppDeploymentHistory + var r0 *gRPC.HelmAppDeploymentHistory var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *client.AppDetailRequest) (*client.HelmAppDeploymentHistory, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.AppDetailRequest) (*gRPC.HelmAppDeploymentHistory, error)); ok { return rf(ctx, in) } - if rf, ok := ret.Get(0).(func(context.Context, *client.AppDetailRequest) *client.HelmAppDeploymentHistory); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.AppDetailRequest) *gRPC.HelmAppDeploymentHistory); ok { r0 = rf(ctx, in) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*client.HelmAppDeploymentHistory) + r0 = ret.Get(0).(*gRPC.HelmAppDeploymentHistory) } } - if rf, ok := ret.Get(1).(func(context.Context, *client.AppDetailRequest) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *gRPC.AppDetailRequest) error); ok { r1 = rf(ctx, in) } else { r1 = ret.Error(1) @@ -146,23 +144,23 @@ func (_m *HelmAppClient) GetDeploymentHistory(ctx context.Context, in *client.Ap } // GetDesiredManifest provides a mock function with given fields: ctx, in -func (_m *HelmAppClient) GetDesiredManifest(ctx context.Context, in *client.ObjectRequest) (*client.DesiredManifestResponse, error) { +func (_m *HelmAppClient) GetDesiredManifest(ctx context.Context, in *gRPC.ObjectRequest) (*gRPC.DesiredManifestResponse, error) { ret := _m.Called(ctx, in) - var r0 *client.DesiredManifestResponse + var r0 *gRPC.DesiredManifestResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *client.ObjectRequest) (*client.DesiredManifestResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.ObjectRequest) (*gRPC.DesiredManifestResponse, error)); ok { return rf(ctx, in) } - if rf, ok := ret.Get(0).(func(context.Context, *client.ObjectRequest) *client.DesiredManifestResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.ObjectRequest) *gRPC.DesiredManifestResponse); ok { r0 = rf(ctx, in) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*client.DesiredManifestResponse) + r0 = ret.Get(0).(*gRPC.DesiredManifestResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *client.ObjectRequest) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *gRPC.ObjectRequest) error); ok { r1 = rf(ctx, in) } else { r1 = ret.Error(1) @@ -172,23 +170,23 @@ func (_m *HelmAppClient) GetDesiredManifest(ctx context.Context, in *client.Obje } // GetNotes provides a mock function with given fields: ctx, request -func (_m *HelmAppClient) GetNotes(ctx context.Context, request *client.InstallReleaseRequest) (*client.ChartNotesResponse, error) { +func (_m *HelmAppClient) GetNotes(ctx context.Context, request *gRPC.InstallReleaseRequest) (*gRPC.ChartNotesResponse, error) { ret := _m.Called(ctx, request) - var r0 *client.ChartNotesResponse + var r0 *gRPC.ChartNotesResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *client.InstallReleaseRequest) (*client.ChartNotesResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.InstallReleaseRequest) (*gRPC.ChartNotesResponse, error)); ok { return rf(ctx, request) } - if rf, ok := ret.Get(0).(func(context.Context, *client.InstallReleaseRequest) *client.ChartNotesResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.InstallReleaseRequest) *gRPC.ChartNotesResponse); ok { r0 = rf(ctx, request) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*client.ChartNotesResponse) + r0 = ret.Get(0).(*gRPC.ChartNotesResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *client.InstallReleaseRequest) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *gRPC.InstallReleaseRequest) error); ok { r1 = rf(ctx, request) } else { r1 = ret.Error(1) @@ -198,23 +196,23 @@ func (_m *HelmAppClient) GetNotes(ctx context.Context, request *client.InstallRe } // GetValuesYaml provides a mock function with given fields: ctx, in -func (_m *HelmAppClient) GetValuesYaml(ctx context.Context, in *client.AppDetailRequest) (*client.ReleaseInfo, error) { +func (_m *HelmAppClient) GetValuesYaml(ctx context.Context, in *gRPC.AppDetailRequest) (*gRPC.ReleaseInfo, error) { ret := _m.Called(ctx, in) - var r0 *client.ReleaseInfo + var r0 *gRPC.ReleaseInfo var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *client.AppDetailRequest) (*client.ReleaseInfo, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.AppDetailRequest) (*gRPC.ReleaseInfo, error)); ok { return rf(ctx, in) } - if rf, ok := ret.Get(0).(func(context.Context, *client.AppDetailRequest) *client.ReleaseInfo); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.AppDetailRequest) *gRPC.ReleaseInfo); ok { r0 = rf(ctx, in) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*client.ReleaseInfo) + r0 = ret.Get(0).(*gRPC.ReleaseInfo) } } - if rf, ok := ret.Get(1).(func(context.Context, *client.AppDetailRequest) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *gRPC.AppDetailRequest) error); ok { r1 = rf(ctx, in) } else { r1 = ret.Error(1) @@ -224,23 +222,23 @@ func (_m *HelmAppClient) GetValuesYaml(ctx context.Context, in *client.AppDetail } // Hibernate provides a mock function with given fields: ctx, in -func (_m *HelmAppClient) Hibernate(ctx context.Context, in *client.HibernateRequest) (*client.HibernateResponse, error) { +func (_m *HelmAppClient) Hibernate(ctx context.Context, in *gRPC.HibernateRequest) (*gRPC.HibernateResponse, error) { ret := _m.Called(ctx, in) - var r0 *client.HibernateResponse + var r0 *gRPC.HibernateResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *client.HibernateRequest) (*client.HibernateResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.HibernateRequest) (*gRPC.HibernateResponse, error)); ok { return rf(ctx, in) } - if rf, ok := ret.Get(0).(func(context.Context, *client.HibernateRequest) *client.HibernateResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.HibernateRequest) *gRPC.HibernateResponse); ok { r0 = rf(ctx, in) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*client.HibernateResponse) + r0 = ret.Get(0).(*gRPC.HibernateResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *client.HibernateRequest) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *gRPC.HibernateRequest) error); ok { r1 = rf(ctx, in) } else { r1 = ret.Error(1) @@ -250,23 +248,23 @@ func (_m *HelmAppClient) Hibernate(ctx context.Context, in *client.HibernateRequ } // InstallRelease provides a mock function with given fields: ctx, in -func (_m *HelmAppClient) InstallRelease(ctx context.Context, in *client.InstallReleaseRequest) (*client.InstallReleaseResponse, error) { +func (_m *HelmAppClient) InstallRelease(ctx context.Context, in *gRPC.InstallReleaseRequest) (*gRPC.InstallReleaseResponse, error) { ret := _m.Called(ctx, in) - var r0 *client.InstallReleaseResponse + var r0 *gRPC.InstallReleaseResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *client.InstallReleaseRequest) (*client.InstallReleaseResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.InstallReleaseRequest) (*gRPC.InstallReleaseResponse, error)); ok { return rf(ctx, in) } - if rf, ok := ret.Get(0).(func(context.Context, *client.InstallReleaseRequest) *client.InstallReleaseResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.InstallReleaseRequest) *gRPC.InstallReleaseResponse); ok { r0 = rf(ctx, in) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*client.InstallReleaseResponse) + r0 = ret.Get(0).(*gRPC.InstallReleaseResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *client.InstallReleaseRequest) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *gRPC.InstallReleaseRequest) error); ok { r1 = rf(ctx, in) } else { r1 = ret.Error(1) @@ -276,23 +274,23 @@ func (_m *HelmAppClient) InstallRelease(ctx context.Context, in *client.InstallR } // InstallReleaseWithCustomChart provides a mock function with given fields: ctx, in -func (_m *HelmAppClient) InstallReleaseWithCustomChart(ctx context.Context, in *client.HelmInstallCustomRequest) (*client.HelmInstallCustomResponse, error) { +func (_m *HelmAppClient) InstallReleaseWithCustomChart(ctx context.Context, in *gRPC.HelmInstallCustomRequest) (*gRPC.HelmInstallCustomResponse, error) { ret := _m.Called(ctx, in) - var r0 *client.HelmInstallCustomResponse + var r0 *gRPC.HelmInstallCustomResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *client.HelmInstallCustomRequest) (*client.HelmInstallCustomResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.HelmInstallCustomRequest) (*gRPC.HelmInstallCustomResponse, error)); ok { return rf(ctx, in) } - if rf, ok := ret.Get(0).(func(context.Context, *client.HelmInstallCustomRequest) *client.HelmInstallCustomResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.HelmInstallCustomRequest) *gRPC.HelmInstallCustomResponse); ok { r0 = rf(ctx, in) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*client.HelmInstallCustomResponse) + r0 = ret.Get(0).(*gRPC.HelmInstallCustomResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *client.HelmInstallCustomRequest) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *gRPC.HelmInstallCustomRequest) error); ok { r1 = rf(ctx, in) } else { r1 = ret.Error(1) @@ -302,23 +300,23 @@ func (_m *HelmAppClient) InstallReleaseWithCustomChart(ctx context.Context, in * } // IsReleaseInstalled provides a mock function with given fields: ctx, in -func (_m *HelmAppClient) IsReleaseInstalled(ctx context.Context, in *client.ReleaseIdentifier) (*client.BooleanResponse, error) { +func (_m *HelmAppClient) IsReleaseInstalled(ctx context.Context, in *gRPC.ReleaseIdentifier) (*gRPC.BooleanResponse, error) { ret := _m.Called(ctx, in) - var r0 *client.BooleanResponse + var r0 *gRPC.BooleanResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *client.ReleaseIdentifier) (*client.BooleanResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.ReleaseIdentifier) (*gRPC.BooleanResponse, error)); ok { return rf(ctx, in) } - if rf, ok := ret.Get(0).(func(context.Context, *client.ReleaseIdentifier) *client.BooleanResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.ReleaseIdentifier) *gRPC.BooleanResponse); ok { r0 = rf(ctx, in) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*client.BooleanResponse) + r0 = ret.Get(0).(*gRPC.BooleanResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *client.ReleaseIdentifier) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *gRPC.ReleaseIdentifier) error); ok { r1 = rf(ctx, in) } else { r1 = ret.Error(1) @@ -328,23 +326,23 @@ func (_m *HelmAppClient) IsReleaseInstalled(ctx context.Context, in *client.Rele } // ListApplication provides a mock function with given fields: ctx, req -func (_m *HelmAppClient) ListApplication(ctx context.Context, req *client.AppListRequest) (client.ApplicationService_ListApplicationsClient, error) { +func (_m *HelmAppClient) ListApplication(ctx context.Context, req *gRPC.AppListRequest) (gRPC.ApplicationService_ListApplicationsClient, error) { ret := _m.Called(ctx, req) - var r0 client.ApplicationService_ListApplicationsClient + var r0 gRPC.ApplicationService_ListApplicationsClient var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *client.AppListRequest) (client.ApplicationService_ListApplicationsClient, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.AppListRequest) (gRPC.ApplicationService_ListApplicationsClient, error)); ok { return rf(ctx, req) } - if rf, ok := ret.Get(0).(func(context.Context, *client.AppListRequest) client.ApplicationService_ListApplicationsClient); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.AppListRequest) gRPC.ApplicationService_ListApplicationsClient); ok { r0 = rf(ctx, req) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(client.ApplicationService_ListApplicationsClient) + r0 = ret.Get(0).(gRPC.ApplicationService_ListApplicationsClient) } } - if rf, ok := ret.Get(1).(func(context.Context, *client.AppListRequest) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *gRPC.AppListRequest) error); ok { r1 = rf(ctx, req) } else { r1 = ret.Error(1) @@ -354,23 +352,23 @@ func (_m *HelmAppClient) ListApplication(ctx context.Context, req *client.AppLis } // RollbackRelease provides a mock function with given fields: ctx, in -func (_m *HelmAppClient) RollbackRelease(ctx context.Context, in *client.RollbackReleaseRequest) (*client.BooleanResponse, error) { +func (_m *HelmAppClient) RollbackRelease(ctx context.Context, in *gRPC.RollbackReleaseRequest) (*gRPC.BooleanResponse, error) { ret := _m.Called(ctx, in) - var r0 *client.BooleanResponse + var r0 *gRPC.BooleanResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *client.RollbackReleaseRequest) (*client.BooleanResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.RollbackReleaseRequest) (*gRPC.BooleanResponse, error)); ok { return rf(ctx, in) } - if rf, ok := ret.Get(0).(func(context.Context, *client.RollbackReleaseRequest) *client.BooleanResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.RollbackReleaseRequest) *gRPC.BooleanResponse); ok { r0 = rf(ctx, in) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*client.BooleanResponse) + r0 = ret.Get(0).(*gRPC.BooleanResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *client.RollbackReleaseRequest) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *gRPC.RollbackReleaseRequest) error); ok { r1 = rf(ctx, in) } else { r1 = ret.Error(1) @@ -380,23 +378,23 @@ func (_m *HelmAppClient) RollbackRelease(ctx context.Context, in *client.Rollbac } // TemplateChart provides a mock function with given fields: ctx, in -func (_m *HelmAppClient) TemplateChart(ctx context.Context, in *client.InstallReleaseRequest) (*client.TemplateChartResponse, error) { +func (_m *HelmAppClient) TemplateChart(ctx context.Context, in *gRPC.InstallReleaseRequest) (*gRPC.TemplateChartResponse, error) { ret := _m.Called(ctx, in) - var r0 *client.TemplateChartResponse + var r0 *gRPC.TemplateChartResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *client.InstallReleaseRequest) (*client.TemplateChartResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.InstallReleaseRequest) (*gRPC.TemplateChartResponse, error)); ok { return rf(ctx, in) } - if rf, ok := ret.Get(0).(func(context.Context, *client.InstallReleaseRequest) *client.TemplateChartResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.InstallReleaseRequest) *gRPC.TemplateChartResponse); ok { r0 = rf(ctx, in) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*client.TemplateChartResponse) + r0 = ret.Get(0).(*gRPC.TemplateChartResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *client.InstallReleaseRequest) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *gRPC.InstallReleaseRequest) error); ok { r1 = rf(ctx, in) } else { r1 = ret.Error(1) @@ -406,23 +404,23 @@ func (_m *HelmAppClient) TemplateChart(ctx context.Context, in *client.InstallRe } // UnHibernate provides a mock function with given fields: ctx, in -func (_m *HelmAppClient) UnHibernate(ctx context.Context, in *client.HibernateRequest) (*client.HibernateResponse, error) { +func (_m *HelmAppClient) UnHibernate(ctx context.Context, in *gRPC.HibernateRequest) (*gRPC.HibernateResponse, error) { ret := _m.Called(ctx, in) - var r0 *client.HibernateResponse + var r0 *gRPC.HibernateResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *client.HibernateRequest) (*client.HibernateResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.HibernateRequest) (*gRPC.HibernateResponse, error)); ok { return rf(ctx, in) } - if rf, ok := ret.Get(0).(func(context.Context, *client.HibernateRequest) *client.HibernateResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.HibernateRequest) *gRPC.HibernateResponse); ok { r0 = rf(ctx, in) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*client.HibernateResponse) + r0 = ret.Get(0).(*gRPC.HibernateResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *client.HibernateRequest) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *gRPC.HibernateRequest) error); ok { r1 = rf(ctx, in) } else { r1 = ret.Error(1) @@ -432,23 +430,23 @@ func (_m *HelmAppClient) UnHibernate(ctx context.Context, in *client.HibernateRe } // UpdateApplication provides a mock function with given fields: ctx, in -func (_m *HelmAppClient) UpdateApplication(ctx context.Context, in *client.UpgradeReleaseRequest) (*client.UpgradeReleaseResponse, error) { +func (_m *HelmAppClient) UpdateApplication(ctx context.Context, in *gRPC.UpgradeReleaseRequest) (*gRPC.UpgradeReleaseResponse, error) { ret := _m.Called(ctx, in) - var r0 *client.UpgradeReleaseResponse + var r0 *gRPC.UpgradeReleaseResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *client.UpgradeReleaseRequest) (*client.UpgradeReleaseResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.UpgradeReleaseRequest) (*gRPC.UpgradeReleaseResponse, error)); ok { return rf(ctx, in) } - if rf, ok := ret.Get(0).(func(context.Context, *client.UpgradeReleaseRequest) *client.UpgradeReleaseResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.UpgradeReleaseRequest) *gRPC.UpgradeReleaseResponse); ok { r0 = rf(ctx, in) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*client.UpgradeReleaseResponse) + r0 = ret.Get(0).(*gRPC.UpgradeReleaseResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *client.UpgradeReleaseRequest) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *gRPC.UpgradeReleaseRequest) error); ok { r1 = rf(ctx, in) } else { r1 = ret.Error(1) @@ -458,23 +456,23 @@ func (_m *HelmAppClient) UpdateApplication(ctx context.Context, in *client.Upgra } // UpdateApplicationWithChartInfo provides a mock function with given fields: ctx, in -func (_m *HelmAppClient) UpdateApplicationWithChartInfo(ctx context.Context, in *client.InstallReleaseRequest) (*client.UpgradeReleaseResponse, error) { +func (_m *HelmAppClient) UpdateApplicationWithChartInfo(ctx context.Context, in *gRPC.InstallReleaseRequest) (*gRPC.UpgradeReleaseResponse, error) { ret := _m.Called(ctx, in) - var r0 *client.UpgradeReleaseResponse + var r0 *gRPC.UpgradeReleaseResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *client.InstallReleaseRequest) (*client.UpgradeReleaseResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.InstallReleaseRequest) (*gRPC.UpgradeReleaseResponse, error)); ok { return rf(ctx, in) } - if rf, ok := ret.Get(0).(func(context.Context, *client.InstallReleaseRequest) *client.UpgradeReleaseResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, *gRPC.InstallReleaseRequest) *gRPC.UpgradeReleaseResponse); ok { r0 = rf(ctx, in) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*client.UpgradeReleaseResponse) + r0 = ret.Get(0).(*gRPC.UpgradeReleaseResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, *client.InstallReleaseRequest) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *gRPC.InstallReleaseRequest) error); ok { r1 = rf(ctx, in) } else { r1 = ret.Error(1) diff --git a/api/helm-app/mocks/HelmAppService.go b/api/helm-app/mocks/HelmAppService.go index 59dce9f450d..895130dd23d 100644 --- a/api/helm-app/mocks/HelmAppService.go +++ b/api/helm-app/mocks/HelmAppService.go @@ -4,8 +4,9 @@ package mocks import ( context "context" - - client "github.com/devtron-labs/devtron/api/helm-app" + "github.com/devtron-labs/devtron/api/helm-app/bean" + bean2 "github.com/devtron-labs/devtron/api/helm-app/gRPC" + client "github.com/devtron-labs/devtron/api/helm-app/service" http "net/http" @@ -88,19 +89,19 @@ func (_m *HelmAppService) EncodeAppId(appIdentifier *client.AppIdentifier) strin } // GetApplicationDetail provides a mock function with given fields: ctx, app -func (_m *HelmAppService) GetApplicationDetail(ctx context.Context, app *client.AppIdentifier) (*client.AppDetail, error) { +func (_m *HelmAppService) GetApplicationDetail(ctx context.Context, app *client.AppIdentifier) (*bean2.AppDetail, error) { ret := _m.Called(ctx, app) - var r0 *client.AppDetail + var r0 *bean2.AppDetail var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *client.AppIdentifier) (*client.AppDetail, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *client.AppIdentifier) (*bean2.AppDetail, error)); ok { return rf(ctx, app) } - if rf, ok := ret.Get(0).(func(context.Context, *client.AppIdentifier) *client.AppDetail); ok { + if rf, ok := ret.Get(0).(func(context.Context, *client.AppIdentifier) *bean2.AppDetail); ok { r0 = rf(ctx, app) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*client.AppDetail) + r0 = ret.Get(0).(*bean2.AppDetail) } } @@ -114,23 +115,23 @@ func (_m *HelmAppService) GetApplicationDetail(ctx context.Context, app *client. } // GetApplicationDetailWithFilter provides a mock function with given fields: ctx, app, resourceTreeFilter -func (_m *HelmAppService) GetApplicationDetailWithFilter(ctx context.Context, app *client.AppIdentifier, resourceTreeFilter *client.ResourceTreeFilter) (*client.AppDetail, error) { +func (_m *HelmAppService) GetApplicationDetailWithFilter(ctx context.Context, app *client.AppIdentifier, resourceTreeFilter *bean2.ResourceTreeFilter) (*bean2.AppDetail, error) { ret := _m.Called(ctx, app, resourceTreeFilter) - var r0 *client.AppDetail + var r0 *bean2.AppDetail var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *client.AppIdentifier, *client.ResourceTreeFilter) (*client.AppDetail, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *client.AppIdentifier, *bean2.ResourceTreeFilter) (*bean2.AppDetail, error)); ok { return rf(ctx, app, resourceTreeFilter) } - if rf, ok := ret.Get(0).(func(context.Context, *client.AppIdentifier, *client.ResourceTreeFilter) *client.AppDetail); ok { + if rf, ok := ret.Get(0).(func(context.Context, *client.AppIdentifier, *bean2.ResourceTreeFilter) *bean2.AppDetail); ok { r0 = rf(ctx, app, resourceTreeFilter) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*client.AppDetail) + r0 = ret.Get(0).(*bean2.AppDetail) } } - if rf, ok := ret.Get(1).(func(context.Context, *client.AppIdentifier, *client.ResourceTreeFilter) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *client.AppIdentifier, *bean2.ResourceTreeFilter) error); ok { r1 = rf(ctx, app, resourceTreeFilter) } else { r1 = ret.Error(1) @@ -164,19 +165,19 @@ func (_m *HelmAppService) GetApplicationStatus(ctx context.Context, app *client. } // GetClusterConf provides a mock function with given fields: clusterId -func (_m *HelmAppService) GetClusterConf(clusterId int) (*client.ClusterConfig, error) { +func (_m *HelmAppService) GetClusterConf(clusterId int) (*bean2.ClusterConfig, error) { ret := _m.Called(clusterId) - var r0 *client.ClusterConfig + var r0 *bean2.ClusterConfig var r1 error - if rf, ok := ret.Get(0).(func(int) (*client.ClusterConfig, error)); ok { + if rf, ok := ret.Get(0).(func(int) (*bean2.ClusterConfig, error)); ok { return rf(clusterId) } - if rf, ok := ret.Get(0).(func(int) *client.ClusterConfig); ok { + if rf, ok := ret.Get(0).(func(int) *bean2.ClusterConfig); ok { r0 = rf(clusterId) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*client.ClusterConfig) + r0 = ret.Get(0).(*bean2.ClusterConfig) } } @@ -216,19 +217,19 @@ func (_m *HelmAppService) GetDeploymentDetail(ctx context.Context, app *client.A } // GetDeploymentHistory provides a mock function with given fields: ctx, app -func (_m *HelmAppService) GetDeploymentHistory(ctx context.Context, app *client.AppIdentifier) (*client.HelmAppDeploymentHistory, error) { +func (_m *HelmAppService) GetDeploymentHistory(ctx context.Context, app *client.AppIdentifier) (*bean2.HelmAppDeploymentHistory, error) { ret := _m.Called(ctx, app) - var r0 *client.HelmAppDeploymentHistory + var r0 *bean2.HelmAppDeploymentHistory var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *client.AppIdentifier) (*client.HelmAppDeploymentHistory, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *client.AppIdentifier) (*bean2.HelmAppDeploymentHistory, error)); ok { return rf(ctx, app) } - if rf, ok := ret.Get(0).(func(context.Context, *client.AppIdentifier) *client.HelmAppDeploymentHistory); ok { + if rf, ok := ret.Get(0).(func(context.Context, *client.AppIdentifier) *bean2.HelmAppDeploymentHistory); ok { r0 = rf(ctx, app) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*client.HelmAppDeploymentHistory) + r0 = ret.Get(0).(*bean2.HelmAppDeploymentHistory) } } @@ -284,21 +285,21 @@ func (_m *HelmAppService) GetDevtronHelmAppIdentifier() *client.AppIdentifier { } // GetNotes provides a mock function with given fields: ctx, request -func (_m *HelmAppService) GetNotes(ctx context.Context, request *client.InstallReleaseRequest) (string, error) { +func (_m *HelmAppService) GetNotes(ctx context.Context, request *bean2.InstallReleaseRequest) (string, error) { ret := _m.Called(ctx, request) var r0 string var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *client.InstallReleaseRequest) (string, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *bean2.InstallReleaseRequest) (string, error)); ok { return rf(ctx, request) } - if rf, ok := ret.Get(0).(func(context.Context, *client.InstallReleaseRequest) string); ok { + if rf, ok := ret.Get(0).(func(context.Context, *bean2.InstallReleaseRequest) string); ok { r0 = rf(ctx, request) } else { r0 = ret.Get(0).(string) } - if rf, ok := ret.Get(1).(func(context.Context, *client.InstallReleaseRequest) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *bean2.InstallReleaseRequest) error); ok { r1 = rf(ctx, request) } else { r1 = ret.Error(1) @@ -308,11 +309,11 @@ func (_m *HelmAppService) GetNotes(ctx context.Context, request *client.InstallR } // GetRevisionHistoryMaxValue provides a mock function with given fields: appType -func (_m *HelmAppService) GetRevisionHistoryMaxValue(appType client.SourceAppType) int32 { +func (_m *HelmAppService) GetRevisionHistoryMaxValue(appType bean.SourceAppType) int32 { ret := _m.Called(appType) var r0 int32 - if rf, ok := ret.Get(0).(func(client.SourceAppType) int32); ok { + if rf, ok := ret.Get(0).(func(bean.SourceAppType) int32); ok { r0 = rf(appType) } else { r0 = ret.Get(0).(int32) @@ -322,19 +323,19 @@ func (_m *HelmAppService) GetRevisionHistoryMaxValue(appType client.SourceAppTyp } // GetValuesYaml provides a mock function with given fields: ctx, app -func (_m *HelmAppService) GetValuesYaml(ctx context.Context, app *client.AppIdentifier) (*client.ReleaseInfo, error) { +func (_m *HelmAppService) GetValuesYaml(ctx context.Context, app *client.AppIdentifier) (*bean2.ReleaseInfo, error) { ret := _m.Called(ctx, app) - var r0 *client.ReleaseInfo + var r0 *bean2.ReleaseInfo var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *client.AppIdentifier) (*client.ReleaseInfo, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *client.AppIdentifier) (*bean2.ReleaseInfo, error)); ok { return rf(ctx, app) } - if rf, ok := ret.Get(0).(func(context.Context, *client.AppIdentifier) *client.ReleaseInfo); ok { + if rf, ok := ret.Get(0).(func(context.Context, *client.AppIdentifier) *bean2.ReleaseInfo); ok { r0 = rf(ctx, app) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*client.ReleaseInfo) + r0 = ret.Get(0).(*bean2.ReleaseInfo) } } @@ -374,23 +375,23 @@ func (_m *HelmAppService) HibernateApplication(ctx context.Context, app *client. } // InstallRelease provides a mock function with given fields: ctx, clusterId, installReleaseRequest -func (_m *HelmAppService) InstallRelease(ctx context.Context, clusterId int, installReleaseRequest *client.InstallReleaseRequest) (*client.InstallReleaseResponse, error) { +func (_m *HelmAppService) InstallRelease(ctx context.Context, clusterId int, installReleaseRequest *bean2.InstallReleaseRequest) (*bean2.InstallReleaseResponse, error) { ret := _m.Called(ctx, clusterId, installReleaseRequest) - var r0 *client.InstallReleaseResponse + var r0 *bean2.InstallReleaseResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, int, *client.InstallReleaseRequest) (*client.InstallReleaseResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, int, *bean2.InstallReleaseRequest) (*bean2.InstallReleaseResponse, error)); ok { return rf(ctx, clusterId, installReleaseRequest) } - if rf, ok := ret.Get(0).(func(context.Context, int, *client.InstallReleaseRequest) *client.InstallReleaseResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, int, *bean2.InstallReleaseRequest) *bean2.InstallReleaseResponse); ok { r0 = rf(ctx, clusterId, installReleaseRequest) } else { if ret.Get(0) != nil { - r0 = ret.Get(0).(*client.InstallReleaseResponse) + r0 = ret.Get(0).(*bean2.InstallReleaseResponse) } } - if rf, ok := ret.Get(1).(func(context.Context, int, *client.InstallReleaseRequest) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, int, *bean2.InstallReleaseRequest) error); ok { r1 = rf(ctx, clusterId, installReleaseRequest) } else { r1 = ret.Error(1) @@ -505,15 +506,15 @@ func (_m *HelmAppService) UnHibernateApplication(ctx context.Context, app *clien } // UpdateApplication provides a mock function with given fields: ctx, app, request -func (_m *HelmAppService) UpdateApplication(ctx context.Context, app *client.AppIdentifier, request *client.UpdateApplicationRequestDto) (*openapi.UpdateReleaseResponse, error) { +func (_m *HelmAppService) UpdateApplication(ctx context.Context, app *client.AppIdentifier, request *bean.UpdateApplicationRequestDto) (*openapi.UpdateReleaseResponse, error) { ret := _m.Called(ctx, app, request) var r0 *openapi.UpdateReleaseResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *client.AppIdentifier, *client.UpdateApplicationRequestDto) (*openapi.UpdateReleaseResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *client.AppIdentifier, *bean.UpdateApplicationRequestDto) (*openapi.UpdateReleaseResponse, error)); ok { return rf(ctx, app, request) } - if rf, ok := ret.Get(0).(func(context.Context, *client.AppIdentifier, *client.UpdateApplicationRequestDto) *openapi.UpdateReleaseResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, *client.AppIdentifier, *bean.UpdateApplicationRequestDto) *openapi.UpdateReleaseResponse); ok { r0 = rf(ctx, app, request) } else { if ret.Get(0) != nil { @@ -521,7 +522,7 @@ func (_m *HelmAppService) UpdateApplication(ctx context.Context, app *client.App } } - if rf, ok := ret.Get(1).(func(context.Context, *client.AppIdentifier, *client.UpdateApplicationRequestDto) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *client.AppIdentifier, *bean.UpdateApplicationRequestDto) error); ok { r1 = rf(ctx, app, request) } else { r1 = ret.Error(1) @@ -531,15 +532,15 @@ func (_m *HelmAppService) UpdateApplication(ctx context.Context, app *client.App } // UpdateApplicationWithChartInfo provides a mock function with given fields: ctx, clusterId, request -func (_m *HelmAppService) UpdateApplicationWithChartInfo(ctx context.Context, clusterId int, request *client.UpdateApplicationWithChartInfoRequestDto) (*openapi.UpdateReleaseResponse, error) { +func (_m *HelmAppService) UpdateApplicationWithChartInfo(ctx context.Context, clusterId int, request *bean.UpdateApplicationWithChartInfoRequestDto) (*openapi.UpdateReleaseResponse, error) { ret := _m.Called(ctx, clusterId, request) var r0 *openapi.UpdateReleaseResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, int, *client.UpdateApplicationWithChartInfoRequestDto) (*openapi.UpdateReleaseResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, int, *bean.UpdateApplicationWithChartInfoRequestDto) (*openapi.UpdateReleaseResponse, error)); ok { return rf(ctx, clusterId, request) } - if rf, ok := ret.Get(0).(func(context.Context, int, *client.UpdateApplicationWithChartInfoRequestDto) *openapi.UpdateReleaseResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, int, *bean.UpdateApplicationWithChartInfoRequestDto) *openapi.UpdateReleaseResponse); ok { r0 = rf(ctx, clusterId, request) } else { if ret.Get(0) != nil { @@ -547,7 +548,7 @@ func (_m *HelmAppService) UpdateApplicationWithChartInfo(ctx context.Context, cl } } - if rf, ok := ret.Get(1).(func(context.Context, int, *client.UpdateApplicationWithChartInfoRequestDto) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, int, *bean.UpdateApplicationWithChartInfoRequestDto) error); ok { r1 = rf(ctx, clusterId, request) } else { r1 = ret.Error(1) @@ -557,15 +558,15 @@ func (_m *HelmAppService) UpdateApplicationWithChartInfo(ctx context.Context, cl } // UpdateApplicationWithChartInfoWithExtraValues provides a mock function with given fields: ctx, appIdentifier, chartRepository, extraValues, extraValuesYamlUrl, useLatestChartVersion -func (_m *HelmAppService) UpdateApplicationWithChartInfoWithExtraValues(ctx context.Context, appIdentifier *client.AppIdentifier, chartRepository *client.ChartRepository, extraValues map[string]interface{}, extraValuesYamlUrl string, useLatestChartVersion bool) (*openapi.UpdateReleaseResponse, error) { +func (_m *HelmAppService) UpdateApplicationWithChartInfoWithExtraValues(ctx context.Context, appIdentifier *client.AppIdentifier, chartRepository *bean2.ChartRepository, extraValues map[string]interface{}, extraValuesYamlUrl string, useLatestChartVersion bool) (*openapi.UpdateReleaseResponse, error) { ret := _m.Called(ctx, appIdentifier, chartRepository, extraValues, extraValuesYamlUrl, useLatestChartVersion) var r0 *openapi.UpdateReleaseResponse var r1 error - if rf, ok := ret.Get(0).(func(context.Context, *client.AppIdentifier, *client.ChartRepository, map[string]interface{}, string, bool) (*openapi.UpdateReleaseResponse, error)); ok { + if rf, ok := ret.Get(0).(func(context.Context, *client.AppIdentifier, *bean2.ChartRepository, map[string]interface{}, string, bool) (*openapi.UpdateReleaseResponse, error)); ok { return rf(ctx, appIdentifier, chartRepository, extraValues, extraValuesYamlUrl, useLatestChartVersion) } - if rf, ok := ret.Get(0).(func(context.Context, *client.AppIdentifier, *client.ChartRepository, map[string]interface{}, string, bool) *openapi.UpdateReleaseResponse); ok { + if rf, ok := ret.Get(0).(func(context.Context, *client.AppIdentifier, *bean2.ChartRepository, map[string]interface{}, string, bool) *openapi.UpdateReleaseResponse); ok { r0 = rf(ctx, appIdentifier, chartRepository, extraValues, extraValuesYamlUrl, useLatestChartVersion) } else { if ret.Get(0) != nil { @@ -573,7 +574,7 @@ func (_m *HelmAppService) UpdateApplicationWithChartInfoWithExtraValues(ctx cont } } - if rf, ok := ret.Get(1).(func(context.Context, *client.AppIdentifier, *client.ChartRepository, map[string]interface{}, string, bool) error); ok { + if rf, ok := ret.Get(1).(func(context.Context, *client.AppIdentifier, *bean2.ChartRepository, map[string]interface{}, string, bool) error); ok { r1 = rf(ctx, appIdentifier, chartRepository, extraValues, extraValuesYamlUrl, useLatestChartVersion) } else { r1 = ret.Error(1) @@ -583,11 +584,11 @@ func (_m *HelmAppService) UpdateApplicationWithChartInfoWithExtraValues(ctx cont } // ValidateOCIRegistry provides a mock function with given fields: ctx, OCIRegistryRequest -func (_m *HelmAppService) ValidateOCIRegistry(ctx context.Context, OCIRegistryRequest *client.RegistryCredential) bool { +func (_m *HelmAppService) ValidateOCIRegistry(ctx context.Context, OCIRegistryRequest *bean2.RegistryCredential) bool { ret := _m.Called(ctx, OCIRegistryRequest) var r0 bool - if rf, ok := ret.Get(0).(func(context.Context, *client.RegistryCredential) bool); ok { + if rf, ok := ret.Get(0).(func(context.Context, *bean2.RegistryCredential) bool); ok { r0 = rf(ctx, OCIRegistryRequest) } else { r0 = ret.Get(0).(bool) diff --git a/api/helm-app/HelmAppService.go b/api/helm-app/service/HelmAppService.go similarity index 89% rename from api/helm-app/HelmAppService.go rename to api/helm-app/service/HelmAppService.go index 2b5d992d031..5d98580ca7e 100644 --- a/api/helm-app/HelmAppService.go +++ b/api/helm-app/service/HelmAppService.go @@ -1,11 +1,14 @@ -package client +package service import ( "context" "errors" "fmt" "github.com/devtron-labs/common-lib/utils/k8s" + "github.com/devtron-labs/devtron/api/helm-app/bean" + "github.com/devtron-labs/devtron/api/helm-app/gRPC" "github.com/devtron-labs/devtron/api/helm-app/models" + "github.com/devtron-labs/devtron/internal/constants" repository2 "github.com/devtron-labs/devtron/internal/sql/repository/dockerRegistry" "github.com/go-pg/pg" "google.golang.org/grpc/codes" @@ -43,37 +46,37 @@ import ( type HelmAppService interface { ListHelmApplications(ctx context.Context, clusterIds []int, w http.ResponseWriter, token string, helmAuth func(token string, object string) bool) - GetApplicationDetail(ctx context.Context, app *AppIdentifier) (*AppDetail, error) - GetApplicationAndReleaseStatus(ctx context.Context, app *AppIdentifier) (*AppStatus, error) - GetApplicationDetailWithFilter(ctx context.Context, app *AppIdentifier, resourceTreeFilter *ResourceTreeFilter) (*AppDetail, error) + GetApplicationDetail(ctx context.Context, app *AppIdentifier) (*gRPC.AppDetail, error) + GetApplicationAndReleaseStatus(ctx context.Context, app *AppIdentifier) (*gRPC.AppStatus, error) + GetApplicationDetailWithFilter(ctx context.Context, app *AppIdentifier, resourceTreeFilter *gRPC.ResourceTreeFilter) (*gRPC.AppDetail, error) HibernateApplication(ctx context.Context, app *AppIdentifier, hibernateRequest *openapi.HibernateRequest) ([]*openapi.HibernateStatus, error) UnHibernateApplication(ctx context.Context, app *AppIdentifier, hibernateRequest *openapi.HibernateRequest) ([]*openapi.HibernateStatus, error) DecodeAppId(appId string) (*AppIdentifier, error) EncodeAppId(appIdentifier *AppIdentifier) string - GetDeploymentHistory(ctx context.Context, app *AppIdentifier) (*HelmAppDeploymentHistory, error) - GetValuesYaml(ctx context.Context, app *AppIdentifier) (*ReleaseInfo, error) + GetDeploymentHistory(ctx context.Context, app *AppIdentifier) (*gRPC.HelmAppDeploymentHistory, error) + GetValuesYaml(ctx context.Context, app *AppIdentifier) (*gRPC.ReleaseInfo, error) GetDesiredManifest(ctx context.Context, app *AppIdentifier, resource *openapi.ResourceIdentifier) (*openapi.DesiredManifestResponse, error) DeleteApplication(ctx context.Context, app *AppIdentifier) (*openapi.UninstallReleaseResponse, error) DeleteDBLinkedHelmApplication(ctx context.Context, app *AppIdentifier, useId int32) (*openapi.UninstallReleaseResponse, error) - UpdateApplication(ctx context.Context, app *AppIdentifier, request *UpdateApplicationRequestDto) (*openapi.UpdateReleaseResponse, error) + UpdateApplication(ctx context.Context, app *AppIdentifier, request *bean.UpdateApplicationRequestDto) (*openapi.UpdateReleaseResponse, error) GetDeploymentDetail(ctx context.Context, app *AppIdentifier, version int32) (*openapi.HelmAppDeploymentManifestDetail, error) - InstallRelease(ctx context.Context, clusterId int, installReleaseRequest *InstallReleaseRequest) (*InstallReleaseResponse, error) - UpdateApplicationWithChartInfo(ctx context.Context, clusterId int, request *UpdateApplicationWithChartInfoRequestDto) (*openapi.UpdateReleaseResponse, error) + InstallRelease(ctx context.Context, clusterId int, installReleaseRequest *gRPC.InstallReleaseRequest) (*gRPC.InstallReleaseResponse, error) + UpdateApplicationWithChartInfo(ctx context.Context, clusterId int, request *bean.UpdateApplicationWithChartInfoRequestDto) (*openapi.UpdateReleaseResponse, error) IsReleaseInstalled(ctx context.Context, app *AppIdentifier) (bool, error) RollbackRelease(ctx context.Context, app *AppIdentifier, version int32) (bool, error) - GetClusterConf(clusterId int) (*ClusterConfig, error) + GetClusterConf(clusterId int) (*gRPC.ClusterConfig, error) GetDevtronHelmAppIdentifier() *AppIdentifier - UpdateApplicationWithChartInfoWithExtraValues(ctx context.Context, appIdentifier *AppIdentifier, chartRepository *ChartRepository, extraValues map[string]interface{}, extraValuesYamlUrl string, useLatestChartVersion bool) (*openapi.UpdateReleaseResponse, error) + UpdateApplicationWithChartInfoWithExtraValues(ctx context.Context, appIdentifier *AppIdentifier, chartRepository *gRPC.ChartRepository, extraValues map[string]interface{}, extraValuesYamlUrl string, useLatestChartVersion bool) (*openapi.UpdateReleaseResponse, error) TemplateChart(ctx context.Context, templateChartRequest *openapi2.TemplateChartRequest) (*openapi2.TemplateChartResponse, error) - GetNotes(ctx context.Context, request *InstallReleaseRequest) (string, error) - ValidateOCIRegistry(ctx context.Context, OCIRegistryRequest *RegistryCredential) bool - GetRevisionHistoryMaxValue(appType SourceAppType) int32 + GetNotes(ctx context.Context, request *gRPC.InstallReleaseRequest) (string, error) + ValidateOCIRegistry(ctx context.Context, OCIRegistryRequest *gRPC.RegistryCredential) bool + GetRevisionHistoryMaxValue(appType bean.SourceAppType) int32 } type HelmAppServiceImpl struct { logger *zap.SugaredLogger clusterService cluster.ClusterService - helmAppClient HelmAppClient + helmAppClient gRPC.HelmAppClient pump connector.Pump enforcerUtil rbac.EnforcerUtilHelm serverDataStore *serverDataStore.ServerDataStore @@ -89,7 +92,7 @@ type HelmAppServiceImpl struct { } func NewHelmAppServiceImpl(Logger *zap.SugaredLogger, clusterService cluster.ClusterService, - helmAppClient HelmAppClient, pump connector.Pump, enforcerUtil rbac.EnforcerUtilHelm, + helmAppClient gRPC.HelmAppClient, pump connector.Pump, enforcerUtil rbac.EnforcerUtilHelm, serverDataStore *serverDataStore.ServerDataStore, serverEnvConfig *serverEnvConfig.ServerEnvConfig, appStoreApplicationVersionRepository appStoreDiscoverRepository.AppStoreApplicationVersionRepository, environmentService cluster.EnvironmentService, pipelineRepository pipelineConfig.PipelineRepository, @@ -127,7 +130,7 @@ func GetHelmReleaseConfig() (*HelmReleaseConfig, error) { return cfg, err } -func (impl *HelmAppServiceImpl) listApplications(ctx context.Context, clusterIds []int) (ApplicationService_ListApplicationsClient, error) { +func (impl *HelmAppServiceImpl) listApplications(ctx context.Context, clusterIds []int) (gRPC.ApplicationService_ListApplicationsClient, error) { if len(clusterIds) == 0 { return nil, nil } @@ -138,9 +141,9 @@ func (impl *HelmAppServiceImpl) listApplications(ctx context.Context, clusterIds impl.logger.Errorw("error in fetching cluster detail", "err", err) return nil, err } - req := &AppListRequest{} + req := &gRPC.AppListRequest{} for _, clusterDetail := range clusters { - config := &ClusterConfig{ + config := &gRPC.ClusterConfig{ ApiServerUrl: clusterDetail.ServerUrl, Token: clusterDetail.Config[k8s.BearerToken], ClusterId: int32(clusterDetail.Id), @@ -198,14 +201,14 @@ func (impl *HelmAppServiceImpl) ListHelmApplications(ctx context.Context, cluste return appStream.Recv() }, err, func(message interface{}) interface{} { - return impl.appListRespProtoTransformer(message.(*DeployedAppList), token, helmAuth, helmCdPipelines, installedHelmApps) + return impl.appListRespProtoTransformer(message.(*gRPC.DeployedAppList), token, helmAuth, helmCdPipelines, installedHelmApps) }) } -func (impl *HelmAppServiceImpl) hibernateReqAdaptor(hibernateRequest *openapi.HibernateRequest) *HibernateRequest { - req := &HibernateRequest{} +func (impl *HelmAppServiceImpl) hibernateReqAdaptor(hibernateRequest *openapi.HibernateRequest) *gRPC.HibernateRequest { + req := &gRPC.HibernateRequest{} for _, reqObject := range hibernateRequest.GetResources() { - obj := &ObjectIdentifier{ + obj := &gRPC.ObjectIdentifier{ Group: *reqObject.Group, Kind: *reqObject.Kind, Version: *reqObject.Version, @@ -216,7 +219,7 @@ func (impl *HelmAppServiceImpl) hibernateReqAdaptor(hibernateRequest *openapi.Hi } return req } -func (impl *HelmAppServiceImpl) hibernateResponseAdaptor(in []*HibernateStatus) []*openapi.HibernateStatus { +func (impl *HelmAppServiceImpl) hibernateResponseAdaptor(in []*gRPC.HibernateStatus) []*openapi.HibernateStatus { var resStatus []*openapi.HibernateStatus for _, status := range in { resObj := &openapi.HibernateStatus{ @@ -265,13 +268,13 @@ func (impl *HelmAppServiceImpl) UnHibernateApplication(ctx context.Context, app return response, nil } -func (impl *HelmAppServiceImpl) GetClusterConf(clusterId int) (*ClusterConfig, error) { +func (impl *HelmAppServiceImpl) GetClusterConf(clusterId int) (*gRPC.ClusterConfig, error) { cluster, err := impl.clusterService.FindById(clusterId) if err != nil { impl.logger.Errorw("error in fetching cluster detail", "err", err) return nil, err } - config := &ClusterConfig{ + config := &gRPC.ClusterConfig{ ApiServerUrl: cluster.ServerUrl, Token: cluster.Config[k8s.BearerToken], ClusterId: int32(cluster.Id), @@ -286,25 +289,25 @@ func (impl *HelmAppServiceImpl) GetClusterConf(clusterId int) (*ClusterConfig, e return config, nil } -func (impl *HelmAppServiceImpl) GetApplicationDetail(ctx context.Context, app *AppIdentifier) (*AppDetail, error) { +func (impl *HelmAppServiceImpl) GetApplicationDetail(ctx context.Context, app *AppIdentifier) (*gRPC.AppDetail, error) { return impl.getApplicationDetail(ctx, app, nil) } -func (impl *HelmAppServiceImpl) GetApplicationAndReleaseStatus(ctx context.Context, app *AppIdentifier) (*AppStatus, error) { +func (impl *HelmAppServiceImpl) GetApplicationAndReleaseStatus(ctx context.Context, app *AppIdentifier) (*gRPC.AppStatus, error) { return impl.getApplicationAndReleaseStatus(ctx, app) } -func (impl *HelmAppServiceImpl) GetApplicationDetailWithFilter(ctx context.Context, app *AppIdentifier, resourceTreeFilter *ResourceTreeFilter) (*AppDetail, error) { +func (impl *HelmAppServiceImpl) GetApplicationDetailWithFilter(ctx context.Context, app *AppIdentifier, resourceTreeFilter *gRPC.ResourceTreeFilter) (*gRPC.AppDetail, error) { return impl.getApplicationDetail(ctx, app, resourceTreeFilter) } -func (impl *HelmAppServiceImpl) getApplicationDetail(ctx context.Context, app *AppIdentifier, resourceTreeFilter *ResourceTreeFilter) (*AppDetail, error) { +func (impl *HelmAppServiceImpl) getApplicationDetail(ctx context.Context, app *AppIdentifier, resourceTreeFilter *gRPC.ResourceTreeFilter) (*gRPC.AppDetail, error) { config, err := impl.GetClusterConf(app.ClusterId) if err != nil { impl.logger.Errorw("error in fetching cluster detail", "err", err) return nil, err } - req := &AppDetailRequest{ + req := &gRPC.AppDetailRequest{ ClusterConfig: config, Namespace: app.Namespace, ReleaseName: app.ReleaseName, @@ -334,13 +337,13 @@ func (impl *HelmAppServiceImpl) getApplicationDetail(ctx context.Context, app *A return appdetail, err } -func (impl *HelmAppServiceImpl) getApplicationAndReleaseStatus(ctx context.Context, app *AppIdentifier) (*AppStatus, error) { +func (impl *HelmAppServiceImpl) getApplicationAndReleaseStatus(ctx context.Context, app *AppIdentifier) (*gRPC.AppStatus, error) { config, err := impl.GetClusterConf(app.ClusterId) if err != nil { impl.logger.Errorw("error in fetching cluster detail", "err", err) return nil, err } - req := &AppDetailRequest{ + req := &gRPC.AppDetailRequest{ ClusterConfig: config, Namespace: app.Namespace, ReleaseName: app.ReleaseName, @@ -353,28 +356,35 @@ func (impl *HelmAppServiceImpl) getApplicationAndReleaseStatus(ctx context.Conte return appStatus, err } -func (impl *HelmAppServiceImpl) GetDeploymentHistory(ctx context.Context, app *AppIdentifier) (*HelmAppDeploymentHistory, error) { +func (impl *HelmAppServiceImpl) GetDeploymentHistory(ctx context.Context, app *AppIdentifier) (*gRPC.HelmAppDeploymentHistory, error) { config, err := impl.GetClusterConf(app.ClusterId) if err != nil { impl.logger.Errorw("error in fetching cluster detail", "err", err) return nil, err } - req := &AppDetailRequest{ + req := &gRPC.AppDetailRequest{ ClusterConfig: config, Namespace: app.Namespace, ReleaseName: app.ReleaseName, } history, err := impl.helmAppClient.GetDeploymentHistory(ctx, req) + if util.GetGRPCErrorDetailedMessage(err) == bean.ErrReleaseNotFound { + err = &util.ApiError{ + Code: constants.HelmReleaseNotFound, + InternalMessage: bean.ErrReleaseNotFound, + UserMessage: fmt.Sprintf("no release found with release name '%s'", req.ReleaseName), + } + } return history, err } -func (impl *HelmAppServiceImpl) GetValuesYaml(ctx context.Context, app *AppIdentifier) (*ReleaseInfo, error) { +func (impl *HelmAppServiceImpl) GetValuesYaml(ctx context.Context, app *AppIdentifier) (*gRPC.ReleaseInfo, error) { config, err := impl.GetClusterConf(app.ClusterId) if err != nil { impl.logger.Errorw("error in fetching cluster detail", "err", err) return nil, err } - req := &AppDetailRequest{ + req := &gRPC.AppDetailRequest{ ClusterConfig: config, Namespace: app.Namespace, ReleaseName: app.ReleaseName, @@ -390,11 +400,11 @@ func (impl *HelmAppServiceImpl) GetDesiredManifest(ctx context.Context, app *App return nil, err } - req := &ObjectRequest{ + req := &gRPC.ObjectRequest{ ClusterConfig: config, ReleaseName: app.ReleaseName, ReleaseNamespace: app.Namespace, - ObjectIdentifier: &ObjectIdentifier{ + ObjectIdentifier: &gRPC.ObjectIdentifier{ Group: resource.GetGroup(), Kind: resource.GetKind(), Version: resource.GetVersion(), @@ -513,7 +523,7 @@ func (impl *HelmAppServiceImpl) DeleteApplication(ctx context.Context, app *AppI return nil, models.NamespaceNotExistError{Err: fmt.Errorf("namespace %s does not exist", app.Namespace)} } - req := &ReleaseIdentifier{ + req := &gRPC.ReleaseIdentifier{ ClusterConfig: config, ReleaseName: app.ReleaseName, ReleaseNamespace: app.Namespace, @@ -564,15 +574,15 @@ func (impl *HelmAppServiceImpl) checkIfNsExists(app *AppIdentifier) (bool, error return exists, nil } -func (impl *HelmAppServiceImpl) UpdateApplication(ctx context.Context, app *AppIdentifier, request *UpdateApplicationRequestDto) (*openapi.UpdateReleaseResponse, error) { +func (impl *HelmAppServiceImpl) UpdateApplication(ctx context.Context, app *AppIdentifier, request *bean.UpdateApplicationRequestDto) (*openapi.UpdateReleaseResponse, error) { config, err := impl.GetClusterConf(app.ClusterId) if err != nil { impl.logger.Errorw("error in fetching cluster detail", "clusterId", app.ClusterId, "err", err) return nil, err } - req := &UpgradeReleaseRequest{ - ReleaseIdentifier: &ReleaseIdentifier{ + req := &gRPC.UpgradeReleaseRequest{ + ReleaseIdentifier: &gRPC.ReleaseIdentifier{ ClusterConfig: config, ReleaseName: app.ReleaseName, ReleaseNamespace: app.Namespace, @@ -600,8 +610,8 @@ func (impl *HelmAppServiceImpl) GetDeploymentDetail(ctx context.Context, app *Ap return nil, err } - req := &DeploymentDetailRequest{ - ReleaseIdentifier: &ReleaseIdentifier{ + req := &gRPC.DeploymentDetailRequest{ + ReleaseIdentifier: &gRPC.ReleaseIdentifier{ ClusterConfig: config, ReleaseName: app.ReleaseName, ReleaseNamespace: app.Namespace, @@ -623,7 +633,7 @@ func (impl *HelmAppServiceImpl) GetDeploymentDetail(ctx context.Context, app *Ap return response, nil } -func (impl *HelmAppServiceImpl) InstallRelease(ctx context.Context, clusterId int, installReleaseRequest *InstallReleaseRequest) (*InstallReleaseResponse, error) { +func (impl *HelmAppServiceImpl) InstallRelease(ctx context.Context, clusterId int, installReleaseRequest *gRPC.InstallReleaseRequest) (*gRPC.InstallReleaseResponse, error) { config, err := impl.GetClusterConf(clusterId) if err != nil { impl.logger.Errorw("error in fetching cluster detail", "clusterId", clusterId, "err", err) @@ -642,7 +652,7 @@ func (impl *HelmAppServiceImpl) InstallRelease(ctx context.Context, clusterId in } func (impl *HelmAppServiceImpl) UpdateApplicationWithChartInfo(ctx context.Context, clusterId int, - request *UpdateApplicationWithChartInfoRequestDto) (*openapi.UpdateReleaseResponse, error) { + request *bean.UpdateApplicationWithChartInfoRequestDto) (*openapi.UpdateReleaseResponse, error) { config, err := impl.GetClusterConf(clusterId) if err != nil { impl.logger.Errorw("error in fetching cluster detail", "clusterId", clusterId, "err", err) @@ -671,7 +681,7 @@ func (impl *HelmAppServiceImpl) IsReleaseInstalled(ctx context.Context, app *App return false, err } - req := &ReleaseIdentifier{ + req := &gRPC.ReleaseIdentifier{ ClusterConfig: config, ReleaseName: app.ReleaseName, ReleaseNamespace: app.Namespace, @@ -693,8 +703,8 @@ func (impl *HelmAppServiceImpl) RollbackRelease(ctx context.Context, app *AppIde return false, err } - req := &RollbackReleaseRequest{ - ReleaseIdentifier: &ReleaseIdentifier{ + req := &gRPC.RollbackReleaseRequest{ + ReleaseIdentifier: &gRPC.ReleaseIdentifier{ ClusterConfig: config, ReleaseName: app.ReleaseName, ReleaseNamespace: app.Namespace, @@ -720,7 +730,7 @@ func (impl *HelmAppServiceImpl) GetDevtronHelmAppIdentifier() *AppIdentifier { } func (impl *HelmAppServiceImpl) UpdateApplicationWithChartInfoWithExtraValues(ctx context.Context, appIdentifier *AppIdentifier, - chartRepository *ChartRepository, extraValues map[string]interface{}, extraValuesYamlUrl string, useLatestChartVersion bool) (*openapi.UpdateReleaseResponse, error) { + chartRepository *gRPC.ChartRepository, extraValues map[string]interface{}, extraValuesYamlUrl string, useLatestChartVersion bool) (*openapi.UpdateReleaseResponse, error) { // get release info releaseInfo, err := impl.GetValuesYaml(context.Background(), appIdentifier) @@ -794,9 +804,9 @@ func (impl *HelmAppServiceImpl) UpdateApplicationWithChartInfoWithExtraValues(ct // update in helm - updateReleaseRequest := &UpdateApplicationWithChartInfoRequestDto{ - InstallReleaseRequest: &InstallReleaseRequest{ - ReleaseIdentifier: &ReleaseIdentifier{ + updateReleaseRequest := &bean.UpdateApplicationWithChartInfoRequestDto{ + InstallReleaseRequest: &gRPC.InstallReleaseRequest{ + ReleaseIdentifier: &gRPC.ReleaseIdentifier{ ReleaseName: appIdentifier.ReleaseName, ReleaseNamespace: appIdentifier.Namespace, }, @@ -804,7 +814,7 @@ func (impl *HelmAppServiceImpl) UpdateApplicationWithChartInfoWithExtraValues(ct ValuesYaml: string(mergedValuesYamlByteArr), ChartRepository: chartRepository, }, - SourceAppType: SOURCE_UNKNOWN, + SourceAppType: bean.SOURCE_UNKNOWN, } if !useLatestChartVersion { updateReleaseRequest.ChartVersion = releaseInfo.DeployedAppDetail.ChartVersion @@ -865,8 +875,8 @@ func (impl *HelmAppServiceImpl) TemplateChart(ctx context.Context, templateChart return nil, err } var IsOCIRepo bool - var registryCredential *RegistryCredential - var chartRepository *ChartRepository + var registryCredential *gRPC.RegistryCredential + var chartRepository *gRPC.ChartRepository dockerRegistryId := appStoreAppVersion.AppStore.DockerArtifactStoreId if dockerRegistryId != "" { ociRegistryConfigs := appStoreAppVersion.AppStore.DockerArtifactStore.OCIRegistryConfig @@ -882,7 +892,7 @@ func (impl *HelmAppServiceImpl) TemplateChart(ctx context.Context, templateChart } } IsOCIRepo = true - registryCredential = &RegistryCredential{ + registryCredential = &gRPC.RegistryCredential{ RegistryUrl: appStoreAppVersion.AppStore.DockerArtifactStore.RegistryURL, Username: appStoreAppVersion.AppStore.DockerArtifactStore.Username, Password: appStoreAppVersion.AppStore.DockerArtifactStore.Password, @@ -894,7 +904,7 @@ func (impl *HelmAppServiceImpl) TemplateChart(ctx context.Context, templateChart IsPublic: ociRegistryConfig.IsPublic, } } else { - chartRepository = &ChartRepository{ + chartRepository = &gRPC.ChartRepository{ Name: appStoreAppVersion.AppStore.ChartRepo.Name, Url: appStoreAppVersion.AppStore.ChartRepo.Url, Username: appStoreAppVersion.AppStore.ChartRepo.UserName, @@ -902,13 +912,13 @@ func (impl *HelmAppServiceImpl) TemplateChart(ctx context.Context, templateChart } } - installReleaseRequest := &InstallReleaseRequest{ + installReleaseRequest := &gRPC.InstallReleaseRequest{ ChartName: appStoreAppVersion.Name, ChartVersion: appStoreAppVersion.Version, ValuesYaml: *templateChartRequest.ValuesYaml, K8SVersion: k8sServerVersion.String(), ChartRepository: chartRepository, - ReleaseIdentifier: &ReleaseIdentifier{ + ReleaseIdentifier: &gRPC.ReleaseIdentifier{ ReleaseNamespace: *templateChartRequest.Namespace, ReleaseName: *templateChartRequest.ReleaseName, }, @@ -936,7 +946,7 @@ func (impl *HelmAppServiceImpl) TemplateChart(ctx context.Context, templateChart return response, nil } -func (impl *HelmAppServiceImpl) GetNotes(ctx context.Context, request *InstallReleaseRequest) (string, error) { +func (impl *HelmAppServiceImpl) GetNotes(ctx context.Context, request *gRPC.InstallReleaseRequest) (string, error) { var notesTxt string response, err := impl.helmAppClient.GetNotes(ctx, request) if err != nil { @@ -947,7 +957,7 @@ func (impl *HelmAppServiceImpl) GetNotes(ctx context.Context, request *InstallRe return notesTxt, err } -func (impl *HelmAppServiceImpl) ValidateOCIRegistry(ctx context.Context, OCIRegistryRequest *RegistryCredential) bool { +func (impl *HelmAppServiceImpl) ValidateOCIRegistry(ctx context.Context, OCIRegistryRequest *gRPC.RegistryCredential) bool { response, err := impl.helmAppClient.ValidateOCIRegistry(ctx, OCIRegistryRequest) if err != nil { impl.logger.Errorw("error in fetching chart", "err", err) @@ -985,7 +995,7 @@ func (impl *HelmAppServiceImpl) EncodeAppId(appIdentifier *AppIdentifier) string return fmt.Sprintf("%d|%s|%s", appIdentifier.ClusterId, appIdentifier.Namespace, appIdentifier.ReleaseName) } -func (impl *HelmAppServiceImpl) appListRespProtoTransformer(deployedApps *DeployedAppList, token string, helmAuth func(token string, object string) bool, helmCdPipelines []*pipelineConfig.Pipeline, installedHelmApps []*repository.InstalledApps) openapi.AppList { +func (impl *HelmAppServiceImpl) appListRespProtoTransformer(deployedApps *gRPC.DeployedAppList, token string, helmAuth func(token string, object string) bool, helmCdPipelines []*pipelineConfig.Pipeline, installedHelmApps []*repository.InstalledApps) openapi.AppList { applicationType := "HELM-APP" appList := openapi.AppList{ClusterIds: &[]int32{deployedApps.ClusterId}, ApplicationType: &applicationType} if deployedApps.Errored { @@ -1054,13 +1064,13 @@ func (impl *HelmAppServiceImpl) appListRespProtoTransformer(deployedApps *Deploy return appList } -func (impl *HelmAppServiceImpl) GetRevisionHistoryMaxValue(appType SourceAppType) int32 { +func (impl *HelmAppServiceImpl) GetRevisionHistoryMaxValue(appType bean.SourceAppType) int32 { switch appType { - case SOURCE_DEVTRON_APP: + case bean.SOURCE_DEVTRON_APP: return int32(impl.helmReleaseConfig.RevisionHistoryLimitDevtronApp) - case SOURCE_HELM_APP: + case bean.SOURCE_HELM_APP: return int32(impl.helmReleaseConfig.RevisionHistoryLimitHelmApp) - case SOURCE_EXTERNAL_HELM_APP: + case bean.SOURCE_EXTERNAL_HELM_APP: return int32(impl.helmReleaseConfig.RevisionHistoryLimitExternalHelmApp) default: return 0 diff --git a/api/helm-app/wire_helmApp.go b/api/helm-app/wire_helmApp.go index 82c492f049b..f7a453ee3b0 100644 --- a/api/helm-app/wire_helmApp.go +++ b/api/helm-app/wire_helmApp.go @@ -1,21 +1,23 @@ package client import ( + "github.com/devtron-labs/devtron/api/helm-app/gRPC" + "github.com/devtron-labs/devtron/api/helm-app/service" "github.com/devtron-labs/devtron/util/rbac" "github.com/google/wire" ) var HelmAppWireSet = wire.NewSet( - NewHelmAppClientImpl, - wire.Bind(new(HelmAppClient), new(*HelmAppClientImpl)), - GetHelmReleaseConfig, - NewHelmAppServiceImpl, - wire.Bind(new(HelmAppService), new(*HelmAppServiceImpl)), + gRPC.NewHelmAppClientImpl, + wire.Bind(new(gRPC.HelmAppClient), new(*gRPC.HelmAppClientImpl)), + service.GetHelmReleaseConfig, + service.NewHelmAppServiceImpl, + wire.Bind(new(service.HelmAppService), new(*service.HelmAppServiceImpl)), NewHelmAppRestHandlerImpl, wire.Bind(new(HelmAppRestHandler), new(*HelmAppRestHandlerImpl)), NewHelmAppRouterImpl, wire.Bind(new(HelmAppRouter), new(*HelmAppRouterImpl)), - GetConfig, + gRPC.GetConfig, rbac.NewEnforcerUtilHelmImpl, wire.Bind(new(rbac.EnforcerUtilHelm), new(*rbac.EnforcerUtilHelmImpl)), ) diff --git a/api/k8s/application/k8sApplicationRestHandler.go b/api/k8s/application/k8sApplicationRestHandler.go index 087676758eb..315ec0e15f8 100644 --- a/api/k8s/application/k8sApplicationRestHandler.go +++ b/api/k8s/application/k8sApplicationRestHandler.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "github.com/devtron-labs/common-lib/utils" + client "github.com/devtron-labs/devtron/api/helm-app/service" "net/http" "strconv" "strings" @@ -15,7 +16,6 @@ import ( "github.com/devtron-labs/common-lib/utils/k8sObjectsUtil" "github.com/devtron-labs/devtron/api/bean" "github.com/devtron-labs/devtron/api/connector" - client "github.com/devtron-labs/devtron/api/helm-app" "github.com/devtron-labs/devtron/api/restHandler/common" util2 "github.com/devtron-labs/devtron/internal/util" "github.com/devtron-labs/devtron/pkg/auth/authorisation/casbin" diff --git a/api/restHandler/AppListingRestHandler.go b/api/restHandler/AppListingRestHandler.go index 870f54bae61..6c20e37b984 100644 --- a/api/restHandler/AppListingRestHandler.go +++ b/api/restHandler/AppListingRestHandler.go @@ -21,6 +21,8 @@ import ( "context" "encoding/json" "fmt" + "github.com/devtron-labs/devtron/api/helm-app/gRPC" + client "github.com/devtron-labs/devtron/api/helm-app/service" "net/http" "strconv" "strings" @@ -33,7 +35,6 @@ import ( "github.com/devtron-labs/common-lib/utils/k8s/health" k8sObjectUtils "github.com/devtron-labs/common-lib/utils/k8sObjectsUtil" "github.com/devtron-labs/devtron/api/bean" - client "github.com/devtron-labs/devtron/api/helm-app" "github.com/devtron-labs/devtron/api/restHandler/common" "github.com/devtron-labs/devtron/client/argocdServer/application" "github.com/devtron-labs/devtron/client/cron" @@ -90,16 +91,17 @@ type AppListingRestHandler interface { } type AppListingRestHandlerImpl struct { - application application.ServiceClient - appListingService app.AppListingService - teamService team.TeamService - enforcer casbin.Enforcer - pipeline pipeline.PipelineBuilder - logger *zap.SugaredLogger - enforcerUtil rbac.EnforcerUtil - deploymentGroupService deploymentGroup.DeploymentGroupService - userService user.UserService - helmAppClient client.HelmAppClient + application application.ServiceClient + appListingService app.AppListingService + teamService team.TeamService + enforcer casbin.Enforcer + pipeline pipeline.PipelineBuilder + logger *zap.SugaredLogger + enforcerUtil rbac.EnforcerUtil + deploymentGroupService deploymentGroup.DeploymentGroupService + userService user.UserService + // TODO fix me next + helmAppClient gRPC.HelmAppClient // TODO refactoring: use HelmAppService clusterService cluster.ClusterService helmAppService client.HelmAppService argoUserService argo.ArgoUserService @@ -137,7 +139,7 @@ func NewAppListingRestHandlerImpl(application application.ServiceClient, pipeline pipeline.PipelineBuilder, logger *zap.SugaredLogger, enforcerUtil rbac.EnforcerUtil, deploymentGroupService deploymentGroup.DeploymentGroupService, userService user.UserService, - helmAppClient client.HelmAppClient, clusterService cluster.ClusterService, helmAppService client.HelmAppService, + helmAppClient gRPC.HelmAppClient, clusterService cluster.ClusterService, helmAppService client.HelmAppService, argoUserService argo.ArgoUserService, k8sCommonService k8s.K8sCommonService, installedAppService service1.InstalledAppService, cdApplicationStatusUpdateHandler cron.CdApplicationStatusUpdateHandler, pipelineRepository pipelineConfig.PipelineRepository, @@ -1578,7 +1580,7 @@ func (handler AppListingRestHandlerImpl) fetchResourceTree(w http.ResponseWriter if err != nil { handler.logger.Errorw("error in fetching cluster detail", "err", err) } - req := &client.AppDetailRequest{ + req := &gRPC.AppDetailRequest{ ClusterConfig: config, Namespace: cdPipeline.Environment.Namespace, ReleaseName: cdPipeline.DeploymentAppName, diff --git a/api/restHandler/AppRestHandler.go b/api/restHandler/AppRestHandler.go index ed0b6ab4e01..c787fd4f668 100644 --- a/api/restHandler/AppRestHandler.go +++ b/api/restHandler/AppRestHandler.go @@ -19,11 +19,11 @@ package restHandler import ( "encoding/json" + client "github.com/devtron-labs/devtron/api/helm-app/service" "net/http" "strconv" "strings" - client "github.com/devtron-labs/devtron/api/helm-app" "github.com/devtron-labs/devtron/api/restHandler/common" "github.com/devtron-labs/devtron/internal/sql/repository/helper" "github.com/devtron-labs/devtron/pkg/app" diff --git a/api/restHandler/app/BuildPipelineRestHandler.go b/api/restHandler/app/BuildPipelineRestHandler.go index cd7b6b1e5e4..ba0a97e4660 100644 --- a/api/restHandler/app/BuildPipelineRestHandler.go +++ b/api/restHandler/app/BuildPipelineRestHandler.go @@ -25,6 +25,7 @@ import ( "github.com/devtron-labs/devtron/pkg/pipeline/types" resourceGroup "github.com/devtron-labs/devtron/pkg/resourceGroup" util2 "github.com/devtron-labs/devtron/util" + "github.com/devtron-labs/devtron/util/response" "github.com/go-pg/pg" "github.com/gorilla/mux" "go.opentelemetry.io/otel" @@ -51,6 +52,7 @@ type DevtronAppBuildRestHandler interface { TriggerCiPipeline(w http.ResponseWriter, r *http.Request) GetCiPipelineMin(w http.ResponseWriter, r *http.Request) GetCIPipelineById(w http.ResponseWriter, r *http.Request) + GetCIPipelineByPipelineId(w http.ResponseWriter, r *http.Request) HandleWorkflowWebhook(w http.ResponseWriter, r *http.Request) GetBuildLogs(w http.ResponseWriter, r *http.Request) FetchWorkflowDetails(w http.ResponseWriter, r *http.Request) @@ -1170,6 +1172,69 @@ func (handler PipelineConfigRestHandlerImpl) GetCIPipelineById(w http.ResponseWr common.WriteJsonResp(w, err, ciPipeline, http.StatusOK) } +func (handler PipelineConfigRestHandlerImpl) GetCIPipelineByPipelineId(w http.ResponseWriter, r *http.Request) { + token := r.Header.Get("token") + var ciPipelineId int + var err error + v := r.URL.Query() + pipelineId := v.Get("pipelineId") + if len(pipelineId) != 0 { + ciPipelineId, err = strconv.Atoi(pipelineId) + if err != nil { + handler.Logger.Errorw("request err, GetCIPipelineByPipelineId", "err", err, "pipelineIdParam", pipelineId) + response.WriteResponse(http.StatusBadRequest, "please send valid pipelineId", w, errors.New("pipelineId id invalid")) + return + } + } else { + response.WriteResponse(http.StatusBadRequest, "please send valid pipelineId", w, errors.New("pipelineId id invalid")) + return + } + + handler.Logger.Infow("request payload, GetCIPipelineByPipelineId", "pipelineId", pipelineId) + + ciPipeline, err := handler.pipelineBuilder.GetCiPipelineById(ciPipelineId) + if err != nil { + handler.Logger.Infow("service error, GetCIPipelineById", "err", err, "pipelineId", pipelineId) + common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + return + } + + app, err := handler.pipelineBuilder.GetApp(ciPipeline.AppId) + if err != nil { + handler.Logger.Infow("service error, GetCIPipelineByPipelineId", "err", err, "appId", ciPipeline.AppId, "pipelineId", pipelineId) + common.WriteJsonResp(w, err, nil, http.StatusBadRequest) + return + } + ciPipeline.AppName = app.AppName + ciPipeline.AppType = app.AppType + + resourceName := handler.enforcerUtil.GetAppRBACNameByAppId(app.Id) + if ok := handler.enforcer.Enforce(token, casbin.ResourceApplications, casbin.ActionGet, resourceName); !ok { + common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), "Unauthorized User", http.StatusForbidden) + return + } + + pipelineData, err := handler.pipelineRepository.FindActiveByAppIdAndPipelineId(ciPipeline.AppId, ciPipelineId) + if err != nil { + common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) + return + } + var environmentIds []int + for _, pipeline := range pipelineData { + environmentIds = append(environmentIds, pipeline.EnvironmentId) + } + if handler.appWorkflowService.CheckCdPipelineByCiPipelineId(ciPipelineId) { + for _, envId := range environmentIds { + envObject := handler.enforcerUtil.GetEnvRBACNameByCiPipelineIdAndEnvId(ciPipelineId, envId) + if ok := handler.enforcer.Enforce(token, casbin.ResourceEnvironment, casbin.ActionUpdate, envObject); !ok { + common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), "Unauthorized User", http.StatusForbidden) + return + } + } + } + common.WriteJsonResp(w, err, ciPipeline, http.StatusOK) +} + func (handler PipelineConfigRestHandlerImpl) CreateMaterial(w http.ResponseWriter, r *http.Request) { token := r.Header.Get("token") decoder := json.NewDecoder(r.Body) diff --git a/api/router/PipelineConfigRouter.go b/api/router/PipelineConfigRouter.go index 17ed897e733..43dabec7f14 100644 --- a/api/router/PipelineConfigRouter.go +++ b/api/router/PipelineConfigRouter.go @@ -81,6 +81,7 @@ func (router PipelineConfigRouterImpl) initPipelineConfigRouter(configRouter *mu configRouter.Path("/env").HandlerFunc(router.restHandler.EnvConfigOverrideUpdate).Methods("PUT") configRouter.Path("/env/{appId}/{environmentId}/{chartRefId}").HandlerFunc(router.restHandler.GetEnvConfigOverride).Methods("GET") + configRouter.Path("/ci-pipeline").HandlerFunc(router.restHandler.GetCIPipelineByPipelineId).Methods("GET") configRouter.Path("/ci-pipeline").HandlerFunc(router.restHandler.CreateCiConfig).Methods("POST") configRouter.Path("/ci-pipeline/{appId}").HandlerFunc(router.restHandler.GetCiPipeline).Methods("GET") configRouter.Path("/external-ci/{appId}").HandlerFunc(router.restHandler.GetExternalCi).Methods("GET") diff --git a/client/telemetry/TelemetryEventClient.go b/client/telemetry/TelemetryEventClient.go index 3280c59002c..8449e756c56 100644 --- a/client/telemetry/TelemetryEventClient.go +++ b/client/telemetry/TelemetryEventClient.go @@ -6,13 +6,13 @@ import ( "encoding/json" "fmt" cloudProviderIdentifier "github.com/devtron-labs/common-lib/cloud-provider-identifier" + "github.com/devtron-labs/devtron/api/helm-app/gRPC" cron3 "github.com/devtron-labs/devtron/util/cron" "net/http" "time" "github.com/devtron-labs/common-lib/utils/k8s" "github.com/devtron-labs/devtron/api/bean" - client "github.com/devtron-labs/devtron/api/helm-app" "github.com/devtron-labs/devtron/internal/sql/repository" repository2 "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" "github.com/devtron-labs/devtron/pkg/attributes" @@ -55,7 +55,7 @@ type TelemetryEventClientImpl struct { moduleRepository moduleRepo.ModuleRepository serverDataStore *serverDataStore.ServerDataStore userAuditService user2.UserAuditService - helmAppClient client.HelmAppClient + helmAppClient gRPC.HelmAppClient InstalledAppRepository repository2.InstalledAppRepository userAttributesRepository repository.UserAttributesRepository cloudProviderIdentifierService cloudProviderIdentifier.ProviderIdentifierService @@ -74,7 +74,7 @@ type TelemetryEventClient interface { func NewTelemetryEventClientImpl(logger *zap.SugaredLogger, client *http.Client, clusterService cluster.ClusterService, K8sUtil *k8s.K8sServiceImpl, aCDAuthConfig *util3.ACDAuthConfig, userService user2.UserService, attributeRepo repository.AttributesRepository, ssoLoginService sso.SSOLoginService, - PosthogClient *PosthogClient, moduleRepository moduleRepo.ModuleRepository, serverDataStore *serverDataStore.ServerDataStore, userAuditService user2.UserAuditService, helmAppClient client.HelmAppClient, InstalledAppRepository repository2.InstalledAppRepository, + PosthogClient *PosthogClient, moduleRepository moduleRepo.ModuleRepository, serverDataStore *serverDataStore.ServerDataStore, userAuditService user2.UserAuditService, helmAppClient gRPC.HelmAppClient, InstalledAppRepository repository2.InstalledAppRepository, cloudProviderIdentifierService cloudProviderIdentifier.ProviderIdentifierService, cronLogger *cron3.CronLoggerImpl) (*TelemetryEventClientImpl, error) { cron := cron.New( cron.WithChain(cron.Recover(cronLogger))) @@ -240,8 +240,8 @@ func (impl *TelemetryEventClientImpl) SummaryDetailsForTelemetry() (cluster []cl ExternalHelmAppClusterCount = make(map[int32]int) for _, clusterDetail := range clusters { - req := &client.AppListRequest{} - config := &client.ClusterConfig{ + req := &gRPC.AppListRequest{} + config := &gRPC.ClusterConfig{ ApiServerUrl: clusterDetail.ServerUrl, Token: clusterDetail.Config[k8s.BearerToken], ClusterId: int32(clusterDetail.Id), diff --git a/client/telemetry/TelemetryEventClientExtended.go b/client/telemetry/TelemetryEventClientExtended.go index 386b3f33e3b..92961ab5498 100644 --- a/client/telemetry/TelemetryEventClientExtended.go +++ b/client/telemetry/TelemetryEventClientExtended.go @@ -3,13 +3,13 @@ package telemetry import ( "encoding/json" cloudProviderIdentifier "github.com/devtron-labs/common-lib/cloud-provider-identifier" + client "github.com/devtron-labs/devtron/api/helm-app/gRPC" "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config" cron3 "github.com/devtron-labs/devtron/util/cron" "net/http" "time" util2 "github.com/devtron-labs/common-lib/utils/k8s" - client "github.com/devtron-labs/devtron/api/helm-app" "github.com/devtron-labs/devtron/internal/sql/repository" "github.com/devtron-labs/devtron/internal/sql/repository/app" dockerRegistryRepository "github.com/devtron-labs/devtron/internal/sql/repository/dockerRegistry" diff --git a/cmd/external-app/wire_gen.go b/cmd/external-app/wire_gen.go index 889a659a107..badb07718f1 100644 --- a/cmd/external-app/wire_gen.go +++ b/cmd/external-app/wire_gen.go @@ -25,6 +25,8 @@ import ( "github.com/devtron-labs/devtron/api/dashboardEvent" externalLink2 "github.com/devtron-labs/devtron/api/externalLink" client2 "github.com/devtron-labs/devtron/api/helm-app" + "github.com/devtron-labs/devtron/api/helm-app/gRPC" + "github.com/devtron-labs/devtron/api/helm-app/service" application2 "github.com/devtron-labs/devtron/api/k8s/application" capacity2 "github.com/devtron-labs/devtron/api/k8s/capacity" module2 "github.com/devtron-labs/devtron/api/module" @@ -46,16 +48,16 @@ import ( "github.com/devtron-labs/devtron/internal/util" "github.com/devtron-labs/devtron/pkg/apiToken" app2 "github.com/devtron-labs/devtron/pkg/app" - repository8 "github.com/devtron-labs/devtron/pkg/appStore/chartGroup/repository" + repository7 "github.com/devtron-labs/devtron/pkg/appStore/chartGroup/repository" "github.com/devtron-labs/devtron/pkg/appStore/chartProvider" "github.com/devtron-labs/devtron/pkg/appStore/deployment/common" repository4 "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" - service3 "github.com/devtron-labs/devtron/pkg/appStore/deployment/service" + service2 "github.com/devtron-labs/devtron/pkg/appStore/deployment/service" "github.com/devtron-labs/devtron/pkg/appStore/deployment/tool" "github.com/devtron-labs/devtron/pkg/appStore/discover/repository" - "github.com/devtron-labs/devtron/pkg/appStore/discover/service" + service3 "github.com/devtron-labs/devtron/pkg/appStore/discover/service" "github.com/devtron-labs/devtron/pkg/appStore/values/repository" - service2 "github.com/devtron-labs/devtron/pkg/appStore/values/service" + service4 "github.com/devtron-labs/devtron/pkg/appStore/values/service" "github.com/devtron-labs/devtron/pkg/attributes" "github.com/devtron-labs/devtron/pkg/auth/authentication" "github.com/devtron-labs/devtron/pkg/auth/authorisation/casbin" @@ -78,7 +80,7 @@ import ( "github.com/devtron-labs/devtron/pkg/k8s/capacity" "github.com/devtron-labs/devtron/pkg/k8s/informer" "github.com/devtron-labs/devtron/pkg/kubernetesResourceAuditLogs" - repository7 "github.com/devtron-labs/devtron/pkg/kubernetesResourceAuditLogs/repository" + repository8 "github.com/devtron-labs/devtron/pkg/kubernetesResourceAuditLogs/repository" "github.com/devtron-labs/devtron/pkg/module" "github.com/devtron-labs/devtron/pkg/module/repo" "github.com/devtron-labs/devtron/pkg/module/store" @@ -187,22 +189,22 @@ func InitializeApp() (*App, error) { } chartRepositoryServiceImpl := chartRepo.NewChartRepositoryServiceImpl(sugaredLogger, chartRepoRepositoryImpl, k8sServiceImpl, clusterServiceImpl, acdAuthConfig, httpClient, serverEnvConfigServerEnvConfig) installedAppRepositoryImpl := repository4.NewInstalledAppRepositoryImpl(sugaredLogger, db) - helmClientConfig, err := client2.GetConfig() + helmClientConfig, err := gRPC.GetConfig() if err != nil { return nil, err } - helmAppClientImpl := client2.NewHelmAppClientImpl(sugaredLogger, helmClientConfig) + helmAppClientImpl := gRPC.NewHelmAppClientImpl(sugaredLogger, helmClientConfig) pumpImpl := connector.NewPumpImpl(sugaredLogger) appRepositoryImpl := app.NewAppRepositoryImpl(db, sugaredLogger) enforcerUtilHelmImpl := rbac.NewEnforcerUtilHelmImpl(sugaredLogger, clusterRepositoryImpl, teamRepositoryImpl, appRepositoryImpl, environmentRepositoryImpl, installedAppRepositoryImpl) serverDataStoreServerDataStore := serverDataStore.InitServerDataStore() appStoreApplicationVersionRepositoryImpl := appStoreDiscoverRepository.NewAppStoreApplicationVersionRepositoryImpl(sugaredLogger, db) pipelineRepositoryImpl := pipelineConfig.NewPipelineRepositoryImpl(db, sugaredLogger) - helmReleaseConfig, err := client2.GetHelmReleaseConfig() + helmReleaseConfig, err := service.GetHelmReleaseConfig() if err != nil { return nil, err } - helmAppServiceImpl := client2.NewHelmAppServiceImpl(sugaredLogger, clusterServiceImpl, helmAppClientImpl, pumpImpl, enforcerUtilHelmImpl, serverDataStoreServerDataStore, serverEnvConfigServerEnvConfig, appStoreApplicationVersionRepositoryImpl, environmentServiceImpl, pipelineRepositoryImpl, installedAppRepositoryImpl, appRepositoryImpl, clusterRepositoryImpl, k8sServiceImpl, helmReleaseConfig) + helmAppServiceImpl := service.NewHelmAppServiceImpl(sugaredLogger, clusterServiceImpl, helmAppClientImpl, pumpImpl, enforcerUtilHelmImpl, serverDataStoreServerDataStore, serverEnvConfigServerEnvConfig, appStoreApplicationVersionRepositoryImpl, environmentServiceImpl, pipelineRepositoryImpl, installedAppRepositoryImpl, appRepositoryImpl, clusterRepositoryImpl, k8sServiceImpl, helmReleaseConfig) dockerArtifactStoreRepositoryImpl := repository5.NewDockerArtifactStoreRepositoryImpl(db) dockerRegistryIpsConfigRepositoryImpl := repository5.NewDockerRegistryIpsConfigRepositoryImpl(db) ociRegistryConfigRepositoryImpl := repository5.NewOCIRegistryConfigRepositoryImpl(db) @@ -233,27 +235,40 @@ func InitializeApp() (*App, error) { return nil, err } dashboardRouterImpl := dashboard.NewDashboardRouterImpl(sugaredLogger, dashboardConfig) + chartGroupDeploymentRepositoryImpl := repository7.NewChartGroupDeploymentRepositoryImpl(db, sugaredLogger) + clusterInstalledAppsRepositoryImpl := repository4.NewClusterInstalledAppsRepositoryImpl(db, sugaredLogger) + appStoreDeploymentHelmServiceImpl := appStoreDeploymentTool.NewAppStoreDeploymentHelmServiceImpl(sugaredLogger, helmAppServiceImpl, appStoreApplicationVersionRepositoryImpl, helmAppClientImpl, installedAppRepositoryImpl, ociRegistryConfigRepositoryImpl) chartTemplateServiceImpl := util.NewChartTemplateServiceImpl(sugaredLogger) - gitOpsConfigRepositoryImpl := repository3.NewGitOpsConfigRepositoryImpl(sugaredLogger, db) - gitCliUtil := git.NewGitCliUtil(sugaredLogger) - gitFactory, err := git.NewGitFactory(sugaredLogger, gitOpsConfigRepositoryImpl, gitCliUtil) + appStoreDeploymentCommonServiceImpl := appStoreDeploymentCommon.NewAppStoreDeploymentCommonServiceImpl(sugaredLogger, appStoreApplicationVersionRepositoryImpl, chartTemplateServiceImpl) + installedAppVersionHistoryRepositoryImpl := repository4.NewInstalledAppVersionHistoryRepositoryImpl(sugaredLogger, db) + deploymentServiceTypeConfig, err := service2.GetDeploymentServiceTypeConfig() + if err != nil { + return nil, err + } + acdConfig, err := argocdServer.GetACDDeploymentConfig() if err != nil { return nil, err } + gitOpsConfigRepositoryImpl := repository3.NewGitOpsConfigRepositoryImpl(sugaredLogger, db) globalEnvVariables, err := util2.GetGlobalEnvVariables() if err != nil { return nil, err } gitOpsConfigReadServiceImpl := config.NewGitOpsConfigReadServiceImpl(sugaredLogger, gitOpsConfigRepositoryImpl, userServiceImpl, globalEnvVariables) + gitCliUtil := git.NewGitCliUtil(sugaredLogger) + gitFactory, err := git.NewGitFactory(sugaredLogger, gitOpsConfigRepositoryImpl, gitCliUtil) + if err != nil { + return nil, err + } gitOperationServiceImpl := git.NewGitOperationServiceImpl(sugaredLogger, gitFactory, gitOpsConfigReadServiceImpl, chartTemplateServiceImpl) - appStoreDeploymentCommonServiceImpl := appStoreDeploymentCommon.NewAppStoreDeploymentCommonServiceImpl(sugaredLogger, installedAppRepositoryImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl, chartTemplateServiceImpl, gitFactory, gitOpsConfigReadServiceImpl, gitOperationServiceImpl) + appStoreDeploymentServiceImpl := service2.NewAppStoreDeploymentServiceImpl(sugaredLogger, installedAppRepositoryImpl, chartGroupDeploymentRepositoryImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl, clusterInstalledAppsRepositoryImpl, appRepositoryImpl, appStoreDeploymentHelmServiceImpl, appStoreDeploymentHelmServiceImpl, environmentServiceImpl, clusterServiceImpl, helmAppServiceImpl, appStoreDeploymentCommonServiceImpl, installedAppVersionHistoryRepositoryImpl, deploymentServiceTypeConfig, acdConfig, gitOpsConfigReadServiceImpl, gitOperationServiceImpl) attributesServiceImpl := attributes.NewAttributesServiceImpl(sugaredLogger, attributesRepositoryImpl) - helmAppRestHandlerImpl := client2.NewHelmAppRestHandlerImpl(sugaredLogger, helmAppServiceImpl, enforcerImpl, clusterServiceImpl, enforcerUtilHelmImpl, appStoreDeploymentCommonServiceImpl, userServiceImpl, attributesServiceImpl, serverEnvConfigServerEnvConfig) + helmAppRestHandlerImpl := client2.NewHelmAppRestHandlerImpl(sugaredLogger, helmAppServiceImpl, enforcerImpl, clusterServiceImpl, enforcerUtilHelmImpl, appStoreDeploymentServiceImpl, userServiceImpl, attributesServiceImpl, serverEnvConfigServerEnvConfig) helmAppRouterImpl := client2.NewHelmAppRouterImpl(helmAppRestHandlerImpl) k8sCommonServiceImpl := k8s2.NewK8sCommonServiceImpl(sugaredLogger, k8sServiceImpl, clusterServiceImpl) environmentRestHandlerImpl := cluster2.NewEnvironmentRestHandlerImpl(environmentServiceImpl, sugaredLogger, userServiceImpl, validate, enforcerImpl, deleteServiceImpl, k8sServiceImpl, k8sCommonServiceImpl) environmentRouterImpl := cluster2.NewEnvironmentRouterImpl(environmentRestHandlerImpl) - k8sResourceHistoryRepositoryImpl := repository7.NewK8sResourceHistoryRepositoryImpl(db, sugaredLogger) + k8sResourceHistoryRepositoryImpl := repository8.NewK8sResourceHistoryRepositoryImpl(db, sugaredLogger) k8sResourceHistoryServiceImpl := kubernetesResourceAuditLogs.Newk8sResourceHistoryServiceImpl(k8sResourceHistoryRepositoryImpl, sugaredLogger, appRepositoryImpl, environmentRepositoryImpl) ephemeralContainersRepositoryImpl := repository2.NewEphemeralContainersRepositoryImpl(db) ephemeralContainerServiceImpl := cluster.NewEphemeralContainerServiceImpl(ephemeralContainersRepositoryImpl, sugaredLogger) @@ -268,26 +283,13 @@ func InitializeApp() (*App, error) { k8sApplicationRouterImpl := application2.NewK8sApplicationRouterImpl(k8sApplicationRestHandlerImpl) chartRepositoryRestHandlerImpl := chartRepo2.NewChartRepositoryRestHandlerImpl(sugaredLogger, userServiceImpl, chartRepositoryServiceImpl, enforcerImpl, validate, deleteServiceImpl, attributesServiceImpl) chartRepositoryRouterImpl := chartRepo2.NewChartRepositoryRouterImpl(chartRepositoryRestHandlerImpl) - appStoreServiceImpl := service.NewAppStoreServiceImpl(sugaredLogger, appStoreApplicationVersionRepositoryImpl) + appStoreServiceImpl := service3.NewAppStoreServiceImpl(sugaredLogger, appStoreApplicationVersionRepositoryImpl) appStoreRestHandlerImpl := appStoreDiscover.NewAppStoreRestHandlerImpl(sugaredLogger, userServiceImpl, appStoreServiceImpl, enforcerImpl) appStoreDiscoverRouterImpl := appStoreDiscover.NewAppStoreDiscoverRouterImpl(appStoreRestHandlerImpl) appStoreVersionValuesRepositoryImpl := appStoreValuesRepository.NewAppStoreVersionValuesRepositoryImpl(sugaredLogger, db) - appStoreValuesServiceImpl := service2.NewAppStoreValuesServiceImpl(sugaredLogger, appStoreApplicationVersionRepositoryImpl, installedAppRepositoryImpl, appStoreVersionValuesRepositoryImpl, userServiceImpl) + appStoreValuesServiceImpl := service4.NewAppStoreValuesServiceImpl(sugaredLogger, appStoreApplicationVersionRepositoryImpl, installedAppRepositoryImpl, appStoreVersionValuesRepositoryImpl, userServiceImpl) appStoreValuesRestHandlerImpl := appStoreValues.NewAppStoreValuesRestHandlerImpl(sugaredLogger, userServiceImpl, appStoreValuesServiceImpl) appStoreValuesRouterImpl := appStoreValues.NewAppStoreValuesRouterImpl(appStoreValuesRestHandlerImpl) - chartGroupDeploymentRepositoryImpl := repository8.NewChartGroupDeploymentRepositoryImpl(db, sugaredLogger) - clusterInstalledAppsRepositoryImpl := repository4.NewClusterInstalledAppsRepositoryImpl(db, sugaredLogger) - appStoreDeploymentHelmServiceImpl := appStoreDeploymentTool.NewAppStoreDeploymentHelmServiceImpl(sugaredLogger, helmAppServiceImpl, appStoreApplicationVersionRepositoryImpl, helmAppClientImpl, installedAppRepositoryImpl, appStoreDeploymentCommonServiceImpl, ociRegistryConfigRepositoryImpl, gitOperationServiceImpl) - installedAppVersionHistoryRepositoryImpl := repository4.NewInstalledAppVersionHistoryRepositoryImpl(sugaredLogger, db) - deploymentServiceTypeConfig, err := service3.GetDeploymentServiceTypeConfig() - if err != nil { - return nil, err - } - acdConfig, err := argocdServer.GetACDDeploymentConfig() - if err != nil { - return nil, err - } - appStoreDeploymentServiceImpl := service3.NewAppStoreDeploymentServiceImpl(sugaredLogger, installedAppRepositoryImpl, chartGroupDeploymentRepositoryImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl, clusterInstalledAppsRepositoryImpl, appRepositoryImpl, appStoreDeploymentHelmServiceImpl, appStoreDeploymentHelmServiceImpl, environmentServiceImpl, clusterServiceImpl, helmAppServiceImpl, appStoreDeploymentCommonServiceImpl, installedAppVersionHistoryRepositoryImpl, deploymentServiceTypeConfig, acdConfig, gitOpsConfigReadServiceImpl, gitOperationServiceImpl) appStoreDeploymentRestHandlerImpl := appStoreDeployment.NewAppStoreDeploymentRestHandlerImpl(sugaredLogger, userServiceImpl, enforcerImpl, enforcerUtilImpl, enforcerUtilHelmImpl, appStoreDeploymentServiceImpl, validate, helmAppServiceImpl, appStoreDeploymentCommonServiceImpl, helmUserServiceImpl, attributesServiceImpl) appStoreDeploymentRouterImpl := appStoreDeployment.NewAppStoreDeploymentRouterImpl(appStoreDeploymentRestHandlerImpl) chartProviderServiceImpl := chartProvider.NewChartProviderServiceImpl(sugaredLogger, chartRepoRepositoryImpl, chartRepositoryServiceImpl, dockerArtifactStoreRepositoryImpl, ociRegistryConfigRepositoryImpl) @@ -308,7 +310,7 @@ func InitializeApp() (*App, error) { } dashboardTelemetryRestHandlerImpl := dashboardEvent.NewDashboardTelemetryRestHandlerImpl(sugaredLogger, telemetryEventClientImpl) dashboardTelemetryRouterImpl := dashboardEvent.NewDashboardTelemetryRouterImpl(dashboardTelemetryRestHandlerImpl) - commonDeploymentRestHandlerImpl := appStoreDeployment.NewCommonDeploymentRestHandlerImpl(sugaredLogger, userServiceImpl, enforcerImpl, enforcerUtilImpl, enforcerUtilHelmImpl, appStoreDeploymentServiceImpl, validate, helmAppServiceImpl, appStoreDeploymentCommonServiceImpl, helmAppRestHandlerImpl, helmUserServiceImpl) + commonDeploymentRestHandlerImpl := appStoreDeployment.NewCommonDeploymentRestHandlerImpl(sugaredLogger, userServiceImpl, enforcerImpl, enforcerUtilImpl, enforcerUtilHelmImpl, appStoreDeploymentServiceImpl, validate, helmAppServiceImpl, helmAppRestHandlerImpl, helmUserServiceImpl) commonDeploymentRouterImpl := appStoreDeployment.NewCommonDeploymentRouterImpl(commonDeploymentRestHandlerImpl) externalLinkMonitoringToolRepositoryImpl := externalLink.NewExternalLinkMonitoringToolRepositoryImpl(db) externalLinkIdentifierMappingRepositoryImpl := externalLink.NewExternalLinkIdentifierMappingRepositoryImpl(db) diff --git a/internal/util/ChartTemplateService.go b/internal/util/ChartTemplateService.go index 926af8335a2..24c6153ea6f 100644 --- a/internal/util/ChartTemplateService.go +++ b/internal/util/ChartTemplateService.go @@ -429,6 +429,7 @@ func IsAcdApp(deploymentAppType string) bool { return deploymentAppType == PIPELINE_DEPLOYMENT_TYPE_ACD } +// TODO refactoring: This feature belongs to enterprise only func IsManifestDownload(deploymentAppType string) bool { return deploymentAppType == PIPELINE_DEPLOYMENT_TYPE_MANIFEST_DOWNLOAD } diff --git a/pkg/app/integrationTest/AppService_test.go b/pkg/app/integrationTest/AppService_test.go index 03ed6b64232..de06a34394e 100644 --- a/pkg/app/integrationTest/AppService_test.go +++ b/pkg/app/integrationTest/AppService_test.go @@ -4,6 +4,8 @@ import ( "encoding/csv" "encoding/json" "fmt" + "github.com/devtron-labs/devtron/api/helm-app/gRPC" + client "github.com/devtron-labs/devtron/api/helm-app/service" "log" "os" "strconv" @@ -12,7 +14,6 @@ import ( "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" pubsub "github.com/devtron-labs/common-lib/pubsub-lib" - client "github.com/devtron-labs/devtron/api/helm-app" client1 "github.com/devtron-labs/devtron/client/events" "github.com/devtron-labs/devtron/internal/sql/repository" "github.com/devtron-labs/devtron/internal/sql/repository/app" @@ -130,11 +131,11 @@ func InitAppService() *app2.AppServiceImpl { moduleActionAuditLogRepository := module.NewModuleActionAuditLogRepositoryImpl(dbConnection) clusterRepository := repository1.NewClusterRepositoryImpl(dbConnection, logger) clusterService := cluster.NewClusterServiceImplExtended(clusterRepository, nil, nil, logger, nil, nil, nil, nil, nil, nil, nil, nil) - helmClientConfig, err := client.GetConfig() + helmClientConfig, err := gRPC.GetConfig() if err != nil { log.Fatal("error in getting server helm client config, AppService_test", "err", err) } - helmAppClient := client.NewHelmAppClientImpl(logger, helmClientConfig) + helmAppClient := gRPC.NewHelmAppClientImpl(logger, helmClientConfig) helmAppService := client.NewHelmAppServiceImpl(logger, clusterService, helmAppClient, nil, nil, nil, serverEnvConfig, nil, nil, nil, nil, nil, nil, nil, nil) moduleService := module.NewModuleServiceImpl(logger, serverEnvConfig, moduleRepositoryImpl, moduleActionAuditLogRepository, helmAppService, nil, nil, nil, nil, nil, nil, nil) eventClient := client1.NewEventRESTClientImpl(logger, httpClient, eventClientConfig, pubSubClient, ciPipelineRepositoryImpl, diff --git a/pkg/appStore/adapter/Adapter.go b/pkg/appStore/adapter/Adapter.go new file mode 100644 index 00000000000..4065e755d06 --- /dev/null +++ b/pkg/appStore/adapter/Adapter.go @@ -0,0 +1,160 @@ +package adapter + +import ( + "encoding/json" + "fmt" + "github.com/devtron-labs/devtron/internal/util" + appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" + "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" +) + +// NewInstallAppModel is used to generate new repository.InstalledApps model to be saved; +// Note: Do not use for update operations +func NewInstallAppModel(chart *appStoreBean.InstallAppVersionDTO, status appStoreBean.AppstoreDeploymentStatus) *repository.InstalledApps { + installAppModel := &repository.InstalledApps{ + AppId: chart.AppId, + EnvironmentId: chart.EnvironmentId, + DeploymentAppType: chart.DeploymentAppType, + } + if status != appStoreBean.WF_UNKNOWN { + installAppModel.UpdateStatus(status) + } + installAppModel.CreateAuditLog(chart.UserId) + installAppModel.UpdateGitOpsRepoName(chart.GitOpsRepoName) + installAppModel.MarkActive() + return installAppModel +} + +// NewInstallAppVersionsModel is used to generate new repository.InstalledAppVersions model to be saved; +// Note: Do not use for update operations +func NewInstallAppVersionsModel(chart *appStoreBean.InstallAppVersionDTO) *repository.InstalledAppVersions { + installedAppVersions := &repository.InstalledAppVersions{ + InstalledAppId: chart.InstalledAppId, + AppStoreApplicationVersionId: chart.AppStoreVersion, + ValuesYaml: chart.ValuesOverrideYaml, + ReferenceValueId: chart.ReferenceValueId, + ReferenceValueKind: chart.ReferenceValueKind, + } + installedAppVersions.CreateAuditLog(chart.UserId) + installedAppVersions.MarkActive() + return installedAppVersions +} + +// NewInstallAppVersionHistoryModel is used to generate new repository.InstalledAppVersionHistory model to be saved; +// Note: Do not use for update operations +func NewInstallAppVersionHistoryModel(chart *appStoreBean.InstallAppVersionDTO, status string, helmInstallConfigDTO appStoreBean.HelmReleaseStatusConfig) (*repository.InstalledAppVersionHistory, error) { + installedAppVersions := &repository.InstalledAppVersionHistory{ + InstalledAppVersionId: chart.InstalledAppVersionId, + ValuesYamlRaw: chart.ValuesOverrideYaml, + } + helmInstallConfig, err := json.Marshal(helmInstallConfigDTO) + if err != nil { + return nil, err + } + installedAppVersions.HelmReleaseStatusConfig = string(helmInstallConfig) + installedAppVersions.SetStartedOn() + installedAppVersions.SetStatus(status) + installedAppVersions.CreateAuditLog(chart.UserId) + return installedAppVersions, nil +} + +// NewClusterInstalledAppsModel is used to generate new repository.ClusterInstalledApps model to be saved; +// Note: Do not use for update operations +func NewClusterInstalledAppsModel(chart *appStoreBean.InstallAppVersionDTO, clusterId int) *repository.ClusterInstalledApps { + clusterInstalledAppsModel := &repository.ClusterInstalledApps{ + ClusterId: clusterId, + InstalledAppId: chart.InstalledAppId, + } + clusterInstalledAppsModel.CreateAuditLog(chart.UserId) + return clusterInstalledAppsModel +} + +// NewInstalledAppDeploymentAction is used to generate appStoreBean.InstalledAppDeploymentAction from deploymentAppType +func NewInstalledAppDeploymentAction(deploymentAppType string) *appStoreBean.InstalledAppDeploymentAction { + installedAppDeploymentAction := &appStoreBean.InstalledAppDeploymentAction{} + switch deploymentAppType { + case util.PIPELINE_DEPLOYMENT_TYPE_ACD: + installedAppDeploymentAction.PerformGitOps = true + installedAppDeploymentAction.PerformACDDeployment = true + installedAppDeploymentAction.PerformHelmDeployment = false + case util.PIPELINE_DEPLOYMENT_TYPE_HELM: + installedAppDeploymentAction.PerformGitOps = false + installedAppDeploymentAction.PerformACDDeployment = false + installedAppDeploymentAction.PerformHelmDeployment = true + case util.PIPELINE_DEPLOYMENT_TYPE_MANIFEST_DOWNLOAD: + installedAppDeploymentAction.PerformGitOps = false + installedAppDeploymentAction.PerformHelmDeployment = false + installedAppDeploymentAction.PerformACDDeployment = false + } + return installedAppDeploymentAction +} + +// GenerateInstallAppVersionDTO converts repository.InstalledApps and repository.InstalledAppVersions db object to appStoreBean.InstallAppVersionDTO bean +func GenerateInstallAppVersionDTO(chart *repository.InstalledApps, installedAppVersion *repository.InstalledAppVersions) *appStoreBean.InstallAppVersionDTO { + chartVersionApp := installedAppVersion.AppStoreApplicationVersion + + var chartRepoName, chartRepoUrl, Username, Password string + if chartVersionApp.AppStore.ChartRepoId != 0 { + chartRepo := chartVersionApp.AppStore.ChartRepo + chartRepoName = chartRepo.Name + chartRepoUrl = chartRepo.Url + Username = chartRepo.UserName + Password = chartRepo.Password + } else { + chartRepo := chartVersionApp.AppStore.DockerArtifactStore + chartRepoName = chartRepo.Id + chartRepoUrl = fmt.Sprintf("%s://%s/%s", + "oci", + chartVersionApp.AppStore.DockerArtifactStore.RegistryURL, + chartVersionApp.AppStore.Name) + Username = chartVersionApp.AppStore.DockerArtifactStore.Username + Password = chartVersionApp.AppStore.DockerArtifactStore.Password + } + + return &appStoreBean.InstallAppVersionDTO{ + EnvironmentId: chart.EnvironmentId, + AppId: chart.AppId, + TeamId: chart.App.TeamId, + TeamName: chart.App.Team.Name, + AppOfferingMode: chart.App.AppOfferingMode, + ClusterId: chart.Environment.ClusterId, + Namespace: chart.Environment.Namespace, + AppName: chart.App.AppName, + EnvironmentName: chart.Environment.Name, + InstalledAppId: chart.Id, + DeploymentAppType: chart.DeploymentAppType, + + Id: installedAppVersion.Id, + InstalledAppVersionId: installedAppVersion.Id, + InstallAppVersionChartDTO: &appStoreBean.InstallAppVersionChartDTO{ + AppStoreChartId: chartVersionApp.AppStore.Id, + ChartName: chartVersionApp.Name, + ChartVersion: chartVersionApp.Version, + InstallAppVersionChartRepoDTO: &appStoreBean.InstallAppVersionChartRepoDTO{ + RepoName: chartRepoName, + RepoUrl: chartRepoUrl, + UserName: Username, + Password: Password, + }, + }, + AppStoreApplicationVersionId: installedAppVersion.AppStoreApplicationVersionId, + } +} + +// GenerateInstallAppVersionMinDTO converts repository.InstalledApps db object to appStoreBean.InstallAppVersionDTO bean; +// Note: It only generates a minimal DTO and doesn't include repository.InstalledAppVersions data +func GenerateInstallAppVersionMinDTO(chart *repository.InstalledApps) *appStoreBean.InstallAppVersionDTO { + return &appStoreBean.InstallAppVersionDTO{ + EnvironmentId: chart.EnvironmentId, + InstalledAppId: chart.Id, + AppId: chart.AppId, + AppOfferingMode: chart.App.AppOfferingMode, + ClusterId: chart.Environment.ClusterId, + Namespace: chart.Environment.Namespace, + AppName: chart.App.AppName, + EnvironmentName: chart.Environment.Name, + TeamId: chart.App.TeamId, + TeamName: chart.App.Team.Name, + DeploymentAppType: chart.DeploymentAppType, + } +} diff --git a/pkg/appStore/bean/bean.go b/pkg/appStore/bean/bean.go index 017741415ee..86456bcfb9b 100644 --- a/pkg/appStore/bean/bean.go +++ b/pkg/appStore/bean/bean.go @@ -63,7 +63,7 @@ type InstalledAppDto struct { } type InstallAppVersionDTO struct { - Id int `json:"id,omitempty"` + Id int `json:"id,omitempty"` // TODO: redundant data; refers to InstalledAppVersionId AppId int `json:"appId,omitempty"` AppName string `json:"appName,omitempty"` TeamId int `json:"teamId,omitempty"` @@ -76,8 +76,8 @@ type InstallAppVersionDTO struct { ValuesOverrideYaml string `json:"valuesOverrideYaml,omitempty"` Readme string `json:"readme,omitempty"` UserId int32 `json:"-"` - ReferenceValueId int `json:"referenceValueId, omitempty" validate:"required,number"` - ReferenceValueKind string `json:"referenceValueKind, omitempty" validate:"oneof=DEFAULT TEMPLATE DEPLOYED EXISTING"` + ReferenceValueId int `json:"referenceValueId, omitempty" validate:"required,number"` // TODO: ineffective usage of omitempty; can be removed + ReferenceValueKind string `json:"referenceValueKind, omitempty" validate:"oneof=DEFAULT TEMPLATE DEPLOYED EXISTING"` // TODO: ineffective usage of omitempty; can be removed ACDAppName string `json:"-"` Environment *repository2.Environment `json:"-"` ChartGroupEntryId int `json:"-"` @@ -96,14 +96,22 @@ type InstallAppVersionDTO struct { GitHash string `json:"gitHash"` EnvironmentName string `json:"-"` InstallAppVersionChartDTO *InstallAppVersionChartDTO `json:"-"` - DeploymentAppType string `json:"deploymentAppType"` + DeploymentAppType string `json:"deploymentAppType"` // TODO: instead of string, use enum AcdPartialDelete bool `json:"acdPartialDelete"` InstalledAppDeleteResponse *InstalledAppDeleteResponseDTO `json:"deleteResponse,omitempty"` AppStoreApplicationVersionId int - PerformGitOpsForHelmApp bool `json:"performGitOpsForHelmApp"` - PerformGitOps bool `json:"performGitOps"` - PerformACDDeployment bool `json:"performACDDeployment"` - PerformHelmDeployment bool `json:"performHelmDeployment"` +} + +func (chart *InstallAppVersionDTO) UpdateDeploymentAppType(deploymentAppType string) { + chart.DeploymentAppType = deploymentAppType +} + +// InstalledAppDeploymentAction is an internal struct for Helm App deployment; used to decide the deployment steps to be performed +type InstalledAppDeploymentAction struct { + PerformGitOpsForHelmApp bool + PerformGitOps bool + PerformACDDeployment bool + PerformHelmDeployment bool } type InstalledAppDeleteResponseDTO struct { @@ -148,7 +156,7 @@ type InstalledAppsResponse struct { EnvironmentName string `json:"environmentName"` DeployedAt time.Time `json:"deployedAt"` DeployedBy string `json:"deployedBy"` - DeploymentAppType string `json:"deploymentAppType,omitempty"` + DeploymentAppType string `json:"deploymentAppType,omitempty"` // TODO: instead of string, use enum InstalledAppsId int `json:"installedAppId"` Readme string `json:"readme"` EnvironmentId int `json:"environmentId"` @@ -343,15 +351,6 @@ func (a AppstoreDeploymentStatus) String() string { "HELM_SUCCESS"}[a] } -type PushChartToGitRequestDTO struct { - AppName string - EnvName string - ChartAppStoreName string - RepoURL string - TempChartRefDir string - UserId int32 -} - type HelmReleaseStatusConfig struct { InstallAppVersionHistoryId int Message string diff --git a/pkg/appStore/deployment/adapter/Adapter.go b/pkg/appStore/deployment/adapter/Adapter.go new file mode 100644 index 00000000000..75dd265781f --- /dev/null +++ b/pkg/appStore/deployment/adapter/Adapter.go @@ -0,0 +1,36 @@ +package adapter + +import ( + "github.com/devtron-labs/devtron/internal/util" + appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git/bean" + "k8s.io/helm/pkg/proto/hapi/chart" + "path" +) + +func ParseChartGitPushRequest(installAppRequestDTO *appStoreBean.InstallAppVersionDTO, repoURl string, tempRefChart string) *bean.PushChartToGitRequestDTO { + return &bean.PushChartToGitRequestDTO{ + AppName: installAppRequestDTO.AppName, + EnvName: installAppRequestDTO.Environment.Name, + ChartAppStoreName: installAppRequestDTO.AppStoreName, + RepoURL: repoURl, + TempChartRefDir: tempRefChart, + UserId: installAppRequestDTO.UserId, + } +} + +func ParseChartCreateRequest(appName string) *util.ChartCreateRequest { + chartPath := getRefProxyChartPath() + return &util.ChartCreateRequest{ + ChartMetaData: &chart.Metadata{ + Name: appName, + Version: "1.0.1", + }, + ChartPath: chartPath, + } +} + +func getRefProxyChartPath() string { + template := appStoreBean.CHART_PROXY_TEMPLATE + return path.Join(appStoreBean.RefChartProxyDirPath, template) +} diff --git a/pkg/appStore/deployment/common/AppStoreDeploymentCommonService.go b/pkg/appStore/deployment/common/AppStoreDeploymentCommonService.go index a62122f0712..5000cb125e4 100644 --- a/pkg/appStore/deployment/common/AppStoreDeploymentCommonService.go +++ b/pkg/appStore/deployment/common/AppStoreDeploymentCommonService.go @@ -19,223 +19,40 @@ package appStoreDeploymentCommon import ( "encoding/json" - "fmt" - "github.com/devtron-labs/devtron/api/bean" "github.com/devtron-labs/devtron/internal/util" appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" - "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" appStoreDiscoverRepository "github.com/devtron-labs/devtron/pkg/appStore/discover/repository" - util2 "github.com/devtron-labs/devtron/pkg/appStore/util" - repository2 "github.com/devtron-labs/devtron/pkg/cluster/repository" - commonBean "github.com/devtron-labs/devtron/pkg/deployment/gitOps/common/bean" - "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config" - "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git" - "github.com/go-pg/pg" - "github.com/google/go-github/github" - "github.com/microsoft/azure-devops-go-api/azuredevops" - dirCopy "github.com/otiai10/copy" - "github.com/xanzy/go-gitlab" "go.uber.org/zap" "k8s.io/helm/pkg/chartutil" - "k8s.io/helm/pkg/proto/hapi/chart" - "net/http" - "os" - "path" - "path/filepath" - "regexp" "sigs.k8s.io/yaml" ) type AppStoreDeploymentCommonService interface { - GetInstalledAppByClusterNamespaceAndName(clusterId int, namespace string, appName string) (*appStoreBean.InstallAppVersionDTO, error) - GetInstalledAppByInstalledAppId(installedAppId int) (*appStoreBean.InstallAppVersionDTO, error) - ParseGitRepoErrorResponse(err error) (bool, error) - GetValuesAndRequirementGitConfig(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*git.ChartConfig, *git.ChartConfig, error) - CreateChartProxyAndGetPath(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*util.ChartCreateResponse, error) - CreateGitOpsRepoAndPushChart(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, builtChartPath string, requirementsConfig *git.ChartConfig, valuesConfig *git.ChartConfig) (*commonBean.ChartGitAttribute, bool, string, error) - GetGitCommitConfig(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, fileString string, filename string) (*git.ChartConfig, error) + // GetValuesString will return values string from the given valuesOverrideYaml GetValuesString(chartName, valuesOverrideYaml string) (string, error) + // GetRequirementsString will return requirement dependencies for the given appStoreVersionId GetRequirementsString(appStoreVersionId int) (string, error) - GenerateManifest(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (manifestResponse *AppStoreManifestResponse, err error) - GitOpsOperations(manifestResponse *AppStoreManifestResponse, installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*AppStoreGitOpsResponse, error) - GenerateManifestAndPerformGitOperations(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*AppStoreGitOpsResponse, error) + // CreateChartProxyAndGetPath parse chart in local directory and returns path of local dir and values.yaml + CreateChartProxyAndGetPath(chartCreateRequest *util.ChartCreateRequest) (*util.ChartCreateResponse, error) } type AppStoreDeploymentCommonServiceImpl struct { logger *zap.SugaredLogger - installedAppRepository repository.InstalledAppRepository appStoreApplicationVersionRepository appStoreDiscoverRepository.AppStoreApplicationVersionRepository - environmentRepository repository2.EnvironmentRepository chartTemplateService util.ChartTemplateService - gitFactory *git.GitFactory - gitOpsConfigReadService config.GitOpsConfigReadService - gitOperationService git.GitOperationService } func NewAppStoreDeploymentCommonServiceImpl( logger *zap.SugaredLogger, - installedAppRepository repository.InstalledAppRepository, appStoreApplicationVersionRepository appStoreDiscoverRepository.AppStoreApplicationVersionRepository, - environmentRepository repository2.EnvironmentRepository, - chartTemplateService util.ChartTemplateService, - gitFactory *git.GitFactory, - gitOpsConfigReadService config.GitOpsConfigReadService, - gitOperationService git.GitOperationService) *AppStoreDeploymentCommonServiceImpl { + chartTemplateService util.ChartTemplateService) *AppStoreDeploymentCommonServiceImpl { return &AppStoreDeploymentCommonServiceImpl{ logger: logger, - installedAppRepository: installedAppRepository, appStoreApplicationVersionRepository: appStoreApplicationVersionRepository, - environmentRepository: environmentRepository, chartTemplateService: chartTemplateService, - gitFactory: gitFactory, - gitOpsConfigReadService: gitOpsConfigReadService, - gitOperationService: gitOperationService, } } -// TODO: move this from here - -func ParseChartCreateRequest(installAppRequestDTO *appStoreBean.InstallAppVersionDTO, chartPath string) *util.ChartCreateRequest { - return &util.ChartCreateRequest{ChartMetaData: &chart.Metadata{ - Name: installAppRequestDTO.AppName, - Version: "1.0.1", - }, ChartPath: chartPath} -} - -func ParseChartGitPushRequest(installAppRequestDTO *appStoreBean.InstallAppVersionDTO, repoURl string, tempRefChart string) *appStoreBean.PushChartToGitRequestDTO { - return &appStoreBean.PushChartToGitRequestDTO{ - AppName: installAppRequestDTO.AppName, - EnvName: installAppRequestDTO.Environment.Name, - ChartAppStoreName: installAppRequestDTO.AppStoreName, - RepoURL: repoURl, - TempChartRefDir: tempRefChart, - UserId: installAppRequestDTO.UserId, - } -} - -type AppStoreManifestResponse struct { - ChartResponse *util.ChartCreateResponse - ValuesConfig *git.ChartConfig - RequirementsConfig *git.ChartConfig -} - -type AppStoreGitOpsResponse struct { - ChartGitAttribute *commonBean.ChartGitAttribute - GitHash string -} - -func (impl AppStoreDeploymentCommonServiceImpl) GetInstalledAppByClusterNamespaceAndName(clusterId int, namespace string, appName string) (*appStoreBean.InstallAppVersionDTO, error) { - installedApp, err := impl.installedAppRepository.GetInstalledApplicationByClusterIdAndNamespaceAndAppName(clusterId, namespace, appName) - if err != nil { - if err == pg.ErrNoRows { - impl.logger.Warnw("no installed apps found", "clusterId", clusterId) - return nil, nil - } else { - impl.logger.Errorw("error while fetching installed apps", "clusterId", clusterId, "error", err) - return nil, err - } - } - - if installedApp.Id > 0 { - installedAppVersion, err := impl.installedAppRepository.GetInstalledAppVersionByInstalledAppIdAndEnvId(installedApp.Id, installedApp.EnvironmentId) - if err != nil { - return nil, err - } - return impl.convert(installedApp, installedAppVersion), nil - } - - return nil, nil -} - -func (impl AppStoreDeploymentCommonServiceImpl) GetInstalledAppByInstalledAppId(installedAppId int) (*appStoreBean.InstallAppVersionDTO, error) { - installedAppVersion, err := impl.installedAppRepository.GetActiveInstalledAppVersionByInstalledAppId(installedAppId) - if err != nil { - return nil, err - } - installedApp := &installedAppVersion.InstalledApp - return impl.convert(installedApp, installedAppVersion), nil -} - -// converts db object to bean -func (impl AppStoreDeploymentCommonServiceImpl) convert(chart *repository.InstalledApps, installedAppVersion *repository.InstalledAppVersions) *appStoreBean.InstallAppVersionDTO { - - chartVersionApp := installedAppVersion.AppStoreApplicationVersion - - var chartRepoName, chartRepoUrl, Username, Password string - if installedAppVersion.AppStoreApplicationVersion.AppStore.ChartRepoId != 0 { - chartRepo := installedAppVersion.AppStoreApplicationVersion.AppStore.ChartRepo - chartRepoName = chartRepo.Name - chartRepoUrl = chartRepo.Url - Username = chartRepo.UserName - Password = chartRepo.Password - } else { - chartRepo := installedAppVersion.AppStoreApplicationVersion.AppStore.DockerArtifactStore - chartRepoName = chartRepo.Id - chartRepoUrl = fmt.Sprintf("%s://%s/%s", - "oci", - installedAppVersion.AppStoreApplicationVersion.AppStore.DockerArtifactStore.RegistryURL, - installedAppVersion.AppStoreApplicationVersion.AppStore.Name) - Username = installedAppVersion.AppStoreApplicationVersion.AppStore.DockerArtifactStore.Username - Password = installedAppVersion.AppStoreApplicationVersion.AppStore.DockerArtifactStore.Password - } - - return &appStoreBean.InstallAppVersionDTO{ - EnvironmentId: chart.EnvironmentId, - Id: chart.Id, - AppId: chart.AppId, - TeamId: chart.App.TeamId, - TeamName: chart.App.Team.Name, - AppOfferingMode: chart.App.AppOfferingMode, - ClusterId: chart.Environment.ClusterId, - Namespace: chart.Environment.Namespace, - AppName: chart.App.AppName, - EnvironmentName: chart.Environment.Name, - InstalledAppId: chart.Id, - InstalledAppVersionId: installedAppVersion.Id, - InstallAppVersionChartDTO: &appStoreBean.InstallAppVersionChartDTO{ - AppStoreChartId: chartVersionApp.AppStore.Id, - ChartName: chartVersionApp.Name, - ChartVersion: chartVersionApp.Version, - InstallAppVersionChartRepoDTO: &appStoreBean.InstallAppVersionChartRepoDTO{ - RepoName: chartRepoName, - RepoUrl: chartRepoUrl, - UserName: Username, - Password: Password, - }, - }, - DeploymentAppType: chart.DeploymentAppType, - AppStoreApplicationVersionId: installedAppVersion.AppStoreApplicationVersionId, - } -} - -func (impl AppStoreDeploymentCommonServiceImpl) ParseGitRepoErrorResponse(err error) (bool, error) { - //update values yaml in chart - noTargetFound := false - if err != nil { - if errorResponse, ok := err.(*github.ErrorResponse); ok && errorResponse.Response.StatusCode == http.StatusNotFound { - impl.logger.Errorw("no content found while updating git repo on github, do auto fix", "error", err) - noTargetFound = true - } - if errorResponse, ok := err.(azuredevops.WrappedError); ok && *errorResponse.StatusCode == http.StatusNotFound { - impl.logger.Errorw("no content found while updating git repo on azure, do auto fix", "error", err) - noTargetFound = true - } - if errorResponse, ok := err.(*azuredevops.WrappedError); ok && *errorResponse.StatusCode == http.StatusNotFound { - impl.logger.Errorw("no content found while updating git repo on azure, do auto fix", "error", err) - noTargetFound = true - } - if errorResponse, ok := err.(*gitlab.ErrorResponse); ok && errorResponse.Response.StatusCode == http.StatusNotFound { - impl.logger.Errorw("no content found while updating git repo gitlab, do auto fix", "error", err) - noTargetFound = true - } - if err.Error() == git.BITBUCKET_REPO_NOT_FOUND_ERROR { - impl.logger.Errorw("no content found while updating git repo bitbucket, do auto fix", "error", err) - noTargetFound = true - } - } - return noTargetFound, err -} - func (impl AppStoreDeploymentCommonServiceImpl) GetValuesString(chartName, valuesOverrideYaml string) (string, error) { ValuesOverrideByte, err := yaml.YAMLToJSON([]byte(valuesOverrideYaml)) @@ -289,301 +106,17 @@ func (impl AppStoreDeploymentCommonServiceImpl) GetRequirementsString(appStoreVe return string(requirementDependenciesByte), nil } -func (impl AppStoreDeploymentCommonServiceImpl) GetGitCommitConfig(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, fileString string, filename string) (*git.ChartConfig, error) { - appStoreAppVersion, err := impl.appStoreApplicationVersionRepository.FindById(installAppVersionRequest.AppStoreVersion) - if err != nil { - impl.logger.Errorw("fetching error", "err", err) - return nil, err - } - environment, err := impl.environmentRepository.FindById(installAppVersionRequest.EnvironmentId) - if err != nil { - impl.logger.Errorw("fetching error", "err", err) - return nil, err - } - - argocdAppName := installAppVersionRequest.AppName + "-" + environment.Name - gitOpsRepoName := impl.gitOpsConfigReadService.GetGitOpsRepoName(installAppVersionRequest.AppName) - userEmailId, userName := impl.gitOpsConfigReadService.GetUserEmailIdAndNameForGitOpsCommit(installAppVersionRequest.UserId) - YamlConfig := &git.ChartConfig{ - FileName: filename, - FileContent: fileString, - ChartName: installAppVersionRequest.AppName, - ChartLocation: argocdAppName, - ChartRepoName: gitOpsRepoName, - ReleaseMessage: fmt.Sprintf("release-%d-env-%d ", appStoreAppVersion.Id, environment.Id), - UserEmailId: userEmailId, - UserName: userName, - } - return YamlConfig, nil -} - -func (impl AppStoreDeploymentCommonServiceImpl) GetValuesAndRequirementGitConfig(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*git.ChartConfig, *git.ChartConfig, error) { - - appStoreAppVersion, err := impl.appStoreApplicationVersionRepository.FindById(installAppVersionRequest.AppStoreVersion) - if err != nil { - impl.logger.Errorw("fetching error", "err", err) - return nil, nil, err - } - values, err := impl.GetValuesString(appStoreAppVersion.AppStore.Name, installAppVersionRequest.ValuesOverrideYaml) - if err != nil { - impl.logger.Errorw("error in getting values fot installedAppVersionRequest", "err", err) - return nil, nil, err - } - dependency, err := impl.GetRequirementsString(installAppVersionRequest.AppStoreVersion) - if err != nil { - impl.logger.Errorw("error in getting dependency array fot installedAppVersionRequest", "err", err) - return nil, nil, err - } - valuesConfig, err := impl.GetGitCommitConfig(installAppVersionRequest, values, appStoreBean.VALUES_YAML_FILE) - if err != nil { - impl.logger.Errorw("error in creating values config for git", "err", err) - return nil, nil, err - } - RequirementConfig, err := impl.GetGitCommitConfig(installAppVersionRequest, dependency, appStoreBean.REQUIREMENTS_YAML_FILE) - if err != nil { - impl.logger.Errorw("error in creating dependency config for git", "err", err) - return nil, nil, err - } - return valuesConfig, RequirementConfig, nil -} - -// CreateChartProxyAndGetPath parse chart in local directory and returns path of local dir and values.yaml -func (impl AppStoreDeploymentCommonServiceImpl) CreateChartProxyAndGetPath(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*util.ChartCreateResponse, error) { - +func (impl AppStoreDeploymentCommonServiceImpl) CreateChartProxyAndGetPath(chartCreateRequest *util.ChartCreateRequest) (*util.ChartCreateResponse, error) { ChartCreateResponse := &util.ChartCreateResponse{} - template := appStoreBean.CHART_PROXY_TEMPLATE - chartPath := path.Join(appStoreBean.RefChartProxyDirPath, template) - valid, err := chartutil.IsChartDir(chartPath) + valid, err := chartutil.IsChartDir(chartCreateRequest.ChartPath) if err != nil || !valid { - impl.logger.Errorw("invalid base chart", "dir", chartPath, "err", err) + impl.logger.Errorw("invalid base chart", "dir", chartCreateRequest.ChartPath, "err", err) return ChartCreateResponse, err } - chartCreateRequest := ParseChartCreateRequest(installAppVersionRequest, chartPath) chartCreateResponse, err := impl.chartTemplateService.BuildChartProxyForHelmApps(chartCreateRequest) if err != nil { impl.logger.Errorw("Error in building chart proxy", "err", err) return chartCreateResponse, err } return chartCreateResponse, nil - -} - -func (impl AppStoreDeploymentCommonServiceImpl) GenerateManifest(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (manifestResponse *AppStoreManifestResponse, err error) { - - manifestResponse = &AppStoreManifestResponse{} - - ChartCreateResponse, err := impl.CreateChartProxyAndGetPath(installAppVersionRequest) - if err != nil { - impl.logger.Errorw("Error in building chart while generating manifest", "err", err) - return manifestResponse, err - } - valuesConfig, dependencyConfig, err := impl.GetValuesAndRequirementGitConfig(installAppVersionRequest) - if err != nil { - impl.logger.Errorw("error in fetching values and requirements.yaml config while generating manifest", "err", err) - return manifestResponse, err - } - - manifestResponse.ChartResponse = ChartCreateResponse - manifestResponse.ValuesConfig = valuesConfig - manifestResponse.RequirementsConfig = dependencyConfig - - return manifestResponse, nil -} - -//func (impl AppStoreDeploymentCommonServiceImpl) GenerateManifestAndPerformGitOps(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*util.ChartGitAttribute, error) { -// -// manifestResponse, err := impl.GenerateManifest(installAppVersionRequest) -// if err != nil { -// impl.logger.Errorw("Error in generating manifest for gitops step", "err", err) -// return nil, err -// } -// impl. -// -//} - -// CreateGitOpsRepo creates a gitOps repo with readme -func (impl AppStoreDeploymentCommonServiceImpl) CreateGitOpsRepo(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (string, bool, error) { - if len(installAppVersionRequest.GitOpsRepoName) == 0 { - //here gitops repo will be the app name, to breaking the mono repo structure - gitOpsRepoName := impl.gitOpsConfigReadService.GetGitOpsRepoName(installAppVersionRequest.AppName) - installAppVersionRequest.GitOpsRepoName = gitOpsRepoName - } - bitbucketMetadata, err := impl.gitOpsConfigReadService.GetBitbucketMetadata() - if err != nil { - impl.logger.Errorw("error in getting bitbucket metadata", "err", err) - return "", false, err - } - //getting user name & emailId for commit author data - gitRepoRequest := &bean.GitOpsConfigDto{ - GitRepoName: installAppVersionRequest.GitOpsRepoName, - Description: "helm chart for " + installAppVersionRequest.GitOpsRepoName, - BitBucketWorkspaceId: bitbucketMetadata.BitBucketWorkspaceId, - BitBucketProjectKey: bitbucketMetadata.BitBucketProjectKey, - } - repoUrl, isNew, err := impl.gitOperationService.CreateRepository(gitRepoRequest, installAppVersionRequest.UserId) - if err != nil { - impl.logger.Errorw("error in creating git project", "name", installAppVersionRequest.GitOpsRepoName, "err", err) - return "", false, err - } - return repoUrl, isNew, err -} - -// PushChartToGitopsRepo pushes built chart to gitOps repo -func (impl AppStoreDeploymentCommonServiceImpl) PushChartToGitopsRepo(PushChartToGitRequest *appStoreBean.PushChartToGitRequestDTO, requirementsConfig *git.ChartConfig, valuesConfig *git.ChartConfig) (*commonBean.ChartGitAttribute, string, error) { - space := regexp.MustCompile(`\s+`) - appStoreName := space.ReplaceAllString(PushChartToGitRequest.ChartAppStoreName, "-") - chartDir := fmt.Sprintf("%s-%s", PushChartToGitRequest.AppName, impl.chartTemplateService.GetDir()) - clonedDir, err := impl.gitOperationService.GetClonedDir(chartDir, PushChartToGitRequest.RepoURL) - if err != nil { - impl.logger.Errorw("error in cloning repo", "url", PushChartToGitRequest.RepoURL, "err", err) - return nil, "", err - } - err = impl.gitOperationService.GitPull(clonedDir, PushChartToGitRequest.RepoURL, appStoreName) - if err != nil { - return nil, "", err - } - - acdAppName := fmt.Sprintf("%s-%s", PushChartToGitRequest.AppName, PushChartToGitRequest.EnvName) - dir := filepath.Join(clonedDir, acdAppName) - err = os.MkdirAll(dir, os.ModePerm) - if err != nil { - impl.logger.Errorw("error in making dir", "err", err) - return nil, "", err - } - err = dirCopy.Copy(PushChartToGitRequest.TempChartRefDir, dir) - if err != nil { - impl.logger.Errorw("error copying dir", "err", err) - return nil, "", err - } - err = impl.AddConfigFileToChart(requirementsConfig, dir, clonedDir) - if err != nil { - impl.logger.Errorw("error in adding requirements.yaml to chart", "err", err, "appName", PushChartToGitRequest.AppName) - return nil, "", err - } - err = impl.AddConfigFileToChart(valuesConfig, dir, clonedDir) - if err != nil { - impl.logger.Errorw("error in adding values.yaml to chart", "err", err, "appName", PushChartToGitRequest.AppName) - return nil, "", err - } - userEmailId, userName := impl.gitOpsConfigReadService.GetUserEmailIdAndNameForGitOpsCommit(PushChartToGitRequest.UserId) - commit, err := impl.gitOperationService.CommitAndPushAllChanges(clonedDir, "first commit", userName, userEmailId) - if err != nil { - impl.logger.Errorw("error in pushing git", "err", err) - impl.logger.Warn("re-trying, taking pull and then push again") - err = impl.gitOperationService.GitPull(clonedDir, PushChartToGitRequest.RepoURL, acdAppName) - if err != nil { - impl.logger.Errorw("error in git pull", "err", err, "appName", acdAppName) - return nil, "", err - } - err = dirCopy.Copy(PushChartToGitRequest.TempChartRefDir, dir) - if err != nil { - impl.logger.Errorw("error copying dir", "err", err) - return nil, "", err - } - commit, err = impl.gitOperationService.CommitAndPushAllChanges(clonedDir, "first commit", userName, userEmailId) - if err != nil { - impl.logger.Errorw("error in pushing git", "err", err) - return nil, "", err - } - } - impl.logger.Debugw("template committed", "url", PushChartToGitRequest.RepoURL, "commit", commit) - defer impl.chartTemplateService.CleanDir(clonedDir) - return &commonBean.ChartGitAttribute{RepoUrl: PushChartToGitRequest.RepoURL, ChartLocation: acdAppName}, commit, err -} - -// AddConfigFileToChart will override requirements.yaml file in chart -func (impl AppStoreDeploymentCommonServiceImpl) AddConfigFileToChart(config *git.ChartConfig, dir string, clonedDir string) error { - filePath := filepath.Join(clonedDir, config.FileName) - file, err := os.Create(filePath) - if err != nil { - impl.logger.Errorw("error in creating file", "err", err, "fileName", config.FileName) - return err - } - defer file.Close() - _, err = file.Write([]byte(config.FileContent)) - if err != nil { - impl.logger.Errorw("error in writing file content", "err", err, "fileName", config.FileName) - return err - } - destinationFilePath := filepath.Join(dir, config.FileName) - err = util2.MoveFileToDestination(filePath, destinationFilePath) - if err != nil { - impl.logger.Errorw("error in moving file from source to destination", "err", err) - return err - } - return nil -} - -// CreateGitOpsRepoAndPushChart is a wrapper for creating gitops repo and pushing chart to created repo -func (impl AppStoreDeploymentCommonServiceImpl) CreateGitOpsRepoAndPushChart(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, builtChartPath string, requirementsConfig *git.ChartConfig, valuesConfig *git.ChartConfig) (*commonBean.ChartGitAttribute, bool, string, error) { - repoURL, isNew, err := impl.CreateGitOpsRepo(installAppVersionRequest) - if err != nil { - impl.logger.Errorw("Error in creating gitops repo for ", "appName", installAppVersionRequest.AppName, "err", err) - return nil, false, "", err - } - pushChartToGitRequest := ParseChartGitPushRequest(installAppVersionRequest, repoURL, builtChartPath) - chartGitAttribute, commitHash, err := impl.PushChartToGitopsRepo(pushChartToGitRequest, requirementsConfig, valuesConfig) - if err != nil { - impl.logger.Errorw("error in pushing chart to git", "err", err) - return nil, false, "", err - } - return chartGitAttribute, isNew, commitHash, err -} - -func (impl AppStoreDeploymentCommonServiceImpl) GitOpsOperations(manifestResponse *AppStoreManifestResponse, installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*AppStoreGitOpsResponse, error) { - appStoreGitOpsResponse := &AppStoreGitOpsResponse{} - chartGitAttribute, isNew, githash, err := impl.CreateGitOpsRepoAndPushChart(installAppVersionRequest, manifestResponse.ChartResponse.BuiltChartPath, manifestResponse.RequirementsConfig, manifestResponse.ValuesConfig) - if err != nil { - impl.logger.Errorw("Error in pushing chart to git", "err", err) - return appStoreGitOpsResponse, err - } - space := regexp.MustCompile(`\s+`) - appStoreName := space.ReplaceAllString(installAppVersionRequest.AppName, "-") - clonedDir := git.GIT_WORKING_DIR + "" + appStoreName - - // Checking this is the first time chart has been pushed , if yes requirements.yaml has been already pushed with chart as there was sync-delay with github api. - // step-2 commit dependencies and values in git - if !isNew { - _, _, err = impl.gitOperationService.CommitValues(manifestResponse.RequirementsConfig) - if err != nil { - impl.logger.Errorw("error in committing dependency config to git", "err", err) - return appStoreGitOpsResponse, err - } - err = impl.gitOperationService.GitPull(clonedDir, chartGitAttribute.RepoUrl, appStoreName) - if err != nil { - impl.logger.Errorw("error in git pull", "err", err) - return appStoreGitOpsResponse, err - } - - githash, _, err = impl.gitOperationService.CommitValues(manifestResponse.ValuesConfig) - if err != nil { - impl.logger.Errorw("error in committing values config to git", "err", err) - return appStoreGitOpsResponse, err - } - err = impl.gitOperationService.GitPull(clonedDir, chartGitAttribute.RepoUrl, appStoreName) - if err != nil { - impl.logger.Errorw("error in git pull", "err", err) - return appStoreGitOpsResponse, err - } - } - appStoreGitOpsResponse.ChartGitAttribute = chartGitAttribute - appStoreGitOpsResponse.GitHash = githash - return appStoreGitOpsResponse, nil -} - -func (impl AppStoreDeploymentCommonServiceImpl) GenerateManifestAndPerformGitOperations(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*AppStoreGitOpsResponse, error) { - appStoreGitOpsResponse := &AppStoreGitOpsResponse{} - manifest, err := impl.GenerateManifest(installAppVersionRequest) - if err != nil { - impl.logger.Errorw("error in performing manifest and git operations", "err", err) - return nil, err - } - gitOpsResponse, err := impl.GitOpsOperations(manifest, installAppVersionRequest) - if err != nil { - impl.logger.Errorw("error in performing gitops operation", "err", err) - return nil, err - } - installAppVersionRequest.GitHash = gitOpsResponse.GitHash - appStoreGitOpsResponse.ChartGitAttribute = gitOpsResponse.ChartGitAttribute - return appStoreGitOpsResponse, nil } diff --git a/pkg/appStore/deployment/fullMode/AppStoreDeploymentFullModeService.go b/pkg/appStore/deployment/fullMode/AppStoreDeploymentFullModeService.go deleted file mode 100644 index ad2242066f3..00000000000 --- a/pkg/appStore/deployment/fullMode/AppStoreDeploymentFullModeService.go +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright (c) 2020 Devtron Labs - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -package appStoreDeploymentFullMode - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "github.com/devtron-labs/common-lib/pubsub-lib" - "github.com/devtron-labs/common-lib/pubsub-lib/model" - commonBean "github.com/devtron-labs/devtron/pkg/deployment/gitOps/common/bean" - "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config" - "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git" - "time" - - "github.com/devtron-labs/devtron/client/argocdServer" - "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig" - "github.com/devtron-labs/devtron/pkg/app/status" - appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" - appStoreDeploymentCommon "github.com/devtron-labs/devtron/pkg/appStore/deployment/common" - repository4 "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" - appStoreDiscoverRepository "github.com/devtron-labs/devtron/pkg/appStore/discover/repository" - repository5 "github.com/devtron-labs/devtron/pkg/cluster/repository" - "github.com/devtron-labs/devtron/pkg/sql" - util2 "github.com/devtron-labs/devtron/pkg/util" - "github.com/devtron-labs/devtron/util/argo" - "github.com/go-pg/pg" - - "github.com/argoproj/argo-cd/v2/pkg/apiclient/application" - application2 "github.com/devtron-labs/devtron/client/argocdServer/application" - "go.uber.org/zap" -) - -const ( - DEFAULT_ENVIRONMENT_OR_NAMESPACE_OR_PROJECT = "devtron" - CLUSTER_COMPONENT_DIR_PATH = "/cluster/component" -) - -// ACD operation and git operation -type AppStoreDeploymentFullModeService interface { - AppStoreDeployOperationACD(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, chartGitAttr *commonBean.ChartGitAttribute, ctx context.Context, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, error) - UpdateValuesYaml(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, error) - UpdateRequirementYaml(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, appStoreAppVersion *appStoreDiscoverRepository.AppStoreApplicationVersion) error - GetGitOpsRepoName(appName string, environmentName string) (string, error) -} - -type AppStoreDeploymentFullModeServiceImpl struct { - logger *zap.SugaredLogger - acdClient application2.ServiceClient - ArgoK8sClient argocdServer.ArgoK8sClient - aCDAuthConfig *util2.ACDAuthConfig - argoUserService argo.ArgoUserService - pipelineStatusTimelineService status.PipelineStatusTimelineService - appStoreDeploymentCommonService appStoreDeploymentCommon.AppStoreDeploymentCommonService - argoClientWrapperService argocdServer.ArgoClientWrapperService - pubSubClient *pubsub_lib.PubSubClientServiceImpl - installedAppRepositoryHistory repository4.InstalledAppVersionHistoryRepository - ACDConfig *argocdServer.ACDConfig - gitOpsConfigReadService config.GitOpsConfigReadService - gitOperationService git.GitOperationService -} - -func NewAppStoreDeploymentFullModeServiceImpl(logger *zap.SugaredLogger, - acdClient application2.ServiceClient, - argoK8sClient argocdServer.ArgoK8sClient, aCDAuthConfig *util2.ACDAuthConfig, - argoUserService argo.ArgoUserService, pipelineStatusTimelineService status.PipelineStatusTimelineService, - appStoreDeploymentCommonService appStoreDeploymentCommon.AppStoreDeploymentCommonService, - argoClientWrapperService argocdServer.ArgoClientWrapperService, - pubSubClient *pubsub_lib.PubSubClientServiceImpl, - installedAppRepositoryHistory repository4.InstalledAppVersionHistoryRepository, - ACDConfig *argocdServer.ACDConfig, - gitOpsConfigReadService config.GitOpsConfigReadService, - gitOperationService git.GitOperationService) *AppStoreDeploymentFullModeServiceImpl { - appStoreDeploymentFullModeServiceImpl := &AppStoreDeploymentFullModeServiceImpl{ - logger: logger, - acdClient: acdClient, - ArgoK8sClient: argoK8sClient, - aCDAuthConfig: aCDAuthConfig, - argoUserService: argoUserService, - pipelineStatusTimelineService: pipelineStatusTimelineService, - appStoreDeploymentCommonService: appStoreDeploymentCommonService, - argoClientWrapperService: argoClientWrapperService, - pubSubClient: pubSubClient, - installedAppRepositoryHistory: installedAppRepositoryHistory, - ACDConfig: ACDConfig, - gitOpsConfigReadService: gitOpsConfigReadService, - gitOperationService: gitOperationService, - } - err := appStoreDeploymentFullModeServiceImpl.subscribeHelmInstallStatus() - if err != nil { - return nil - } - return appStoreDeploymentFullModeServiceImpl -} - -func (impl AppStoreDeploymentFullModeServiceImpl) AppStoreDeployOperationACD(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, chartGitAttr *commonBean.ChartGitAttribute, ctx context.Context, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, error) { - ctx, cancel := context.WithTimeout(ctx, 1*time.Minute) - defer cancel() - //STEP 4: registerInArgo - err := impl.argoClientWrapperService.RegisterGitOpsRepoInArgo(ctx, chartGitAttr.RepoUrl) - if err != nil { - impl.logger.Errorw("error in argo registry", "err", err) - return nil, err - } - //STEP 5: createInArgo - err = impl.createInArgo(chartGitAttr, ctx, *installAppVersionRequest.Environment, installAppVersionRequest.ACDAppName) - if err != nil { - impl.logger.Errorw("error in create in argo", "err", err) - return nil, err - } - //STEP 6: Force Sync ACD - works like trigger deployment - //impl.SyncACD(installAppVersionRequest.ACDAppName, ctx) - - //STEP 7: normal refresh ACD - update for step 6 to avoid delay - syncTime := time.Now() - err = impl.argoClientWrapperService.SyncArgoCDApplicationIfNeededAndRefresh(ctx, installAppVersionRequest.ACDAppName) - if err != nil { - impl.logger.Errorw("error in getting the argo application with normal refresh", "err", err) - return nil, err - } - if !impl.ACDConfig.ArgoCDAutoSyncEnabled { - timeline := &pipelineConfig.PipelineStatusTimeline{ - InstalledAppVersionHistoryId: installAppVersionRequest.InstalledAppVersionHistoryId, - Status: pipelineConfig.TIMELINE_STATUS_ARGOCD_SYNC_COMPLETED, - StatusDetail: "argocd sync completed.", - StatusTime: syncTime, - AuditLog: sql.AuditLog{ - CreatedBy: installAppVersionRequest.UserId, - CreatedOn: time.Now(), - UpdatedBy: installAppVersionRequest.UserId, - UpdatedOn: time.Now(), - }, - } - err = impl.pipelineStatusTimelineService.SaveTimeline(timeline, tx, true) - if err != nil { - impl.logger.Errorw("error in creating timeline for argocd sync", "err", err, "timeline", timeline) - } - } - - return installAppVersionRequest, nil -} - -func (impl AppStoreDeploymentFullModeServiceImpl) createInArgo(chartGitAttribute *commonBean.ChartGitAttribute, ctx context.Context, envModel repository5.Environment, argocdAppName string) error { - appNamespace := envModel.Namespace - if appNamespace == "" { - appNamespace = "default" - } - appreq := &argocdServer.AppTemplate{ - ApplicationName: argocdAppName, - Namespace: impl.aCDAuthConfig.ACDConfigMapNamespace, - TargetNamespace: appNamespace, - TargetServer: envModel.Cluster.ServerUrl, - Project: "default", - ValuesFile: fmt.Sprintf("values.yaml"), - RepoPath: chartGitAttribute.ChartLocation, - RepoUrl: chartGitAttribute.RepoUrl, - AutoSyncEnabled: impl.ACDConfig.ArgoCDAutoSyncEnabled, - } - _, err := impl.ArgoK8sClient.CreateAcdApp(appreq, envModel.Cluster, argocdServer.ARGOCD_APPLICATION_TEMPLATE) - //create - if err != nil { - impl.logger.Errorw("error in creating argo cd app ", "err", err) - return err - } - return nil -} - -func (impl AppStoreDeploymentFullModeServiceImpl) GetGitOpsRepoName(appName string, environmentName string) (string, error) { - gitOpsRepoName := "" - //this method should only call in case of argo-integration and gitops configured - acdToken, err := impl.argoUserService.GetLatestDevtronArgoCdUserToken() - if err != nil { - impl.logger.Errorw("error in getting acd token", "err", err) - return "", err - } - ctx := context.Background() - ctx = context.WithValue(ctx, "token", acdToken) - acdAppName := fmt.Sprintf("%s-%s", appName, environmentName) - application, err := impl.acdClient.Get(ctx, &application.ApplicationQuery{Name: &acdAppName}) - if err != nil { - impl.logger.Errorw("no argo app exists", "acdAppName", acdAppName, "err", err) - return "", err - } - if application != nil { - gitOpsRepoUrl := application.Spec.Source.RepoURL - gitOpsRepoName = impl.gitOpsConfigReadService.GetGitOpsRepoNameFromUrl(gitOpsRepoUrl) - } - return gitOpsRepoName, nil -} - -func (impl AppStoreDeploymentFullModeServiceImpl) UpdateValuesYaml(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, error) { - - valuesString, err := impl.appStoreDeploymentCommonService.GetValuesString(installAppVersionRequest.AppStoreName, installAppVersionRequest.ValuesOverrideYaml) - if err != nil { - impl.logger.Errorw("error in getting values string", "err", err) - return nil, err - } - - valuesGitConfig, err := impl.appStoreDeploymentCommonService.GetGitCommitConfig(installAppVersionRequest, valuesString, appStoreBean.VALUES_YAML_FILE) - if err != nil { - impl.logger.Errorw("error in getting git commit config", "err", err) - } - - commitHash, _, err := impl.gitOperationService.CommitValues(valuesGitConfig) - if err != nil { - impl.logger.Errorw("error in git commit", "err", err) - return installAppVersionRequest, errors.New(pipelineConfig.TIMELINE_STATUS_GIT_COMMIT_FAILED) - } - //update timeline status for git commit state - installAppVersionRequest.GitHash = commitHash - return installAppVersionRequest, nil -} - -func (impl AppStoreDeploymentFullModeServiceImpl) UpdateRequirementYaml(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, appStoreAppVersion *appStoreDiscoverRepository.AppStoreApplicationVersion) error { - - requirementsString, err := impl.appStoreDeploymentCommonService.GetRequirementsString(appStoreAppVersion.Id) - if err != nil { - impl.logger.Errorw("error in getting requirements string", "err", err) - return err - } - - requirementsGitConfig, err := impl.appStoreDeploymentCommonService.GetGitCommitConfig(installAppVersionRequest, requirementsString, appStoreBean.REQUIREMENTS_YAML_FILE) - if err != nil { - impl.logger.Errorw("error in getting git commit config", "err", err) - return err - } - - _, _, err = impl.gitOperationService.CommitValues(requirementsGitConfig) - if err != nil { - impl.logger.Errorw("error in values commit", "err", err) - return errors.New(pipelineConfig.TIMELINE_STATUS_GIT_COMMIT_FAILED) - } - - return nil -} - -func (impl AppStoreDeploymentFullModeServiceImpl) subscribeHelmInstallStatus() error { - - callback := func(msg *model.PubSubMsg) { - - helmInstallNatsMessage := &appStoreBean.HelmReleaseStatusConfig{} - err := json.Unmarshal([]byte(msg.Data), helmInstallNatsMessage) - if err != nil { - impl.logger.Errorw("error in unmarshalling helm install status nats message", "err", err) - return - } - - installedAppVersionHistory, err := impl.installedAppRepositoryHistory.GetInstalledAppVersionHistory(helmInstallNatsMessage.InstallAppVersionHistoryId) - if err != nil { - impl.logger.Errorw("error in fetching installed app by installed app id in subscribe helm status callback", "err", err) - return - } - if helmInstallNatsMessage.ErrorInInstallation { - installedAppVersionHistory.Status = pipelineConfig.WorkflowFailed - } else { - installedAppVersionHistory.Status = pipelineConfig.WorkflowSucceeded - } - installedAppVersionHistory.HelmReleaseStatusConfig = msg.Data - _, err = impl.installedAppRepositoryHistory.UpdateInstalledAppVersionHistory(installedAppVersionHistory, nil) - if err != nil { - impl.logger.Errorw("error in updating helm release status data in installedAppVersionHistoryRepository", "err", err) - return - } - } - - // add required logging here - var loggerFunc pubsub_lib.LoggerFunc = func(msg model.PubSubMsg) (string, []interface{}) { - helmInstallNatsMessage := &appStoreBean.HelmReleaseStatusConfig{} - err := json.Unmarshal([]byte(msg.Data), helmInstallNatsMessage) - if err != nil { - return "error in unmarshalling helm install status nats message", []interface{}{"err", err} - } - return "got nats msg for helm chart install status", []interface{}{"InstallAppVersionHistoryId", helmInstallNatsMessage.InstallAppVersionHistoryId, "ErrorInInstallation", helmInstallNatsMessage.ErrorInInstallation, "IsReleaseInstalled", helmInstallNatsMessage.IsReleaseInstalled} - } - - err := impl.pubSubClient.Subscribe(pubsub_lib.HELM_CHART_INSTALL_STATUS_TOPIC, callback, loggerFunc) - if err != nil { - impl.logger.Error(err) - return err - } - return nil -} diff --git a/pkg/appStore/deployment/repository/InstalledAppModels.go b/pkg/appStore/deployment/repository/InstalledAppModels.go new file mode 100644 index 00000000000..56ea99d0d76 --- /dev/null +++ b/pkg/appStore/deployment/repository/InstalledAppModels.go @@ -0,0 +1,69 @@ +package repository + +import ( + "time" +) + +// TODO: Remove dependencies on native queries and the structs used in it + +// GitOpsAppDetails is used to operate on native query; This should be avoided. +// Usage func: InstalledAppRepository.GetAllGitOpsAppNameAndInstalledAppMapping +type GitOpsAppDetails struct { + GitOpsAppName string `sql:"git_ops_app_name"` + InstalledAppId int `sql:"installed_app_id"` +} + +// InstalledAppsWithChartDetails is used to operate on native query; This should be avoided. +// Usage func: InstalledAppRepository.GetAllInstalledApps +type InstalledAppsWithChartDetails struct { + AppStoreApplicationName string `json:"app_store_application_name"` + ChartRepoName string `json:"chart_repo_name"` + DockerArtifactStoreId string `json:"docker_artifact_store_id"` + AppName string `json:"app_name"` + EnvironmentName string `json:"environment_name"` + InstalledAppVersionId int `json:"installed_app_version_id"` + AppStoreApplicationVersionId int `json:"app_store_application_version_id"` + Icon string `json:"icon"` + Readme string `json:"readme"` + CreatedOn time.Time `json:"created_on"` + UpdatedOn time.Time `json:"updated_on"` + Id int `json:"id"` + EnvironmentId int `json:"environment_id"` + Deprecated bool `json:"deprecated"` + ClusterName string `json:"clusterName"` + Namespace string `json:"namespace"` + TeamId int `json:"teamId"` + ClusterId int `json:"clusterId"` + AppOfferingMode string `json:"app_offering_mode"` + AppStatus string `json:"app_status"` + DeploymentAppDeleteRequest bool `json:"deploymentAppDeleteRequest"` +} + +// InstalledAppAndEnvDetails is used to operate on native query; This should be avoided. +// Usage functions: InstalledAppRepository.GetAllInstalledAppsByChartRepoId and InstalledAppRepository.GetAllInstalledAppsByAppStoreId +type InstalledAppAndEnvDetails struct { + EnvironmentName string `json:"environment_name"` + EnvironmentId int `json:"environment_id"` + AppName string `json:"app_name"` + AppOfferingMode string `json:"appOfferingMode"` + UpdatedOn time.Time `json:"updated_on"` + EmailId string `json:"email_id"` + InstalledAppVersionId int `json:"installed_app_version_id"` + AppId int `json:"app_id"` + InstalledAppId int `json:"installed_app_id"` + AppStoreApplicationVersionId int `json:"app_store_application_version_id"` + AppStatus string `json:"app_status"` + DeploymentAppType string `json:"-"` +} + +// InstallAppDeleteRequest is used to operate on native query; This should be avoided. +// Usage func: InstalledAppRepository.GetInstalledAppByGitHash +type InstallAppDeleteRequest struct { + InstalledAppId int `json:"installed_app_id,omitempty,notnull"` + AppName string `json:"app_name,omitempty"` + AppId int `json:"app_id,omitempty"` + EnvironmentId int `json:"environment_id,omitempty"` + AppOfferingMode string `json:"app_offering_mode"` + ClusterId int `json:"cluster_id"` + Namespace string `json:"namespace"` +} diff --git a/pkg/appStore/deployment/repository/InstalledAppRepository.go b/pkg/appStore/deployment/repository/InstalledAppRepository.go index 134887be611..d4d91de2a1c 100644 --- a/pkg/appStore/deployment/repository/InstalledAppRepository.go +++ b/pkg/appStore/deployment/repository/InstalledAppRepository.go @@ -31,9 +31,62 @@ import ( "github.com/go-pg/pg/orm" "go.uber.org/zap" "strconv" - "time" ) +type InstalledApps struct { + TableName struct{} `sql:"installed_apps" pg:",discard_unknown_columns"` + Id int `sql:"id,pk"` + AppId int `sql:"app_id,notnull"` + EnvironmentId int `sql:"environment_id,notnull"` + Active bool `sql:"active, notnull"` + GitOpsRepoName string `sql:"git_ops_repo_name"` + DeploymentAppType string `sql:"deployment_app_type"` // TODO: instead of string, use enum + Status appStoreBean.AppstoreDeploymentStatus `sql:"status"` + DeploymentAppDeleteRequest bool `sql:"deployment_app_delete_request"` + Notes string `json:"notes"` + App app.App + Environment repository.Environment + sql.AuditLog +} + +func (model *InstalledApps) MarkActive() { + model.Active = true +} + +func (model *InstalledApps) MarkInActive() { + model.Active = false +} + +func (model *InstalledApps) UpdateStatus(status appStoreBean.AppstoreDeploymentStatus) { + model.Status = status +} + +func (model *InstalledApps) UpdateGitOpsRepoName(gitOpsRepoName string) { + model.GitOpsRepoName = gitOpsRepoName +} + +type InstalledAppVersions struct { + TableName struct{} `sql:"installed_app_versions" pg:",discard_unknown_columns"` + Id int `sql:"id,pk"` + InstalledAppId int `sql:"installed_app_id,notnull"` + AppStoreApplicationVersionId int `sql:"app_store_application_version_id,notnull"` + ValuesYaml string `sql:"values_yaml_raw"` + Active bool `sql:"active, notnull"` + ReferenceValueId int `sql:"reference_value_id"` + ReferenceValueKind string `sql:"reference_value_kind"` + sql.AuditLog + InstalledApp InstalledApps + AppStoreApplicationVersion appStoreDiscoverRepository.AppStoreApplicationVersion +} + +func (model *InstalledAppVersions) MarkActive() { + model.Active = true +} + +func (model *InstalledAppVersions) MarkInActive() { + model.Active = false +} + type InstalledAppRepository interface { CreateInstalledApp(model *InstalledApps, tx *pg.Tx) (*InstalledApps, error) CreateInstalledAppVersion(model *InstalledAppVersions, tx *pg.Tx) (*InstalledAppVersions, error) @@ -43,7 +96,7 @@ type InstalledAppRepository interface { GetInstalledAppVersion(id int) (*InstalledAppVersions, error) GetInstalledAppVersionAny(id int) (*InstalledAppVersions, error) GetAllInstalledApps(filter *appStoreBean.AppStoreFilter) ([]InstalledAppsWithChartDetails, error) - GetAllIntalledAppsByAppStoreId(appStoreId int) ([]InstalledAppAndEnvDetails, error) + GetAllInstalledAppsByAppStoreId(appStoreId int) ([]InstalledAppAndEnvDetails, error) GetAllInstalledAppsByChartRepoId(chartRepoId int) ([]InstalledAppAndEnvDetails, error) GetInstalledAppVersionByInstalledAppIdAndEnvId(installedAppId int, envId int) (*InstalledAppVersions, error) FetchNotes(installedAppId int) (*InstalledApps, error) @@ -81,94 +134,10 @@ type InstalledAppRepositoryImpl struct { Logger *zap.SugaredLogger } -type InstallAppDeleteRequest struct { - InstalledAppId int `json:"installed_app_id,omitempty,notnull"` - AppName string `json:"app_name,omitempty"` - AppId int `json:"app_id,omitempty"` - EnvironmentId int `json:"environment_id,omitempty"` - AppOfferingMode string `json:"app_offering_mode"` - ClusterId int `json:"cluster_id"` - Namespace string `json:"namespace"` -} - func NewInstalledAppRepositoryImpl(Logger *zap.SugaredLogger, dbConnection *pg.DB) *InstalledAppRepositoryImpl { return &InstalledAppRepositoryImpl{dbConnection: dbConnection, Logger: Logger} } -type InstalledApps struct { - TableName struct{} `sql:"installed_apps" pg:",discard_unknown_columns"` - Id int `sql:"id,pk"` - AppId int `sql:"app_id,notnull"` - EnvironmentId int `sql:"environment_id,notnull"` - Active bool `sql:"active, notnull"` - GitOpsRepoName string `sql:"git_ops_repo_name"` - DeploymentAppType string `sql:"deployment_app_type"` - Status appStoreBean.AppstoreDeploymentStatus `sql:"status"` - DeploymentAppDeleteRequest bool `sql:"deployment_app_delete_request"` - Notes string `json:"notes"` - App app.App - Environment repository.Environment - sql.AuditLog -} - -type InstalledAppVersions struct { - TableName struct{} `sql:"installed_app_versions" pg:",discard_unknown_columns"` - Id int `sql:"id,pk"` - InstalledAppId int `sql:"installed_app_id,notnull"` - AppStoreApplicationVersionId int `sql:"app_store_application_version_id,notnull"` - ValuesYaml string `sql:"values_yaml_raw"` - Active bool `sql:"active, notnull"` - ReferenceValueId int `sql:"reference_value_id"` - ReferenceValueKind string `sql:"reference_value_kind"` - sql.AuditLog - InstalledApp InstalledApps - AppStoreApplicationVersion appStoreDiscoverRepository.AppStoreApplicationVersion -} - -type GitOpsAppDetails struct { - GitOpsAppName string `sql:"git_ops_app_name"` - InstalledAppId int `sql:"installed_app_id"` -} - -type InstalledAppsWithChartDetails struct { - AppStoreApplicationName string `json:"app_store_application_name"` - ChartRepoName string `json:"chart_repo_name"` - DockerArtifactStoreId string `json:"docker_artifact_store_id"` - AppName string `json:"app_name"` - EnvironmentName string `json:"environment_name"` - InstalledAppVersionId int `json:"installed_app_version_id"` - AppStoreApplicationVersionId int `json:"app_store_application_version_id"` - Icon string `json:"icon"` - Readme string `json:"readme"` - CreatedOn time.Time `json:"created_on"` - UpdatedOn time.Time `json:"updated_on"` - Id int `json:"id"` - EnvironmentId int `json:"environment_id"` - Deprecated bool `json:"deprecated"` - ClusterName string `json:"clusterName"` - Namespace string `json:"namespace"` - TeamId int `json:"teamId"` - ClusterId int `json:"clusterId"` - AppOfferingMode string `json:"app_offering_mode"` - AppStatus string `json:"app_status"` - DeploymentAppDeleteRequest bool `json:"deploymentAppDeleteRequest"` -} - -type InstalledAppAndEnvDetails struct { - EnvironmentName string `json:"environment_name"` - EnvironmentId int `json:"environment_id"` - AppName string `json:"app_name"` - AppOfferingMode string `json:"appOfferingMode"` - UpdatedOn time.Time `json:"updated_on"` - EmailId string `json:"email_id"` - InstalledAppVersionId int `json:"installed_app_version_id"` - AppId int `json:"app_id"` - InstalledAppId int `json:"installed_app_id"` - AppStoreApplicationVersionId int `json:"app_store_application_version_id"` - AppStatus string `json:"app_status"` - DeploymentAppType string `json:"-"` -} - func (impl InstalledAppRepositoryImpl) CreateInstalledApp(model *InstalledApps, tx *pg.Tx) (*InstalledApps, error) { err := tx.Insert(model) if err != nil { @@ -427,7 +396,7 @@ func (impl InstalledAppRepositoryImpl) GetAllInstalledApps(filter *appStoreBean. return installedAppsWithChartDetails, err } -func (impl InstalledAppRepositoryImpl) GetAllIntalledAppsByAppStoreId(appStoreId int) ([]InstalledAppAndEnvDetails, error) { +func (impl InstalledAppRepositoryImpl) GetAllInstalledAppsByAppStoreId(appStoreId int) ([]InstalledAppAndEnvDetails, error) { var installedAppAndEnvDetails []InstalledAppAndEnvDetails var queryTemp = "select env.environment_name, env.id as environment_id, a.app_name, a.app_offering_mode, ia.updated_on, u.email_id," + " asav.id as app_store_application_version_id, iav.id as installed_app_version_id, ia.id as installed_app_id, ia.app_id, ia.deployment_app_type, app_status.status as app_status" + diff --git a/pkg/appStore/deployment/repository/InstalledAppVersionHistory.go b/pkg/appStore/deployment/repository/InstalledAppVersionHistory.go index f914c749ac0..4b2b1276327 100644 --- a/pkg/appStore/deployment/repository/InstalledAppVersionHistory.go +++ b/pkg/appStore/deployment/repository/InstalledAppVersionHistory.go @@ -46,6 +46,18 @@ type InstalledAppVersionHistory struct { sql.AuditLog } +func (model *InstalledAppVersionHistory) SetStartedOn() { + model.StartedOn = time.Now() +} + +func (model *InstalledAppVersionHistory) SetFinishedOn() { + model.FinishedOn = time.Now() +} + +func (model *InstalledAppVersionHistory) SetStatus(status string) { + model.Status = status +} + func (impl InstalledAppVersionHistoryRepositoryImpl) CreateInstalledAppVersionHistory(model *InstalledAppVersionHistory, tx *pg.Tx) (*InstalledAppVersionHistory, error) { err := tx.Insert(model) if err != nil { diff --git a/pkg/appStore/deployment/service/AppStoreDeploymentDBService.go b/pkg/appStore/deployment/service/AppStoreDeploymentDBService.go new file mode 100644 index 00000000000..dba9e489a89 --- /dev/null +++ b/pkg/appStore/deployment/service/AppStoreDeploymentDBService.go @@ -0,0 +1,208 @@ +package service + +import ( + "fmt" + "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig" + "github.com/devtron-labs/devtron/internal/util" + "github.com/devtron-labs/devtron/pkg/appStore/adapter" + appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" + "github.com/devtron-labs/devtron/pkg/bean" + util2 "github.com/devtron-labs/devtron/util" + "github.com/go-pg/pg" + "net/http" +) + +func (impl AppStoreDeploymentServiceImpl) AppStoreDeployOperationDB(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, tx *pg.Tx, skipAppCreation bool) (*appStoreBean.InstallAppVersionDTO, error) { + + var isInternalUse = impl.deploymentTypeConfig.IsInternalUse + + isGitOpsConfigured, err := impl.gitOpsConfigReadService.IsGitOpsConfigured() + if err != nil { + impl.logger.Errorw("error while checking IsGitOpsConfigured", "err", err) + return nil, err + } + + if isInternalUse && !isGitOpsConfigured && installAppVersionRequest.DeploymentAppType == util.PIPELINE_DEPLOYMENT_TYPE_ACD { + impl.logger.Errorw("gitops not configured but selected for CD") + err := &util.ApiError{ + HttpStatusCode: http.StatusBadRequest, + InternalMessage: "Gitops integration is not installed/configured. Please install/configure gitops or use helm option.", + UserMessage: "Gitops integration is not installed/configured. Please install/configure gitops or use helm option.", + } + return nil, err + } + + appStoreAppVersion, err := impl.appStoreApplicationVersionRepository.FindById(installAppVersionRequest.AppStoreVersion) + if err != nil { + impl.logger.Errorw("fetching error", "err", err) + return nil, err + } + + var isOCIRepo bool + if appStoreAppVersion.AppStore.DockerArtifactStore != nil { + isOCIRepo = true + } else { + isOCIRepo = false + } + + var appInstallationMode string + if util2.IsBaseStack() || util2.IsHelmApp(installAppVersionRequest.AppOfferingMode) { + appInstallationMode = util2.SERVER_MODE_HYPERION + } else { + appInstallationMode = util2.SERVER_MODE_FULL + } + + // create env if env not exists for clusterId and namespace for hyperion mode + if util2.IsHelmApp(appInstallationMode) { + envId, err := impl.createEnvironmentIfNotExists(installAppVersionRequest) + if err != nil { + return nil, err + } + installAppVersionRequest.EnvironmentId = envId + } + + environment, err := impl.environmentRepository.FindById(installAppVersionRequest.EnvironmentId) + if err != nil { + impl.logger.Errorw("fetching error", "err", err) + return nil, err + } + installAppVersionRequest.Environment = environment + installAppVersionRequest.ACDAppName = fmt.Sprintf("%s-%s", installAppVersionRequest.AppName, installAppVersionRequest.Environment.Name) + installAppVersionRequest.ClusterId = environment.ClusterId + appCreateRequest := &bean.CreateAppDTO{ + Id: installAppVersionRequest.AppId, + AppName: installAppVersionRequest.AppName, + TeamId: installAppVersionRequest.TeamId, + UserId: installAppVersionRequest.UserId, + } + + appCreateRequest, err = impl.createAppForAppStore(appCreateRequest, tx, appInstallationMode, skipAppCreation) + if err != nil { + impl.logger.Errorw("error while creating app", "error", err) + return nil, err + } + installAppVersionRequest.AppId = appCreateRequest.Id + + if !isInternalUse { + if isGitOpsConfigured && appInstallationMode == util2.SERVER_MODE_FULL && !isOCIRepo { + installAppVersionRequest.DeploymentAppType = util.PIPELINE_DEPLOYMENT_TYPE_ACD + } else { + installAppVersionRequest.DeploymentAppType = util.PIPELINE_DEPLOYMENT_TYPE_HELM + } + } + if installAppVersionRequest.DeploymentAppType == "" { + if isGitOpsConfigured && !isOCIRepo { + installAppVersionRequest.DeploymentAppType = util.PIPELINE_DEPLOYMENT_TYPE_ACD + } else { + installAppVersionRequest.DeploymentAppType = util.PIPELINE_DEPLOYMENT_TYPE_HELM + } + } + + if util2.IsFullStack() { + installAppVersionRequest.GitOpsRepoName = impl.gitOpsConfigReadService.GetGitOpsRepoName(installAppVersionRequest.AppName) + } + + installedAppModel := adapter.NewInstallAppModel(installAppVersionRequest, appStoreBean.DEPLOY_INIT) + installedApp, err := impl.installedAppRepository.CreateInstalledApp(installedAppModel, tx) + if err != nil { + impl.logger.Errorw("error while creating install app", "error", err) + return nil, err + } + installAppVersionRequest.InstalledAppId = installedApp.Id + + installedAppVersions := adapter.NewInstallAppVersionsModel(installAppVersionRequest) + _, err = impl.installedAppRepository.CreateInstalledAppVersion(installedAppVersions, tx) + if err != nil { + impl.logger.Errorw("error while fetching from db", "error", err) + return nil, err + } + + installAppVersionRequest.InstalledAppVersionId = installedAppVersions.Id + installAppVersionRequest.Id = installedAppVersions.Id + + helmInstallConfigDTO := appStoreBean.HelmReleaseStatusConfig{ + InstallAppVersionHistoryId: 0, + Message: "Install initiated", + IsReleaseInstalled: false, + ErrorInInstallation: false, + } + installedAppVersionHistory, err := adapter.NewInstallAppVersionHistoryModel(installAppVersionRequest, pipelineConfig.WorkflowInProgress, helmInstallConfigDTO) + if err != nil { + impl.logger.Errorw("error in helm install config marshal", "err", err) + } + _, err = impl.installedAppRepositoryHistory.CreateInstalledAppVersionHistory(installedAppVersionHistory, tx) + if err != nil { + impl.logger.Errorw("error while fetching from db", "error", err) + return nil, err + } + + installAppVersionRequest.InstalledAppVersionHistoryId = installedAppVersionHistory.Id + if installAppVersionRequest.DefaultClusterComponent { + clusterInstalledAppsModel := adapter.NewClusterInstalledAppsModel(installAppVersionRequest, environment.ClusterId) + err = impl.clusterInstalledAppsRepository.Save(clusterInstalledAppsModel, tx) + if err != nil { + impl.logger.Errorw("error while creating cluster install app", "error", err) + return nil, err + } + } + return installAppVersionRequest, nil +} + +func (impl AppStoreDeploymentServiceImpl) AppStoreDeployOperationStatusUpdate(installAppId int, status appStoreBean.AppstoreDeploymentStatus) (bool, error) { + dbConnection := impl.installedAppRepository.GetConnection() + tx, err := dbConnection.Begin() + if err != nil { + return false, err + } + // Rollback tx on error. + defer tx.Rollback() + installedApp, err := impl.installedAppRepository.GetInstalledApp(installAppId) + if err != nil { + impl.logger.Errorw("error while fetching from db", "error", err) + return false, err + } + installedApp.Status = status + _, err = impl.installedAppRepository.UpdateInstalledApp(installedApp, tx) + if err != nil { + impl.logger.Errorw("error while fetching from db", "error", err) + return false, err + } + err = tx.Commit() + if err != nil { + impl.logger.Errorw("error while commit db transaction to db", "error", err) + return false, err + } + return true, nil +} + +func (impl AppStoreDeploymentServiceImpl) GetInstalledAppByClusterNamespaceAndName(clusterId int, namespace string, appName string) (*appStoreBean.InstallAppVersionDTO, error) { + installedApp, err := impl.installedAppRepository.GetInstalledApplicationByClusterIdAndNamespaceAndAppName(clusterId, namespace, appName) + if err != nil { + if err == pg.ErrNoRows { + impl.logger.Warnw("no installed apps found", "clusterId", clusterId) + return nil, nil + } else { + impl.logger.Errorw("error while fetching installed apps", "clusterId", clusterId, "error", err) + return nil, err + } + } + + if installedApp.Id > 0 { + installedAppVersion, err := impl.installedAppRepository.GetInstalledAppVersionByInstalledAppIdAndEnvId(installedApp.Id, installedApp.EnvironmentId) + if err != nil { + return nil, err + } + return adapter.GenerateInstallAppVersionDTO(installedApp, installedAppVersion), nil + } + + return nil, nil +} + +func (impl AppStoreDeploymentServiceImpl) GetInstalledAppByInstalledAppId(installedAppId int) (*appStoreBean.InstallAppVersionDTO, error) { + installedAppVersion, err := impl.installedAppRepository.GetActiveInstalledAppVersionByInstalledAppId(installedAppId) + if err != nil { + return nil, err + } + installedApp := &installedAppVersion.InstalledApp + return adapter.GenerateInstallAppVersionDTO(installedApp, installedAppVersion), nil +} diff --git a/pkg/appStore/deployment/service/AppStoreDeploymentService.go b/pkg/appStore/deployment/service/AppStoreDeploymentService.go index 203933a51d3..8cf1a5344cd 100644 --- a/pkg/appStore/deployment/service/AppStoreDeploymentService.go +++ b/pkg/appStore/deployment/service/AppStoreDeploymentService.go @@ -23,8 +23,10 @@ import ( "errors" "fmt" "github.com/caarlos0/env/v6" - client "github.com/devtron-labs/devtron/api/helm-app" + bean3 "github.com/devtron-labs/devtron/api/helm-app/bean" + bean4 "github.com/devtron-labs/devtron/api/helm-app/gRPC" openapi "github.com/devtron-labs/devtron/api/helm-app/openapiClient" + "github.com/devtron-labs/devtron/api/helm-app/service" openapi2 "github.com/devtron-labs/devtron/api/openapi/openapiClient" "github.com/devtron-labs/devtron/client/argocdServer" "github.com/devtron-labs/devtron/internal/constants" @@ -32,11 +34,13 @@ import ( "github.com/devtron-labs/devtron/internal/sql/repository/helper" "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig" "github.com/devtron-labs/devtron/internal/util" + "github.com/devtron-labs/devtron/pkg/appStore/adapter" appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" repository3 "github.com/devtron-labs/devtron/pkg/appStore/chartGroup/repository" appStoreDeploymentCommon "github.com/devtron-labs/devtron/pkg/appStore/deployment/common" "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" appStoreDeploymentTool "github.com/devtron-labs/devtron/pkg/appStore/deployment/tool" + bean2 "github.com/devtron-labs/devtron/pkg/appStore/deployment/tool/bean" appStoreDiscoverRepository "github.com/devtron-labs/devtron/pkg/appStore/discover/repository" "github.com/devtron-labs/devtron/pkg/bean" "github.com/devtron-labs/devtron/pkg/cluster" @@ -62,19 +66,21 @@ type AppStoreDeploymentService interface { GetInstalledApp(id int) (*appStoreBean.InstallAppVersionDTO, error) GetAllInstalledAppsByAppStoreId(w http.ResponseWriter, r *http.Request, token string, appStoreId int) ([]appStoreBean.InstalledAppsResponse, error) DeleteInstalledApp(ctx context.Context, installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*appStoreBean.InstallAppVersionDTO, error) - LinkHelmApplicationToChartStore(ctx context.Context, request *openapi.UpdateReleaseWithChartLinkingRequest, appIdentifier *client.AppIdentifier, userId int32) (*openapi.UpdateReleaseResponse, bool, error) + LinkHelmApplicationToChartStore(ctx context.Context, request *openapi.UpdateReleaseWithChartLinkingRequest, appIdentifier *service.AppIdentifier, userId int32) (*openapi.UpdateReleaseResponse, bool, error) RollbackApplication(ctx context.Context, request *openapi2.RollbackReleaseRequest, installedApp *appStoreBean.InstallAppVersionDTO, userId int32) (bool, error) UpdateInstallAppVersionHistory(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*repository.InstalledAppVersionHistory, error) - GetDeploymentHistory(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO) (*client.DeploymentHistoryAndInstalledAppInfo, error) + GetDeploymentHistory(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO) (*bean3.DeploymentHistoryAndInstalledAppInfo, error) GetDeploymentHistoryInfo(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO, installedAppVersionHistoryId int) (*openapi.HelmAppDeploymentManifestDetail, error) UpdateInstalledApp(ctx context.Context, installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*appStoreBean.InstallAppVersionDTO, error) UpdateInstalledAppVersionHistoryWithGitHash(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, tx *pg.Tx) error GetInstalledAppVersion(id int, userId int32) (*appStoreBean.InstallAppVersionDTO, error) InstallAppByHelm(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ctx context.Context) (*appStoreBean.InstallAppVersionDTO, error) UpdateProjectHelmApp(updateAppRequest *appStoreBean.UpdateProjectHelmAppDTO) error - UpdateNotesForInstalledApp(installAppId int, notes string) (bool, error) UpdatePreviousDeploymentStatusForAppStore(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, triggeredAt time.Time, err error) error UpdateInstallAppVersionHistoryStatus(installedAppVersionHistoryId int, status string) error + + GetInstalledAppByClusterNamespaceAndName(clusterId int, namespace string, appName string) (*appStoreBean.InstallAppVersionDTO, error) + GetInstalledAppByInstalledAppId(installedAppId int) (*appStoreBean.InstallAppVersionDTO, error) } type DeploymentServiceTypeConfig struct { @@ -100,7 +106,7 @@ type AppStoreDeploymentServiceImpl struct { appStoreDeploymentArgoCdService appStoreDeploymentTool.AppStoreDeploymentArgoCdService environmentService cluster.EnvironmentService clusterService cluster.ClusterService - helmAppService client.HelmAppService + helmAppService service.HelmAppService appStoreDeploymentCommonService appStoreDeploymentCommon.AppStoreDeploymentCommonService installedAppRepositoryHistory repository.InstalledAppVersionHistoryRepository deploymentTypeConfig *DeploymentServiceTypeConfig @@ -114,7 +120,7 @@ func NewAppStoreDeploymentServiceImpl(logger *zap.SugaredLogger, installedAppRep clusterInstalledAppsRepository repository.ClusterInstalledAppsRepository, appRepository app.AppRepository, appStoreDeploymentHelmService appStoreDeploymentTool.AppStoreDeploymentHelmService, appStoreDeploymentArgoCdService appStoreDeploymentTool.AppStoreDeploymentArgoCdService, environmentService cluster.EnvironmentService, - clusterService cluster.ClusterService, helmAppService client.HelmAppService, appStoreDeploymentCommonService appStoreDeploymentCommon.AppStoreDeploymentCommonService, + clusterService cluster.ClusterService, helmAppService service.HelmAppService, appStoreDeploymentCommonService appStoreDeploymentCommon.AppStoreDeploymentCommonService, installedAppRepositoryHistory repository.InstalledAppVersionHistoryRepository, deploymentTypeConfig *DeploymentServiceTypeConfig, aCDConfig *argocdServer.ACDConfig, gitOpsConfigReadService config.GitOpsConfigReadService, @@ -143,232 +149,6 @@ func NewAppStoreDeploymentServiceImpl(logger *zap.SugaredLogger, installedAppRep return appStoreDeploymentServiceImpl } -func (impl AppStoreDeploymentServiceImpl) AppStoreDeployOperationDB(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, tx *pg.Tx, skipAppCreation bool) (*appStoreBean.InstallAppVersionDTO, error) { - - var isInternalUse = impl.deploymentTypeConfig.IsInternalUse - isGitOpsConfigured, err := impl.gitOpsConfigReadService.IsGitOpsConfigured() - if err != nil { - impl.logger.Errorw("error while checking if gitOps is configured", "err", err) - return nil, err - } - if isInternalUse && !isGitOpsConfigured && installAppVersionRequest.DeploymentAppType == util.PIPELINE_DEPLOYMENT_TYPE_ACD { - impl.logger.Errorw("gitops not configured but selected for CD") - err := &util.ApiError{ - HttpStatusCode: http.StatusBadRequest, - InternalMessage: "Gitops integration is not installed/configured. Please install/configure gitops or use helm option.", - UserMessage: "Gitops integration is not installed/configured. Please install/configure gitops or use helm option.", - } - return nil, err - } - - appStoreAppVersion, err := impl.appStoreApplicationVersionRepository.FindById(installAppVersionRequest.AppStoreVersion) - if err != nil { - impl.logger.Errorw("fetching error", "err", err) - return nil, err - } - - var isOCIRepo bool - if appStoreAppVersion.AppStore.DockerArtifactStore != nil { - isOCIRepo = true - } else { - isOCIRepo = false - } - - var appInstallationMode string - if util2.IsBaseStack() || util2.IsHelmApp(installAppVersionRequest.AppOfferingMode) { - appInstallationMode = util2.SERVER_MODE_HYPERION - } else { - appInstallationMode = util2.SERVER_MODE_FULL - } - - // create env if env not exists for clusterId and namespace for hyperion mode - if util2.IsHelmApp(appInstallationMode) { - envId, err := impl.createEnvironmentIfNotExists(installAppVersionRequest) - if err != nil { - return nil, err - } - installAppVersionRequest.EnvironmentId = envId - } - - environment, err := impl.environmentRepository.FindById(installAppVersionRequest.EnvironmentId) - if err != nil { - impl.logger.Errorw("fetching error", "err", err) - return nil, err - } - installAppVersionRequest.Environment = environment - installAppVersionRequest.ACDAppName = fmt.Sprintf("%s-%s", installAppVersionRequest.AppName, installAppVersionRequest.Environment.Name) - installAppVersionRequest.ClusterId = environment.ClusterId - appCreateRequest := &bean.CreateAppDTO{ - Id: installAppVersionRequest.AppId, - AppName: installAppVersionRequest.AppName, - TeamId: installAppVersionRequest.TeamId, - UserId: installAppVersionRequest.UserId, - } - - appCreateRequest, err = impl.createAppForAppStore(appCreateRequest, tx, appInstallationMode, skipAppCreation) - if err != nil { - impl.logger.Errorw("error while creating app", "error", err) - return nil, err - } - installAppVersionRequest.AppId = appCreateRequest.Id - - installedAppModel := &repository.InstalledApps{ - AppId: appCreateRequest.Id, - EnvironmentId: environment.Id, - Status: appStoreBean.DEPLOY_INIT, - } - - if !isInternalUse { - if isGitOpsConfigured && appInstallationMode == util2.SERVER_MODE_FULL && !isOCIRepo { - installAppVersionRequest.DeploymentAppType = util.PIPELINE_DEPLOYMENT_TYPE_ACD - } else { - installAppVersionRequest.DeploymentAppType = util.PIPELINE_DEPLOYMENT_TYPE_HELM - } - } - if installAppVersionRequest.DeploymentAppType == "" { - if isGitOpsConfigured && !isOCIRepo { - installAppVersionRequest.DeploymentAppType = util.PIPELINE_DEPLOYMENT_TYPE_ACD - } else { - installAppVersionRequest.DeploymentAppType = util.PIPELINE_DEPLOYMENT_TYPE_HELM - } - } - - installedAppModel.DeploymentAppType = installAppVersionRequest.DeploymentAppType - installedAppModel.CreatedBy = installAppVersionRequest.UserId - installedAppModel.UpdatedBy = installAppVersionRequest.UserId - installedAppModel.CreatedOn = time.Now() - installedAppModel.UpdatedOn = time.Now() - installedAppModel.Active = true - if util2.IsFullStack() { - installedAppModel.GitOpsRepoName = impl.gitOpsConfigReadService.GetGitOpsRepoName(installAppVersionRequest.AppName) - installAppVersionRequest.GitOpsRepoName = installedAppModel.GitOpsRepoName - } - installedApp, err := impl.installedAppRepository.CreateInstalledApp(installedAppModel, tx) - if err != nil { - impl.logger.Errorw("error while creating install app", "error", err) - return nil, err - } - installAppVersionRequest.InstalledAppId = installedApp.Id - - installedAppVersions := &repository.InstalledAppVersions{ - InstalledAppId: installAppVersionRequest.InstalledAppId, - AppStoreApplicationVersionId: appStoreAppVersion.Id, - ValuesYaml: installAppVersionRequest.ValuesOverrideYaml, - //Values: "{}", - } - installedAppVersions.CreatedBy = installAppVersionRequest.UserId - installedAppVersions.UpdatedBy = installAppVersionRequest.UserId - installedAppVersions.CreatedOn = time.Now() - installedAppVersions.UpdatedOn = time.Now() - installedAppVersions.Active = true - installedAppVersions.ReferenceValueId = installAppVersionRequest.ReferenceValueId - installedAppVersions.ReferenceValueKind = installAppVersionRequest.ReferenceValueKind - _, err = impl.installedAppRepository.CreateInstalledAppVersion(installedAppVersions, tx) - if err != nil { - impl.logger.Errorw("error while fetching from db", "error", err) - return nil, err - } - installAppVersionRequest.InstalledAppVersionId = installedAppVersions.Id - installAppVersionRequest.Id = installedAppVersions.Id - - installedAppVersionHistory := &repository.InstalledAppVersionHistory{} - installedAppVersionHistory.InstalledAppVersionId = installedAppVersions.Id - installedAppVersionHistory.ValuesYamlRaw = installAppVersionRequest.ValuesOverrideYaml - installedAppVersionHistory.CreatedBy = installAppVersionRequest.UserId - installedAppVersionHistory.CreatedOn = time.Now() - installedAppVersionHistory.UpdatedBy = installAppVersionRequest.UserId - installedAppVersionHistory.UpdatedOn = time.Now() - installedAppVersionHistory.StartedOn = time.Now() - installedAppVersionHistory.Status = pipelineConfig.WorkflowInProgress - helmInstallConfigDTO := appStoreBean.HelmReleaseStatusConfig{ - InstallAppVersionHistoryId: 0, - Message: "Install initiated", - IsReleaseInstalled: false, - ErrorInInstallation: false, - } - helmInstallConfig, err := json.Marshal(helmInstallConfigDTO) - if err != nil { - impl.logger.Errorw("error in helm install config marshal", "err") - } - installedAppVersionHistory.HelmReleaseStatusConfig = string(helmInstallConfig) - _, err = impl.installedAppRepositoryHistory.CreateInstalledAppVersionHistory(installedAppVersionHistory, tx) - if err != nil { - impl.logger.Errorw("error while fetching from db", "error", err) - return nil, err - } - installAppVersionRequest.InstalledAppVersionHistoryId = installedAppVersionHistory.Id - if installAppVersionRequest.DefaultClusterComponent { - clusterInstalledAppsModel := &repository.ClusterInstalledApps{ - ClusterId: environment.ClusterId, - InstalledAppId: installAppVersionRequest.InstalledAppId, - } - clusterInstalledAppsModel.CreatedBy = installAppVersionRequest.UserId - clusterInstalledAppsModel.UpdatedBy = installAppVersionRequest.UserId - clusterInstalledAppsModel.CreatedOn = time.Now() - clusterInstalledAppsModel.UpdatedOn = time.Now() - err = impl.clusterInstalledAppsRepository.Save(clusterInstalledAppsModel, tx) - if err != nil { - impl.logger.Errorw("error while creating cluster install app", "error", err) - return nil, err - } - } - return installAppVersionRequest, nil -} - -func (impl AppStoreDeploymentServiceImpl) UpdateNotesForInstalledApp(installAppId int, notes string) (bool, error) { - dbConnection := impl.installedAppRepository.GetConnection() - tx, err := dbConnection.Begin() - if err != nil { - return false, err - } - // Rollback tx on error. - defer tx.Rollback() - installedApp, err := impl.installedAppRepository.GetInstalledApp(installAppId) - if err != nil { - impl.logger.Errorw("error while fetching from db", "error", err) - return false, err - } - installedApp.Notes = notes - _, err = impl.installedAppRepository.UpdateInstalledApp(installedApp, tx) - if err != nil { - impl.logger.Errorw("error while fetching from db", "error", err) - return false, err - } - err = tx.Commit() - if err != nil { - impl.logger.Errorw("error while commit db transaction to db", "error", err) - return false, err - } - return true, nil -} - -func (impl AppStoreDeploymentServiceImpl) AppStoreDeployOperationStatusUpdate(installAppId int, status appStoreBean.AppstoreDeploymentStatus) (bool, error) { - dbConnection := impl.installedAppRepository.GetConnection() - tx, err := dbConnection.Begin() - if err != nil { - return false, err - } - // Rollback tx on error. - defer tx.Rollback() - installedApp, err := impl.installedAppRepository.GetInstalledApp(installAppId) - if err != nil { - impl.logger.Errorw("error while fetching from db", "error", err) - return false, err - } - installedApp.Status = status - _, err = impl.installedAppRepository.UpdateInstalledApp(installedApp, tx) - if err != nil { - impl.logger.Errorw("error while fetching from db", "error", err) - return false, err - } - err = tx.Commit() - if err != nil { - impl.logger.Errorw("error while commit db transaction to db", "error", err) - return false, err - } - return true, nil -} - func (impl *AppStoreDeploymentServiceImpl) IsChartRepoActive(appStoreVersionId int) (bool, error) { appStoreAppVersion, err := impl.appStoreApplicationVersionRepository.FindById(appStoreVersionId) if err != nil { @@ -398,25 +178,24 @@ func (impl AppStoreDeploymentServiceImpl) InstallApp(installAppVersionRequest *a impl.logger.Errorw(" error", "err", err) return nil, err } - impl.updateDeploymentParametersInRequest(installAppVersionRequest, installAppVersionRequest.DeploymentAppType) + installedAppDeploymentAction := adapter.NewInstalledAppDeploymentAction(installAppVersionRequest.DeploymentAppType) if util.IsAcdApp(installAppVersionRequest.DeploymentAppType) || util.IsManifestDownload(installAppVersionRequest.DeploymentAppType) { _ = impl.appStoreDeploymentArgoCdService.SaveTimelineForACDHelmApps(installAppVersionRequest, pipelineConfig.TIMELINE_STATUS_DEPLOYMENT_INITIATED, "Deployment initiated successfully.", time.Now(), tx) } - manifest, err := impl.appStoreDeploymentCommonService.GenerateManifest(installAppVersionRequest) - if err != nil { - impl.logger.Errorw("error in performing manifest and git operations", "err", err) - return nil, err - } - - if installAppVersionRequest.DeploymentAppType == util.PIPELINE_DEPLOYMENT_TYPE_MANIFEST_DOWNLOAD { + if util.IsManifestDownload(installAppVersionRequest.DeploymentAppType) { _ = impl.appStoreDeploymentArgoCdService.SaveTimelineForACDHelmApps(installAppVersionRequest, pipelineConfig.TIMELINE_DESCRIPTION_MANIFEST_GENERATED, "Manifest generated successfully.", time.Now(), tx) } - var gitOpsResponse *appStoreDeploymentCommon.AppStoreGitOpsResponse - if installAppVersionRequest.PerformGitOps { - gitOpsResponse, err = impl.appStoreDeploymentCommonService.GitOpsOperations(manifest, installAppVersionRequest) + var gitOpsResponse *bean2.AppStoreGitOpsResponse + if installedAppDeploymentAction.PerformGitOps { + manifest, err := impl.appStoreDeploymentArgoCdService.GenerateManifest(installAppVersionRequest) + if err != nil { + impl.logger.Errorw("error in performing manifest and git operations", "err", err) + return nil, err + } + gitOpsResponse, err = impl.appStoreDeploymentArgoCdService.GitOpsOperations(manifest, installAppVersionRequest) if err != nil { impl.logger.Errorw("error in doing gitops operation", "err", err) if util.IsAcdApp(installAppVersionRequest.DeploymentAppType) { @@ -599,26 +378,12 @@ func (impl AppStoreDeploymentServiceImpl) GetInstalledApp(id int) (*appStoreBean impl.logger.Errorw("error while fetching from db", "error", err) return nil, err } - chartTemplate := impl.chartAdaptor2(app) + chartTemplate := adapter.GenerateInstallAppVersionMinDTO(app) return chartTemplate, nil } -// converts db object to bean -func (impl AppStoreDeploymentServiceImpl) chartAdaptor2(chart *repository.InstalledApps) *appStoreBean.InstallAppVersionDTO { - return &appStoreBean.InstallAppVersionDTO{ - EnvironmentId: chart.EnvironmentId, - InstalledAppId: chart.Id, - AppId: chart.AppId, - AppOfferingMode: chart.App.AppOfferingMode, - ClusterId: chart.Environment.ClusterId, - Namespace: chart.Environment.Namespace, - AppName: chart.App.AppName, - EnvironmentName: chart.Environment.Name, - } -} - func (impl AppStoreDeploymentServiceImpl) GetAllInstalledAppsByAppStoreId(w http.ResponseWriter, r *http.Request, token string, appStoreId int) ([]appStoreBean.InstalledAppsResponse, error) { - installedApps, err := impl.installedAppRepository.GetAllIntalledAppsByAppStoreId(appStoreId) + installedApps, err := impl.installedAppRepository.GetAllInstalledAppsByAppStoreId(appStoreId) if err != nil && !util.IsErrNoRows(err) { impl.logger.Error(err) return nil, err @@ -692,9 +457,7 @@ func (impl AppStoreDeploymentServiceImpl) DeleteInstalledApp(ctx context.Context } if installAppVersionRequest.AcdPartialDelete == true { - if util2.IsBaseStack() || util2.IsHelmApp(app.AppOfferingMode) || util.IsHelmApp(model.DeploymentAppType) { - err = impl.appStoreDeploymentHelmService.DeleteDeploymentApp(ctx, app.AppName, environment.Name, installAppVersionRequest) - } else { + if !util2.IsBaseStack() && !util2.IsHelmApp(app.AppOfferingMode) && !util.IsHelmApp(model.DeploymentAppType) { if !installAppVersionRequest.InstalledAppDeleteResponse.ClusterReachable { impl.logger.Errorw("cluster connection error", "err", environment.Cluster.ErrorInConnecting) if !installAppVersionRequest.NonCascadeDelete { @@ -791,7 +554,7 @@ func (impl AppStoreDeploymentServiceImpl) DeleteInstalledApp(ctx context.Context } func (impl AppStoreDeploymentServiceImpl) LinkHelmApplicationToChartStore(ctx context.Context, request *openapi.UpdateReleaseWithChartLinkingRequest, - appIdentifier *client.AppIdentifier, userId int32) (*openapi.UpdateReleaseResponse, bool, error) { + appIdentifier *service.AppIdentifier, userId int32) (*openapi.UpdateReleaseResponse, bool, error) { impl.logger.Infow("Linking helm application to chart store", "appId", request.GetAppId()) @@ -969,20 +732,20 @@ func (impl AppStoreDeploymentServiceImpl) linkHelmApplicationToChartStore(instal // STEP-2 update APP with chart info chartRepoInfo := appStoreAppVersion.AppStore.ChartRepo - updateReleaseRequest := &client.UpdateApplicationWithChartInfoRequestDto{ - InstallReleaseRequest: &client.InstallReleaseRequest{ + updateReleaseRequest := &bean3.UpdateApplicationWithChartInfoRequestDto{ + InstallReleaseRequest: &bean4.InstallReleaseRequest{ ValuesYaml: installAppVersionRequest.ValuesOverrideYaml, ChartName: appStoreAppVersion.Name, ChartVersion: appStoreAppVersion.Version, - ReleaseIdentifier: &client.ReleaseIdentifier{ + ReleaseIdentifier: &bean4.ReleaseIdentifier{ ReleaseNamespace: installAppVersionRequest.Namespace, ReleaseName: installAppVersionRequest.AppName, }, }, - SourceAppType: client.SOURCE_HELM_APP, + SourceAppType: bean3.SOURCE_HELM_APP, } if chartRepoInfo != nil { - updateReleaseRequest.ChartRepository = &client.ChartRepository{ + updateReleaseRequest.ChartRepository = &bean4.ChartRepository{ Name: chartRepoInfo.Name, Url: chartRepoInfo.Url, Username: chartRepoInfo.UserName, @@ -1066,8 +829,8 @@ func (impl AppStoreDeploymentServiceImpl) updateInstalledAppVersionHistoryWithSy } return nil } -func (impl AppStoreDeploymentServiceImpl) GetDeploymentHistory(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO) (*client.DeploymentHistoryAndInstalledAppInfo, error) { - result := &client.DeploymentHistoryAndInstalledAppInfo{} +func (impl AppStoreDeploymentServiceImpl) GetDeploymentHistory(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO) (*bean3.DeploymentHistoryAndInstalledAppInfo, error) { + result := &bean3.DeploymentHistoryAndInstalledAppInfo{} var err error if util2.IsHelmApp(installedApp.AppOfferingMode) { deploymentHistory, err := impl.appStoreDeploymentHelmService.GetDeploymentHistory(ctx, installedApp) @@ -1086,7 +849,7 @@ func (impl AppStoreDeploymentServiceImpl) GetDeploymentHistory(ctx context.Conte } if installedApp.InstalledAppId > 0 { - result.InstalledAppInfo = &client.InstalledAppInfo{ + result.InstalledAppInfo = &bean3.InstalledAppInfo{ AppId: installedApp.AppId, EnvironmentName: installedApp.EnvironmentName, AppOfferingMode: installedApp.AppOfferingMode, @@ -1249,6 +1012,8 @@ func (impl *AppStoreDeploymentServiceImpl) MarkInstalledAppVersionModelInActive( } func (impl *AppStoreDeploymentServiceImpl) CreateInstalledAppVersion(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, tx *pg.Tx) (*repository.InstalledAppVersions, error) { + // TODO fix me next + // TODO refactoring: move this to adapter installedAppVersion := &repository.InstalledAppVersions{ InstalledAppId: installAppVersionRequest.InstalledAppId, AppStoreApplicationVersionId: installAppVersionRequest.AppStoreVersion, @@ -1277,7 +1042,7 @@ func (impl *AppStoreDeploymentServiceImpl) CheckIfMonoRepoMigrationRequired(inst gitOpsRepoName := installedApp.GitOpsRepoName if len(gitOpsRepoName) == 0 { if util.IsAcdApp(installAppVersionRequest.DeploymentAppType) { - gitOpsRepoName, err = impl.appStoreDeploymentArgoCdService.GetGitOpsRepoName(installAppVersionRequest.AppName, installAppVersionRequest.EnvironmentName) + gitOpsRepoName, err = impl.appStoreDeploymentArgoCdService.GetAcdAppGitOpsRepoName(installAppVersionRequest.AppName, installAppVersionRequest.EnvironmentName) if err != nil { return false } @@ -1294,27 +1059,6 @@ func (impl *AppStoreDeploymentServiceImpl) CheckIfMonoRepoMigrationRequired(inst return monoRepoMigrationRequired } -func (impl *AppStoreDeploymentServiceImpl) updateDeploymentParametersInRequest(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, deploymentAppType string) { - - installAppVersionRequest.DeploymentAppType = deploymentAppType - - switch installAppVersionRequest.DeploymentAppType { - case util.PIPELINE_DEPLOYMENT_TYPE_ACD: - installAppVersionRequest.PerformGitOps = true - installAppVersionRequest.PerformACDDeployment = true - installAppVersionRequest.PerformHelmDeployment = false - case util.PIPELINE_DEPLOYMENT_TYPE_HELM: - installAppVersionRequest.PerformGitOps = false - installAppVersionRequest.PerformACDDeployment = false - installAppVersionRequest.PerformHelmDeployment = true - case util.PIPELINE_DEPLOYMENT_TYPE_MANIFEST_DOWNLOAD: - installAppVersionRequest.PerformGitOps = false - installAppVersionRequest.PerformHelmDeployment = false - installAppVersionRequest.PerformACDDeployment = false - } - -} - func (impl *AppStoreDeploymentServiceImpl) UpdateInstalledApp(ctx context.Context, installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*appStoreBean.InstallAppVersionDTO, error) { // db operations @@ -1330,8 +1074,9 @@ func (impl *AppStoreDeploymentServiceImpl) UpdateInstalledApp(ctx context.Contex if err != nil { return nil, err } + installAppVersionRequest.UpdateDeploymentAppType(installedApp.DeploymentAppType) - impl.updateDeploymentParametersInRequest(installAppVersionRequest, installedApp.DeploymentAppType) + installedAppDeploymentAction := adapter.NewInstalledAppDeploymentAction(installedApp.DeploymentAppType) var installedAppVersion *repository.InstalledAppVersions @@ -1373,6 +1118,8 @@ func (impl *AppStoreDeploymentServiceImpl) UpdateInstalledApp(ctx context.Contex } installedAppVersion.Id = installedAppVersion.Id } else { + // TODO fix me next + // TODO refactoring: move this to adapter installedAppVersion.ValuesYaml = installAppVersionRequest.ValuesOverrideYaml installedAppVersion.UpdatedOn = time.Now() installedAppVersion.UpdatedBy = installAppVersionRequest.UserId @@ -1396,6 +1143,8 @@ func (impl *AppStoreDeploymentServiceImpl) UpdateInstalledApp(ctx context.Contex installAppVersionRequest.Environment = &installedApp.Environment installAppVersionHistoryStatus := pipelineConfig.WorkflowInProgress + // TODO fix me next + // TODO refactoring: move this to adapter installedAppVersionHistory := &repository.InstalledAppVersionHistory{ InstalledAppVersionId: installedAppVersion.Id, ValuesYamlRaw: installAppVersionRequest.ValuesOverrideYaml, @@ -1416,26 +1165,25 @@ func (impl *AppStoreDeploymentServiceImpl) UpdateInstalledApp(ctx context.Contex installAppVersionRequest.InstalledAppVersionHistoryId = installedAppVersionHistory.Id _ = impl.appStoreDeploymentArgoCdService.SaveTimelineForACDHelmApps(installAppVersionRequest, pipelineConfig.TIMELINE_STATUS_DEPLOYMENT_INITIATED, "Deployment initiated successfully.", time.Now(), tx) - manifest, err := impl.appStoreDeploymentCommonService.GenerateManifest(installAppVersionRequest) - if err != nil { - impl.logger.Errorw("error in generating manifest for helm apps", "err", err) - _ = impl.UpdateInstalledAppVersionHistoryStatus(installAppVersionRequest, pipelineConfig.WorkflowFailed) - return nil, err - } - if installAppVersionRequest.DeploymentAppType == util.PIPELINE_DEPLOYMENT_TYPE_MANIFEST_DOWNLOAD { + if util.IsManifestDownload(installAppVersionRequest.DeploymentAppType) { _ = impl.appStoreDeploymentArgoCdService.SaveTimelineForACDHelmApps(installAppVersionRequest, pipelineConfig.TIMELINE_DESCRIPTION_MANIFEST_GENERATED, "Manifest generated successfully.", time.Now(), tx) } // gitOps operation monoRepoMigrationRequired := false - gitOpsResponse := &appStoreDeploymentCommon.AppStoreGitOpsResponse{} - - if installAppVersionRequest.PerformGitOps { + gitOpsResponse := &bean2.AppStoreGitOpsResponse{} + if installedAppDeploymentAction.PerformGitOps { + manifest, err := impl.appStoreDeploymentArgoCdService.GenerateManifest(installAppVersionRequest) + if err != nil { + impl.logger.Errorw("error in generating manifest for helm apps", "err", err) + _ = impl.UpdateInstalledAppVersionHistoryStatus(installAppVersionRequest, pipelineConfig.WorkflowFailed) + return nil, err + } // required if gitOps repo name is changed, gitOps repo name will change if env variable which we use as suffix changes gitOpsRepoName := installedApp.GitOpsRepoName if len(gitOpsRepoName) == 0 { if util.IsAcdApp(installAppVersionRequest.DeploymentAppType) { - gitOpsRepoName, err = impl.appStoreDeploymentArgoCdService.GetGitOpsRepoName(installAppVersionRequest.AppName, installAppVersionRequest.EnvironmentName) + gitOpsRepoName, err = impl.appStoreDeploymentArgoCdService.GetAcdAppGitOpsRepoName(installAppVersionRequest.AppName, installAppVersionRequest.EnvironmentName) if err != nil { return nil, err } @@ -1458,10 +1206,10 @@ func (impl *AppStoreDeploymentServiceImpl) UpdateInstalledApp(ctx context.Contex var createRepoErr, requirementsCommitErr, valuesCommitErr error var gitHash string - + // TODO refactoring: move this logic to AppStoreDeploymentGitService.go if monoRepoMigrationRequired { // create new git repo if repo name changed - gitOpsResponse, createRepoErr = impl.appStoreDeploymentCommonService.GitOpsOperations(manifest, installAppVersionRequest) + gitOpsResponse, createRepoErr = impl.appStoreDeploymentArgoCdService.GitOpsOperations(manifest, installAppVersionRequest) gitHash = gitOpsResponse.GitHash } else if isChartChanged || isVersionChanged { @@ -1476,13 +1224,13 @@ func (impl *AppStoreDeploymentServiceImpl) UpdateInstalledApp(ctx context.Contex if valuesCommitErr != nil || requirementsCommitErr != nil { - noTargetFoundForValues, _ := impl.appStoreDeploymentCommonService.ParseGitRepoErrorResponse(valuesCommitErr) - noTargetFoundForRequirements, _ := impl.appStoreDeploymentCommonService.ParseGitRepoErrorResponse(requirementsCommitErr) + noTargetFoundForValues, _ := impl.appStoreDeploymentArgoCdService.ParseGitRepoErrorResponse(valuesCommitErr) + noTargetFoundForRequirements, _ := impl.appStoreDeploymentArgoCdService.ParseGitRepoErrorResponse(requirementsCommitErr) if noTargetFoundForRequirements || noTargetFoundForValues { //create repo again and try again - auto fix monoRepoMigrationRequired = true // since repo is created again, will use this flag to check if ACD patch operation required - gitOpsResponse, createRepoErr = impl.appStoreDeploymentCommonService.GitOpsOperations(manifest, installAppVersionRequest) + gitOpsResponse, createRepoErr = impl.appStoreDeploymentArgoCdService.GitOpsOperations(manifest, installAppVersionRequest) gitHash = gitOpsResponse.GitHash } @@ -1491,6 +1239,7 @@ func (impl *AppStoreDeploymentServiceImpl) UpdateInstalledApp(ctx context.Contex if createRepoErr != nil || requirementsCommitErr != nil || valuesCommitErr != nil { impl.logger.Errorw("error in doing gitops operation", "err", err) _ = impl.appStoreDeploymentArgoCdService.SaveTimelineForACDHelmApps(installAppVersionRequest, pipelineConfig.TIMELINE_STATUS_GIT_COMMIT_FAILED, fmt.Sprintf("Git commit failed - %v", err), time.Now(), tx) + // TODO refactoring: return proper err object return nil, err } @@ -1507,14 +1256,14 @@ func (impl *AppStoreDeploymentServiceImpl) UpdateInstalledApp(ctx context.Contex } } - if installAppVersionRequest.PerformACDDeployment { + if installedAppDeploymentAction.PerformACDDeployment { // refresh update repo details on ArgoCD if repo is changed err = impl.appStoreDeploymentArgoCdService.UpdateAndSyncACDApps(installAppVersionRequest, gitOpsResponse.ChartGitAttribute, monoRepoMigrationRequired, ctx, tx) if err != nil { impl.logger.Errorw("error in acd patch request", "err", err) return nil, err } - } else if installAppVersionRequest.PerformHelmDeployment { + } else if installedAppDeploymentAction.PerformHelmDeployment { err = impl.appStoreDeploymentHelmService.UpdateChartInfo(installAppVersionRequest, gitOpsResponse.ChartGitAttribute, installAppVersionRequest.InstalledAppVersionHistoryId, ctx) if err != nil { if err != nil { diff --git a/pkg/appStore/deployment/service/AppStoreDeploymentService_test.go b/pkg/appStore/deployment/service/AppStoreDeploymentService_test.go index 79a6fd1f9ff..81eae677837 100644 --- a/pkg/appStore/deployment/service/AppStoreDeploymentService_test.go +++ b/pkg/appStore/deployment/service/AppStoreDeploymentService_test.go @@ -9,7 +9,7 @@ import ( "github.com/devtron-labs/devtron/internal/sql/repository/app" "github.com/devtron-labs/devtron/internal/util" appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" - repository5 "github.com/devtron-labs/devtron/pkg/appStore/chartGroup/repository" + repository6 "github.com/devtron-labs/devtron/pkg/appStore/chartGroup/repository" repository3 "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" appStoreDiscoverRepository "github.com/devtron-labs/devtron/pkg/appStore/discover/repository" repository5 "github.com/devtron-labs/devtron/pkg/auth/user/repository" @@ -134,7 +134,7 @@ func initAppStoreDeploymentService(t *testing.T, internalUse bool) *AppStoreDepl db, _ := sql.NewDbConnection(config, sugaredLogger) gitOpsRepository := repository.NewGitOpsConfigRepositoryImpl(sugaredLogger, db) - chartGroupDeploymentRepository := repository5.NewChartGroupDeploymentRepositoryImpl(db, sugaredLogger) + chartGroupDeploymentRepository := repository6.NewChartGroupDeploymentRepositoryImpl(db, sugaredLogger) appStoreDiscoverRepository := appStoreDiscoverRepository.NewAppStoreApplicationVersionRepositoryImpl(sugaredLogger, db) @@ -171,11 +171,11 @@ func initAppStoreDeploymentService(t *testing.T, internalUse bool) *AppStoreDepl clusterService, nil, nil, - nil, InstalledAppVersionHistoryRepository, gitOpsRepository, - nil, &DeploymentServiceTypeConfig{IsInternalUse: internalUse}, + nil, + nil, nil) return AppStoreDeploymentServiceImpl diff --git a/pkg/appStore/deployment/service/InstalledAppService.go b/pkg/appStore/deployment/service/InstalledAppService.go index 438e8adbf1a..3627794d9a9 100644 --- a/pkg/appStore/deployment/service/InstalledAppService.go +++ b/pkg/appStore/deployment/service/InstalledAppService.go @@ -20,9 +20,12 @@ package service import ( "bytes" "context" + "github.com/devtron-labs/devtron/api/helm-app/gRPC" + client "github.com/devtron-labs/devtron/api/helm-app/service" + appStoreDeploymentTool "github.com/devtron-labs/devtron/pkg/appStore/deployment/tool" commonBean "github.com/devtron-labs/devtron/pkg/deployment/gitOps/common/bean" - "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config" "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git" + util2 "github.com/devtron-labs/devtron/pkg/util" /* #nosec */ "crypto/sha1" @@ -38,7 +41,6 @@ import ( "github.com/argoproj/argo-cd/v2/pkg/apiclient/application" "github.com/devtron-labs/common-lib/pubsub-lib/model" util4 "github.com/devtron-labs/common-lib/utils/k8s" - client "github.com/devtron-labs/devtron/api/helm-app" openapi "github.com/devtron-labs/devtron/api/helm-app/openapiClient" "github.com/devtron-labs/devtron/client/argocdServer" "github.com/devtron-labs/devtron/internal/middleware" @@ -49,8 +51,6 @@ import ( appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" "github.com/devtron-labs/devtron/pkg/appStore/chartGroup" repository6 "github.com/devtron-labs/devtron/pkg/appStore/chartGroup/repository" - appStoreDeploymentCommon "github.com/devtron-labs/devtron/pkg/appStore/deployment/common" - appStoreDeploymentFullMode "github.com/devtron-labs/devtron/pkg/appStore/deployment/fullMode" repository2 "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" appStoreDiscoverRepository "github.com/devtron-labs/devtron/pkg/appStore/discover/repository" "github.com/devtron-labs/devtron/pkg/appStore/values/service" @@ -60,7 +60,6 @@ import ( application3 "github.com/devtron-labs/devtron/pkg/k8s/application" "github.com/devtron-labs/devtron/pkg/sql" repository4 "github.com/devtron-labs/devtron/pkg/team" - util2 "github.com/devtron-labs/devtron/pkg/util" util3 "github.com/devtron-labs/devtron/util" "github.com/devtron-labs/devtron/util/argo" @@ -103,25 +102,23 @@ type InstalledAppServiceImpl struct { appRepository app.AppRepository acdClient application2.ServiceClient appStoreValuesService service.AppStoreValuesService - pubsubClient *pubsub.PubSubClientServiceImpl + pubSubClient *pubsub.PubSubClientServiceImpl chartGroupDeploymentRepository repository6.ChartGroupDeploymentRepository envService cluster2.EnvironmentService aCDAuthConfig *util2.ACDAuthConfig userService user.UserService appStoreDeploymentService AppStoreDeploymentService - appStoreDeploymentFullModeService appStoreDeploymentFullMode.AppStoreDeploymentFullModeService installedAppRepositoryHistory repository2.InstalledAppVersionHistoryRepository argoUserService argo.ArgoUserService - helmAppClient client.HelmAppClient + helmAppClient gRPC.HelmAppClient helmAppService client.HelmAppService appStatusService appStatus.AppStatusService K8sUtil *util4.K8sServiceImpl pipelineStatusTimelineService status.PipelineStatusTimelineService - appStoreDeploymentCommonService appStoreDeploymentCommon.AppStoreDeploymentCommonService k8sCommonService k8s.K8sCommonService k8sApplicationService application3.K8sApplicationService acdConfig *argocdServer.ACDConfig - gitOpsConfigReadService config.GitOpsConfigReadService + appStoreDeploymentArgoCdService appStoreDeploymentTool.AppStoreDeploymentArgoCdService gitOperationService git.GitOperationService } @@ -132,17 +129,16 @@ func NewInstalledAppServiceImpl(logger *zap.SugaredLogger, appRepository app.AppRepository, acdClient application2.ServiceClient, appStoreValuesService service.AppStoreValuesService, pubsubClient *pubsub.PubSubClientServiceImpl, chartGroupDeploymentRepository repository6.ChartGroupDeploymentRepository, - envService cluster2.EnvironmentService, aCDAuthConfig *util2.ACDAuthConfig, userService user.UserService, - appStoreDeploymentFullModeService appStoreDeploymentFullMode.AppStoreDeploymentFullModeService, + envService cluster2.EnvironmentService, + userService user.UserService, aCDAuthConfig *util2.ACDAuthConfig, appStoreDeploymentService AppStoreDeploymentService, installedAppRepositoryHistory repository2.InstalledAppVersionHistoryRepository, - argoUserService argo.ArgoUserService, helmAppClient client.HelmAppClient, helmAppService client.HelmAppService, + argoUserService argo.ArgoUserService, helmAppClient gRPC.HelmAppClient, helmAppService client.HelmAppService, appStatusService appStatus.AppStatusService, K8sUtil *util4.K8sServiceImpl, pipelineStatusTimelineService status.PipelineStatusTimelineService, - appStoreDeploymentCommonService appStoreDeploymentCommon.AppStoreDeploymentCommonService, k8sCommonService k8s.K8sCommonService, k8sApplicationService application3.K8sApplicationService, - acdConfig *argocdServer.ACDConfig, gitOpsConfigReadService config.GitOpsConfigReadService, - gitOperationService git.GitOperationService) (*InstalledAppServiceImpl, error) { + acdConfig *argocdServer.ACDConfig, gitOperationService git.GitOperationService, + appStoreDeploymentArgoCdService appStoreDeploymentTool.AppStoreDeploymentArgoCdService) (*InstalledAppServiceImpl, error) { impl := &InstalledAppServiceImpl{ logger: logger, installedAppRepository: installedAppRepository, @@ -152,13 +148,12 @@ func NewInstalledAppServiceImpl(logger *zap.SugaredLogger, appRepository: appRepository, acdClient: acdClient, appStoreValuesService: appStoreValuesService, - pubsubClient: pubsubClient, + pubSubClient: pubsubClient, chartGroupDeploymentRepository: chartGroupDeploymentRepository, envService: envService, aCDAuthConfig: aCDAuthConfig, userService: userService, appStoreDeploymentService: appStoreDeploymentService, - appStoreDeploymentFullModeService: appStoreDeploymentFullModeService, installedAppRepositoryHistory: installedAppRepositoryHistory, argoUserService: argoUserService, helmAppClient: helmAppClient, @@ -166,19 +161,67 @@ func NewInstalledAppServiceImpl(logger *zap.SugaredLogger, appStatusService: appStatusService, K8sUtil: K8sUtil, pipelineStatusTimelineService: pipelineStatusTimelineService, - appStoreDeploymentCommonService: appStoreDeploymentCommonService, k8sCommonService: k8sCommonService, k8sApplicationService: k8sApplicationService, acdConfig: acdConfig, - gitOpsConfigReadService: gitOpsConfigReadService, gitOperationService: gitOperationService, + appStoreDeploymentArgoCdService: appStoreDeploymentArgoCdService, + } + err := impl.subscribe() + if err != nil { + return nil, err } - err := impl.Subscribe() + err = impl.subscribeHelmInstallStatus() if err != nil { return nil, err } return impl, nil } +func (impl InstalledAppServiceImpl) subscribeHelmInstallStatus() error { + + callback := func(msg *model.PubSubMsg) { + + helmInstallNatsMessage := &appStoreBean.HelmReleaseStatusConfig{} + err := json.Unmarshal([]byte(msg.Data), helmInstallNatsMessage) + if err != nil { + impl.logger.Errorw("error in unmarshalling helm install status nats message", "err", err) + return + } + + installedAppVersionHistory, err := impl.installedAppRepositoryHistory.GetInstalledAppVersionHistory(helmInstallNatsMessage.InstallAppVersionHistoryId) + if err != nil { + impl.logger.Errorw("error in fetching installed app by installed app id in subscribe helm status callback", "err", err) + return + } + if helmInstallNatsMessage.ErrorInInstallation { + installedAppVersionHistory.Status = pipelineConfig.WorkflowFailed + } else { + installedAppVersionHistory.Status = pipelineConfig.WorkflowSucceeded + } + installedAppVersionHistory.HelmReleaseStatusConfig = msg.Data + _, err = impl.installedAppRepositoryHistory.UpdateInstalledAppVersionHistory(installedAppVersionHistory, nil) + if err != nil { + impl.logger.Errorw("error in updating helm release status data in installedAppVersionHistoryRepository", "err", err) + return + } + } + // add required logging here + var loggerFunc pubsub.LoggerFunc = func(msg model.PubSubMsg) (string, []interface{}) { + helmInstallNatsMessage := &appStoreBean.HelmReleaseStatusConfig{} + err := json.Unmarshal([]byte(msg.Data), helmInstallNatsMessage) + if err != nil { + return "error in unmarshalling helm install status nats message", []interface{}{"err", err} + } + return "got nats msg for helm chart install status", []interface{}{"InstallAppVersionHistoryId", helmInstallNatsMessage.InstallAppVersionHistoryId, "ErrorInInstallation", helmInstallNatsMessage.ErrorInInstallation, "IsReleaseInstalled", helmInstallNatsMessage.IsReleaseInstalled} + } + + err := impl.pubSubClient.Subscribe(pubsub.HELM_CHART_INSTALL_STATUS_TOPIC, callback, loggerFunc) + if err != nil { + impl.logger.Error(err) + return err + } + return nil +} func (impl InstalledAppServiceImpl) GetAll(filter *appStoreBean.AppStoreFilter) (openapi.AppList, error) { applicationType := "DEVTRON-CHART-STORE" @@ -357,7 +400,7 @@ func (impl InstalledAppServiceImpl) performDeployStageOnAcd(installedAppVersion installedAppVersion.Status == appStoreBean.GIT_ERROR { //step 2 git operation pull push //TODO: save git Timeline here - appStoreGitOpsResponse, err := impl.appStoreDeploymentCommonService.GenerateManifestAndPerformGitOperations(installedAppVersion) + appStoreGitOpsResponse, err := impl.appStoreDeploymentArgoCdService.GenerateManifestAndPerformGitOperations(installedAppVersion) if err != nil { impl.logger.Errorw(" error", "err", err) _, err = impl.appStoreDeploymentService.AppStoreDeployOperationStatusUpdate(installedAppVersion.InstalledAppId, appStoreBean.GIT_ERROR) @@ -459,7 +502,7 @@ func (impl InstalledAppServiceImpl) performDeployStageOnAcd(installedAppVersion installedAppVersion.Status == appStoreBean.GIT_SUCCESS || installedAppVersion.Status == appStoreBean.ACD_ERROR { //step 3 acd operation register, sync - _, err := impl.appStoreDeploymentFullModeService.AppStoreDeployOperationACD(installedAppVersion, chartGitAttr, ctx, nil) + _, err := impl.appStoreDeploymentArgoCdService.InstallApp(installedAppVersion, chartGitAttr, ctx, nil) if err != nil { impl.logger.Errorw("error", "chartGitAttr", chartGitAttr, "err", err) _, err = impl.appStoreDeploymentService.AppStoreDeployOperationStatusUpdate(installedAppVersion.InstalledAppId, appStoreBean.ACD_ERROR) @@ -576,7 +619,7 @@ func (impl *InstalledAppServiceImpl) triggerDeploymentEvent(installAppVersions [ if err != nil { status = appStoreBean.QUE_ERROR } else { - err = impl.pubsubClient.Publish(pubsub.BULK_APPSTORE_DEPLOY_TOPIC, string(data)) + err = impl.pubSubClient.Publish(pubsub.BULK_APPSTORE_DEPLOY_TOPIC, string(data)) if err != nil { impl.logger.Errorw("err while publishing msg for app-store bulk deploy", "msg", data, "err", err) status = appStoreBean.QUE_ERROR @@ -595,7 +638,7 @@ func (impl *InstalledAppServiceImpl) triggerDeploymentEvent(installAppVersions [ } } -func (impl *InstalledAppServiceImpl) Subscribe() error { +func (impl *InstalledAppServiceImpl) subscribe() error { callback := func(msg *model.PubSubMsg) { deployPayload := &appStoreBean.DeployPayload{} err := json.Unmarshal([]byte(string(msg.Data)), &deployPayload) @@ -621,7 +664,7 @@ func (impl *InstalledAppServiceImpl) Subscribe() error { return "got message for deploy app-store apps in bulk", []interface{}{"installedAppVersionId", deployPayload.InstalledAppVersionId, "installedAppVersionHistoryId", deployPayload.InstalledAppVersionHistoryId} } - err := impl.pubsubClient.Subscribe(pubsub.BULK_APPSTORE_DEPLOY_TOPIC, callback, loggerFunc) + err := impl.pubSubClient.Subscribe(pubsub.BULK_APPSTORE_DEPLOY_TOPIC, callback, loggerFunc) if err != nil { impl.logger.Error("err", err) return err @@ -966,9 +1009,9 @@ func (impl InstalledAppServiceImpl) GetInstalledAppVersionHistoryValues(installe return values, err } -func (impl InstalledAppServiceImpl) getReleaseStatusFromHelmReleaseInstallStatus(helmReleaseInstallStatus string, status string) *client.ReleaseStatus { +func (impl InstalledAppServiceImpl) getReleaseStatusFromHelmReleaseInstallStatus(helmReleaseInstallStatus string, status string) *gRPC.ReleaseStatus { //release status is sent in resource tree call and is shown on UI as helm config apply status - releaseStatus := &client.ReleaseStatus{} + releaseStatus := &gRPC.ReleaseStatus{} if len(helmReleaseInstallStatus) > 0 { helmInstallStatus := &appStoreBean.HelmReleaseStatusConfig{} err := json.Unmarshal([]byte(helmReleaseInstallStatus), helmInstallStatus) @@ -998,6 +1041,7 @@ func (impl InstalledAppServiceImpl) getReleaseStatusFromHelmReleaseInstallStatus return releaseStatus } +// TODO fix me next func (impl InstalledAppServiceImpl) MarkGitOpsInstalledAppsDeletedIfArgoAppIsDeleted(installedAppId int, envId int) error { apiError := &util.ApiError{} installedApp, err := impl.installedAppRepository.GetGitOpsInstalledAppsWhereArgoAppDeletedIsTrue(installedAppId, envId) @@ -1007,6 +1051,7 @@ func (impl InstalledAppServiceImpl) MarkGitOpsInstalledAppsDeletedIfArgoAppIsDel apiError.InternalMessage = "error in fetching partially deleted argoCd apps from installed app repo" return apiError } + // TODO refactoring: move the below logic to AppStoreDeploymentArgoCdService.go acdToken, err := impl.argoUserService.GetLatestDevtronArgoCdUserToken() if err != nil { impl.logger.Errorw("error in getting acd token", "err", err) diff --git a/pkg/appStore/deployment/service/InstalledAppService_test.go b/pkg/appStore/deployment/service/InstalledAppService_test.go index 7bf2ca08c3a..206b4c35abf 100644 --- a/pkg/appStore/deployment/service/InstalledAppService_test.go +++ b/pkg/appStore/deployment/service/InstalledAppService_test.go @@ -5,13 +5,10 @@ import ( "testing" pubsub "github.com/devtron-labs/common-lib/pubsub-lib" - "github.com/devtron-labs/devtron/client/argocdServer" "github.com/devtron-labs/devtron/client/argocdServer/application" - repository2 "github.com/devtron-labs/devtron/client/argocdServer/repository" "github.com/devtron-labs/devtron/internal/sql/repository/app" "github.com/devtron-labs/devtron/internal/util" repository5 "github.com/devtron-labs/devtron/pkg/appStore/chartGroup/repository" - appStoreDeploymentFullMode "github.com/devtron-labs/devtron/pkg/appStore/deployment/fullMode" repository4 "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" appStoreDiscoverRepository "github.com/devtron-labs/devtron/pkg/appStore/discover/repository" "github.com/devtron-labs/devtron/pkg/appStore/values/service" @@ -28,7 +25,6 @@ func TestInstalledAppServiceImpl_DeployDefaultChartOnCluster(t *testing.T) { logger *zap.SugaredLogger installedAppRepository repository4.InstalledAppRepository chartTemplateService util.ChartTemplateService - repositoryService repository2.ServiceClient appStoreApplicationVersionRepository appStoreDiscoverRepository.AppStoreApplicationVersionRepository environmentRepository repository.EnvironmentRepository teamRepository team.TeamRepository @@ -36,15 +32,12 @@ func TestInstalledAppServiceImpl_DeployDefaultChartOnCluster(t *testing.T) { acdClient application.ServiceClient appStoreValuesService service.AppStoreValuesService pubsubClient *pubsub.PubSubClientServiceImpl - tokenCache *util2.TokenCache chartGroupDeploymentRepository repository5.ChartGroupDeploymentRepository envService cluster.EnvironmentService - ArgoK8sClient argocdServer.ArgoK8sClient gitFactory *git.GitFactory aCDAuthConfig *util2.ACDAuthConfig userService user.UserService appStoreDeploymentService AppStoreDeploymentService - appStoreDeploymentFullModeService appStoreDeploymentFullMode.AppStoreDeploymentFullModeService } type args struct { bean *cluster.ClusterBean @@ -70,13 +63,12 @@ func TestInstalledAppServiceImpl_DeployDefaultChartOnCluster(t *testing.T) { appRepository: tt.fields.appRepository, acdClient: tt.fields.acdClient, appStoreValuesService: tt.fields.appStoreValuesService, - pubsubClient: tt.fields.pubsubClient, + pubSubClient: tt.fields.pubsubClient, chartGroupDeploymentRepository: tt.fields.chartGroupDeploymentRepository, envService: tt.fields.envService, aCDAuthConfig: tt.fields.aCDAuthConfig, userService: tt.fields.userService, appStoreDeploymentService: tt.fields.appStoreDeploymentService, - appStoreDeploymentFullModeService: tt.fields.appStoreDeploymentFullModeService, } got, err := impl.DeployDefaultChartOnCluster(tt.args.bean, tt.args.userId) if (err != nil) != tt.wantErr { diff --git a/pkg/appStore/deployment/service/Notes.go b/pkg/appStore/deployment/service/Notes.go index 018eabdf30c..8252202a16d 100644 --- a/pkg/appStore/deployment/service/Notes.go +++ b/pkg/appStore/deployment/service/Notes.go @@ -3,7 +3,7 @@ package service import ( "context" "fmt" - "github.com/devtron-labs/devtron/api/helm-app" + "github.com/devtron-labs/devtron/api/helm-app/gRPC" "github.com/devtron-labs/devtron/internal/util" "github.com/go-pg/pg" "net/http" @@ -82,18 +82,18 @@ func (impl *InstalledAppServiceImpl) findNotesForArgoApplication(installedAppId, return notes, appName, err } - installReleaseRequest := &client.InstallReleaseRequest{ + installReleaseRequest := &gRPC.InstallReleaseRequest{ ChartName: appStoreAppVersion.Name, ChartVersion: appStoreAppVersion.Version, ValuesYaml: installedAppVerison.ValuesYaml, K8SVersion: k8sServerVersion.String(), - ChartRepository: &client.ChartRepository{ + ChartRepository: &gRPC.ChartRepository{ Name: appStoreAppVersion.AppStore.ChartRepo.Name, Url: appStoreAppVersion.AppStore.ChartRepo.Url, Username: appStoreAppVersion.AppStore.ChartRepo.UserName, Password: appStoreAppVersion.AppStore.ChartRepo.Password, }, - ReleaseIdentifier: &client.ReleaseIdentifier{ + ReleaseIdentifier: &gRPC.ReleaseIdentifier{ ReleaseNamespace: installedAppVerison.InstalledApp.Environment.Namespace, ReleaseName: installedAppVerison.InstalledApp.App.AppName, }, @@ -112,7 +112,7 @@ func (impl *InstalledAppServiceImpl) findNotesForArgoApplication(installedAppId, impl.logger.Errorw("error in fetching notes", "err", err) return notes, appName, err } - _, err = impl.appStoreDeploymentService.UpdateNotesForInstalledApp(installedAppId, notes) + _, err = impl.updateNotesForInstalledApp(installedAppId, notes) if err != nil { impl.logger.Errorw("error in updating notes in db ", "err", err) return notes, appName, err @@ -121,3 +121,31 @@ func (impl *InstalledAppServiceImpl) findNotesForArgoApplication(installedAppId, return notes, appName, nil } + +// updateNotesForInstalledApp will update the notes in repository.InstalledApps table +func (impl *InstalledAppServiceImpl) updateNotesForInstalledApp(installAppId int, notes string) (bool, error) { + dbConnection := impl.installedAppRepository.GetConnection() + tx, err := dbConnection.Begin() + if err != nil { + return false, err + } + // Rollback tx on error. + defer tx.Rollback() + installedApp, err := impl.installedAppRepository.GetInstalledApp(installAppId) + if err != nil { + impl.logger.Errorw("error while fetching from db", "error", err) + return false, err + } + installedApp.Notes = notes + _, err = impl.installedAppRepository.UpdateInstalledApp(installedApp, tx) + if err != nil { + impl.logger.Errorw("error while fetching from db", "error", err) + return false, err + } + err = tx.Commit() + if err != nil { + impl.logger.Errorw("error while commit db transaction to db", "error", err) + return false, err + } + return true, nil +} diff --git a/pkg/appStore/deployment/service/ResourceTree.go b/pkg/appStore/deployment/service/ResourceTree.go index e826bacb556..3d0e36b617f 100644 --- a/pkg/appStore/deployment/service/ResourceTree.go +++ b/pkg/appStore/deployment/service/ResourceTree.go @@ -8,7 +8,7 @@ import ( "github.com/devtron-labs/common-lib/utils/k8s/commonBean" "github.com/devtron-labs/common-lib/utils/k8sObjectsUtil" "github.com/devtron-labs/devtron/api/bean" - "github.com/devtron-labs/devtron/api/helm-app" + bean2 "github.com/devtron-labs/devtron/api/helm-app/gRPC" "github.com/devtron-labs/devtron/internal/constants" "github.com/devtron-labs/devtron/internal/util" "github.com/devtron-labs/devtron/pkg/appStatus" @@ -35,7 +35,7 @@ func (impl InstalledAppServiceImpl) FetchResourceTree(rctx context.Context, cn h if err != nil { impl.logger.Errorw("error in fetching cluster detail", "err", err) } - req := &client.AppDetailRequest{ + req := &bean2.AppDetailRequest{ ClusterConfig: config, Namespace: installedApp.Environment.Namespace, ReleaseName: installedApp.App.AppName, diff --git a/pkg/appStore/deployment/tool/AppStoreDeploymentArgoCdService.go b/pkg/appStore/deployment/tool/AppStoreDeploymentArgoCdService.go index d3873c1aee5..ca1525a7a93 100644 --- a/pkg/appStore/deployment/tool/AppStoreDeploymentArgoCdService.go +++ b/pkg/appStore/deployment/tool/AppStoreDeploymentArgoCdService.go @@ -5,15 +5,20 @@ import ( "encoding/json" "errors" "fmt" + "github.com/devtron-labs/devtron/api/helm-app/gRPC" + client "github.com/devtron-labs/devtron/api/helm-app/service" + "github.com/devtron-labs/devtron/pkg/appStore/deployment/tool/bean" + repository5 "github.com/devtron-labs/devtron/pkg/cluster/repository" commonBean "github.com/devtron-labs/devtron/pkg/deployment/gitOps/common/bean" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config" "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git" + util2 "github.com/devtron-labs/devtron/pkg/util" "net/http" "strings" "time" "github.com/argoproj/argo-cd/v2/pkg/apiclient/application" "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" - client "github.com/devtron-labs/devtron/api/helm-app" openapi "github.com/devtron-labs/devtron/api/helm-app/openapiClient" openapi2 "github.com/devtron-labs/devtron/api/openapi/openapiClient" "github.com/devtron-labs/devtron/client/argocdServer" @@ -25,11 +30,11 @@ import ( appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" repository2 "github.com/devtron-labs/devtron/pkg/appStore/chartGroup/repository" appStoreDeploymentCommon "github.com/devtron-labs/devtron/pkg/appStore/deployment/common" - appStoreDeploymentFullMode "github.com/devtron-labs/devtron/pkg/appStore/deployment/fullMode" "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" appStoreDiscoverRepository "github.com/devtron-labs/devtron/pkg/appStore/discover/repository" "github.com/devtron-labs/devtron/pkg/auth/user" "github.com/devtron-labs/devtron/pkg/sql" + "github.com/devtron-labs/devtron/util/argo" "github.com/go-pg/pg" "github.com/golang/protobuf/ptypes/timestamp" "go.opentelemetry.io/otel" @@ -40,26 +45,51 @@ import ( // creating duplicates because cannot use type AppStoreDeploymentArgoCdService interface { - //InstallApp(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ctx context.Context) (*appStoreBean.InstallAppVersionDTO, error) + // ArgoCd Services --------------------------------- + + // InstallApp will register git repo in Argo, create and sync the Argo App and finally update deployment status InstallApp(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, chartGitAttr *commonBean.ChartGitAttribute, ctx context.Context, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, error) + // DeleteInstalledApp will delete entry from appStatus.AppStatusDto table and from repository.ChartGroupDeployment table (if exists) DeleteInstalledApp(ctx context.Context, appName string, environmentName string, installAppVersionRequest *appStoreBean.InstallAppVersionDTO, installedApps *repository.InstalledApps, dbTransaction *pg.Tx) error + // RollbackRelease will rollback to a previous deployment for the given installedAppVersionHistoryId; returns - valuesYamlStr, success, error RollbackRelease(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO, deploymentVersion int32, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, bool, error) - GetDeploymentHistory(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO) (*client.HelmAppDeploymentHistory, error) + // GetDeploymentHistory will return gRPC.HelmAppDeploymentHistory for the given installedAppDto.InstalledAppId + GetDeploymentHistory(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO) (*gRPC.HelmAppDeploymentHistory, error) + // GetDeploymentHistoryInfo will return openapi.HelmAppDeploymentManifestDetail for the given appStoreBean.InstallAppVersionDTO GetDeploymentHistoryInfo(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO, version int32) (*openapi.HelmAppDeploymentManifestDetail, error) - GetGitOpsRepoName(appName string, environmentName string) (string, error) + // GetAcdAppGitOpsRepoName will return the Git Repo used in the ACD app object + GetAcdAppGitOpsRepoName(appName string, environmentName string) (string, error) + // DeleteDeploymentApp will delete the app object from ACD DeleteDeploymentApp(ctx context.Context, appName string, environmentName string, installAppVersionRequest *appStoreBean.InstallAppVersionDTO) error - UpdateInstalledAppAndPipelineStatusForFailedDeploymentStatus(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, triggeredAt time.Time, err error) error SaveTimelineForACDHelmApps(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, status string, statusDetail string, statusTime time.Time, tx *pg.Tx) error UpdateAndSyncACDApps(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ChartGitAttribute *commonBean.ChartGitAttribute, isMonoRepoMigrationRequired bool, ctx context.Context, tx *pg.Tx) error + + // Deployment Status Services ---------------------- + + // UpdateInstalledAppAndPipelineStatusForFailedDeploymentStatus updates failed status in pipelineConfig.PipelineStatusTimeline table + UpdateInstalledAppAndPipelineStatusForFailedDeploymentStatus(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, triggeredAt time.Time, err error) error + + // Git Operation Services -------------------------- + + // ParseGitRepoErrorResponse will return noTargetFound (if git API returns 404 status) + ParseGitRepoErrorResponse(err error) (bool, error) + // GitOpsOperations performs git operations specific to helm app deployments + GitOpsOperations(manifestResponse *bean.AppStoreManifestResponse, installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*bean.AppStoreGitOpsResponse, error) + // GenerateManifest returns bean.AppStoreManifestResponse required in GitOps + GenerateManifest(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (manifestResponse *bean.AppStoreManifestResponse, err error) + // GenerateManifestAndPerformGitOperations is a wrapper function for both GenerateManifest and GitOpsOperations + GenerateManifestAndPerformGitOperations(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*bean.AppStoreGitOpsResponse, error) } type AppStoreDeploymentArgoCdServiceImpl struct { Logger *zap.SugaredLogger - appStoreDeploymentFullModeService appStoreDeploymentFullMode.AppStoreDeploymentFullModeService acdClient application2.ServiceClient + argoK8sClient argocdServer.ArgoK8sClient + aCDAuthConfig *util2.ACDAuthConfig chartGroupDeploymentRepository repository2.ChartGroupDeploymentRepository installedAppRepository repository.InstalledAppRepository installedAppRepositoryHistory repository.InstalledAppVersionHistoryRepository + argoUserService argo.ArgoUserService appStoreDeploymentCommonService appStoreDeploymentCommon.AppStoreDeploymentCommonService helmAppService client.HelmAppService appStatusService appStatus.AppStatusService @@ -70,25 +100,40 @@ type AppStoreDeploymentArgoCdServiceImpl struct { argoClientWrapperService argocdServer.ArgoClientWrapperService acdConfig *argocdServer.ACDConfig gitOperationService git.GitOperationService + gitOpsConfigReadService config.GitOpsConfigReadService + environmentRepository repository5.EnvironmentRepository } -func NewAppStoreDeploymentArgoCdServiceImpl(logger *zap.SugaredLogger, appStoreDeploymentFullModeService appStoreDeploymentFullMode.AppStoreDeploymentFullModeService, - acdClient application2.ServiceClient, chartGroupDeploymentRepository repository2.ChartGroupDeploymentRepository, - installedAppRepository repository.InstalledAppRepository, installedAppRepositoryHistory repository.InstalledAppVersionHistoryRepository, +func NewAppStoreDeploymentArgoCdServiceImpl( + logger *zap.SugaredLogger, + acdClient application2.ServiceClient, + argoK8sClient argocdServer.ArgoK8sClient, + aCDAuthConfig *util2.ACDAuthConfig, + chartGroupDeploymentRepository repository2.ChartGroupDeploymentRepository, + installedAppRepository repository.InstalledAppRepository, + installedAppRepositoryHistory repository.InstalledAppVersionHistoryRepository, + argoUserService argo.ArgoUserService, appStoreDeploymentCommonService appStoreDeploymentCommon.AppStoreDeploymentCommonService, - helmAppService client.HelmAppService, appStatusService appStatus.AppStatusService, - pipelineStatusTimelineService status.PipelineStatusTimelineService, userService user.UserService, + helmAppService client.HelmAppService, + appStatusService appStatus.AppStatusService, + pipelineStatusTimelineService status.PipelineStatusTimelineService, + userService user.UserService, pipelineStatusTimelineRepository pipelineConfig.PipelineStatusTimelineRepository, appStoreApplicationVersionRepository appStoreDiscoverRepository.AppStoreApplicationVersionRepository, - argoClientWrapperService argocdServer.ArgoClientWrapperService, acdConfig *argocdServer.ACDConfig, - gitOperationService git.GitOperationService) *AppStoreDeploymentArgoCdServiceImpl { + argoClientWrapperService argocdServer.ArgoClientWrapperService, + acdConfig *argocdServer.ACDConfig, + gitOperationService git.GitOperationService, + gitOpsConfigReadService config.GitOpsConfigReadService, + environmentRepository repository5.EnvironmentRepository) *AppStoreDeploymentArgoCdServiceImpl { return &AppStoreDeploymentArgoCdServiceImpl{ Logger: logger, - appStoreDeploymentFullModeService: appStoreDeploymentFullModeService, acdClient: acdClient, + argoK8sClient: argoK8sClient, + aCDAuthConfig: aCDAuthConfig, chartGroupDeploymentRepository: chartGroupDeploymentRepository, installedAppRepository: installedAppRepository, installedAppRepositoryHistory: installedAppRepositoryHistory, + argoUserService: argoUserService, appStoreDeploymentCommonService: appStoreDeploymentCommonService, helmAppService: helmAppService, appStatusService: appStatusService, @@ -99,6 +144,8 @@ func NewAppStoreDeploymentArgoCdServiceImpl(logger *zap.SugaredLogger, appStoreD argoClientWrapperService: argoClientWrapperService, acdConfig: acdConfig, gitOperationService: gitOperationService, + gitOpsConfigReadService: gitOpsConfigReadService, + environmentRepository: environmentRepository, } } @@ -175,31 +222,52 @@ func (impl AppStoreDeploymentArgoCdServiceImpl) SaveTimelineForACDHelmApps(insta } func (impl AppStoreDeploymentArgoCdServiceImpl) InstallApp(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, chartGitAttr *commonBean.ChartGitAttribute, ctx context.Context, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, error) { + ctx, cancel := context.WithTimeout(ctx, 1*time.Minute) + defer cancel() + //STEP 4: registerInArgo + err := impl.argoClientWrapperService.RegisterGitOpsRepoInArgo(ctx, chartGitAttr.RepoUrl) + if err != nil { + impl.Logger.Errorw("error in argo registry", "err", err) + return nil, err + } + //STEP 5: createInArgo + err = impl.createInArgo(chartGitAttr, *installAppVersionRequest.Environment, installAppVersionRequest.ACDAppName) + if err != nil { + impl.Logger.Errorw("error in create in argo", "err", err) + return nil, err + } + //STEP 6: Force Sync ACD - works like trigger deployment + //impl.SyncACD(installAppVersionRequest.ACDAppName, ctx) - installAppVersionRequest, err := impl.appStoreDeploymentFullModeService.AppStoreDeployOperationACD(installAppVersionRequest, chartGitAttr, ctx, tx) + //STEP 7: normal refresh ACD - update for step 6 to avoid delay + syncTime := time.Now() + err = impl.argoClientWrapperService.SyncArgoCDApplicationIfNeededAndRefresh(ctx, installAppVersionRequest.ACDAppName) if err != nil { - impl.Logger.Errorw(" error", "err", err) - return installAppVersionRequest, err + impl.Logger.Errorw("error in getting the argo application with normal refresh", "err", err) + return nil, err } + if !impl.acdConfig.ArgoCDAutoSyncEnabled { + timeline := &pipelineConfig.PipelineStatusTimeline{ + InstalledAppVersionHistoryId: installAppVersionRequest.InstalledAppVersionHistoryId, + Status: pipelineConfig.TIMELINE_STATUS_ARGOCD_SYNC_COMPLETED, + StatusDetail: "argocd sync completed.", + StatusTime: syncTime, + AuditLog: sql.AuditLog{ + CreatedBy: installAppVersionRequest.UserId, + CreatedOn: time.Now(), + UpdatedBy: installAppVersionRequest.UserId, + UpdatedOn: time.Now(), + }, + } + err = impl.pipelineStatusTimelineService.SaveTimeline(timeline, tx, true) + if err != nil { + impl.Logger.Errorw("error in creating timeline for argocd sync", "err", err, "timeline", timeline) + } + } + return installAppVersionRequest, nil } -//func (impl AppStoreDeploymentArgoCdServiceImpl) InstallApp(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ctx context.Context) (*appStoreBean.InstallAppVersionDTO, error) { -// //step 2 git operation pull push -// installAppVersionRequest, chartGitAttr, err := impl.appStoreDeploymentFullModeService.AppStoreDeployOperationGIT(installAppVersionRequest) -// if err != nil { -// impl.Logger.Errorw(" error", "err", err) -// return installAppVersionRequest, err -// } -// //step 3 acd operation register, sync -// installAppVersionRequest, err = impl.appStoreDeploymentFullModeService.AppStoreDeployOperationACD(installAppVersionRequest, chartGitAttr, ctx) -// if err != nil { -// impl.Logger.Errorw(" error", "err", err) -// return installAppVersionRequest, err -// } -// return installAppVersionRequest, nil -//} - func (impl AppStoreDeploymentArgoCdServiceImpl) DeleteInstalledApp(ctx context.Context, appName string, environmentName string, installAppVersionRequest *appStoreBean.InstallAppVersionDTO, installedApps *repository.InstalledApps, dbTransaction *pg.Tx) error { err := impl.appStatusService.DeleteWithAppIdEnvId(dbTransaction, installedApps.AppId, installedApps.EnvironmentId) @@ -229,7 +297,6 @@ func (impl AppStoreDeploymentArgoCdServiceImpl) DeleteInstalledApp(ctx context.C return nil } -// returns - valuesYamlStr, success, error func (impl AppStoreDeploymentArgoCdServiceImpl) RollbackRelease(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO, installedAppVersionHistoryId int32, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, bool, error) { //request version id for versionHistory, err := impl.installedAppRepositoryHistory.GetInstalledAppVersionHistory(int(installedAppVersionHistoryId)) @@ -292,7 +359,7 @@ func (impl AppStoreDeploymentArgoCdServiceImpl) RollbackRelease(ctx context.Cont } //If current version upgrade/degrade to another, update requirement dependencies if versionHistory.InstalledAppVersionId != activeInstalledAppVersion.Id { - err = impl.appStoreDeploymentFullModeService.UpdateRequirementYaml(installedApp, &installedAppVersion.AppStoreApplicationVersion) + err = impl.updateRequirementYamlInGit(installedApp, &installedAppVersion.AppStoreApplicationVersion) if err != nil { if errors.Is(err, errors.New(pipelineConfig.TIMELINE_STATUS_GIT_COMMIT_FAILED)) { impl.Logger.Errorw("error", "err", err) @@ -310,7 +377,7 @@ func (impl AppStoreDeploymentArgoCdServiceImpl) RollbackRelease(ctx context.Cont } } //Update Values config - installedApp, err = impl.appStoreDeploymentFullModeService.UpdateValuesYaml(installedApp, tx) + installedApp, err = impl.updateValuesYamlInGit(installedApp) if err != nil { impl.Logger.Errorw("error", "err", err) if errors.Is(err, errors.New(pipelineConfig.TIMELINE_STATUS_GIT_COMMIT_FAILED)) { @@ -362,40 +429,9 @@ func (impl AppStoreDeploymentArgoCdServiceImpl) RollbackRelease(ctx context.Cont return installedApp, true, nil } -func (impl AppStoreDeploymentArgoCdServiceImpl) deleteACD(acdAppName string, ctx context.Context, isNonCascade bool) error { - req := new(application.ApplicationDeleteRequest) - req.Name = &acdAppName - cascadeDelete := !isNonCascade - req.Cascade = &cascadeDelete - if ctx == nil { - impl.Logger.Errorw("err in delete ACD for AppStore, ctx is NULL", "acdAppName", acdAppName) - return fmt.Errorf("context is null") - } - if _, err := impl.acdClient.Delete(ctx, req); err != nil { - impl.Logger.Errorw("err in delete ACD for AppStore", "acdAppName", acdAppName, "err", err) - return err - } - return nil -} -func (impl AppStoreDeploymentArgoCdServiceImpl) getSourcesFromManifest(chartYaml string) ([]string, error) { - var b map[string]interface{} - var sources []string - err := json.Unmarshal([]byte(chartYaml), &b) - if err != nil { - impl.Logger.Errorw("error while unmarshal chart yaml", "error", err) - return sources, err - } - if b != nil && b["sources"] != nil { - slice := b["sources"].([]interface{}) - for _, item := range slice { - sources = append(sources, item.(string)) - } - } - return sources, nil -} -func (impl AppStoreDeploymentArgoCdServiceImpl) GetDeploymentHistory(ctx context.Context, installedAppDto *appStoreBean.InstallAppVersionDTO) (*client.HelmAppDeploymentHistory, error) { - result := &client.HelmAppDeploymentHistory{} - var history []*client.HelmAppDeploymentDetail +func (impl AppStoreDeploymentArgoCdServiceImpl) GetDeploymentHistory(ctx context.Context, installedAppDto *appStoreBean.InstallAppVersionDTO) (*gRPC.HelmAppDeploymentHistory, error) { + result := &gRPC.HelmAppDeploymentHistory{} + var history []*gRPC.HelmAppDeploymentDetail //TODO - response setup installedAppVersions, err := impl.installedAppRepository.GetInstalledAppVersionByInstalledAppIdMeta(installedAppDto.InstalledAppId) @@ -428,8 +464,8 @@ func (impl AppStoreDeploymentArgoCdServiceImpl) GetDeploymentHistory(ctx context if user != nil { emailId = user.EmailId } - history = append(history, &client.HelmAppDeploymentDetail{ - ChartMetadata: &client.ChartMetadata{ + history = append(history, &gRPC.HelmAppDeploymentDetail{ + ChartMetadata: &gRPC.ChartMetadata{ ChartName: installedAppVersionModel.AppStoreApplicationVersion.AppStore.Name, ChartVersion: installedAppVersionModel.AppStoreApplicationVersion.Version, Description: installedAppVersionModel.AppStoreApplicationVersion.Description, @@ -449,12 +485,13 @@ func (impl AppStoreDeploymentArgoCdServiceImpl) GetDeploymentHistory(ctx context } if len(history) == 0 { - history = make([]*client.HelmAppDeploymentDetail, 0) + history = make([]*gRPC.HelmAppDeploymentDetail, 0) } result.DeploymentHistory = history return result, err } +// TODO refactoring: use InstalledAppVersionHistoryId from appStoreBean.InstallAppVersionDTO instead of version int32 func (impl AppStoreDeploymentArgoCdServiceImpl) GetDeploymentHistoryInfo(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO, version int32) (*openapi.HelmAppDeploymentManifestDetail, error) { values := &openapi.HelmAppDeploymentManifestDetail{} _, span := otel.Tracer("orchestrator").Start(ctx, "installedAppRepositoryHistory.GetInstalledAppVersionHistory") @@ -494,63 +531,27 @@ func (impl AppStoreDeploymentArgoCdServiceImpl) GetDeploymentHistoryInfo(ctx con return values, err } -func (impl AppStoreDeploymentArgoCdServiceImpl) GetGitOpsRepoName(appName string, environmentName string) (string, error) { - return impl.appStoreDeploymentFullModeService.GetGitOpsRepoName(appName, environmentName) -} - -func (impl AppStoreDeploymentArgoCdServiceImpl) patchAcdApp(ctx context.Context, installAppVersionRequest *appStoreBean.InstallAppVersionDTO, chartGitAttr *commonBean.ChartGitAttribute) (*appStoreBean.InstallAppVersionDTO, error) { - ctx, cancel := context.WithTimeout(ctx, 1*time.Minute) - defer cancel() - //registerInArgo - err := impl.argoClientWrapperService.RegisterGitOpsRepoInArgo(ctx, chartGitAttr.RepoUrl) - if err != nil { - impl.Logger.Errorw("error in argo registry", "err", err) - return nil, err - } - // update acd app - patchReq := v1alpha1.Application{Spec: v1alpha1.ApplicationSpec{Source: &v1alpha1.ApplicationSource{Path: chartGitAttr.ChartLocation, RepoURL: chartGitAttr.RepoUrl, TargetRevision: "master"}}} - reqbyte, err := json.Marshal(patchReq) - if err != nil { - impl.Logger.Errorw("error in creating patch", "err", err) - } - reqString := string(reqbyte) - patchType := "merge" - _, err = impl.acdClient.Patch(ctx, &application.ApplicationPatchRequest{Patch: &reqString, Name: &installAppVersionRequest.ACDAppName, PatchType: &patchType}) - if err != nil { - impl.Logger.Errorw("error in creating argo app ", "name", installAppVersionRequest.ACDAppName, "patch", string(reqbyte), "err", err) - return nil, err - } - //impl.appStoreDeploymentFullModeService.SyncACD(installAppVersionRequest.ACDAppName, ctx) - return installAppVersionRequest, nil -} - -func (impl AppStoreDeploymentArgoCdServiceImpl) updateValuesYaml(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, error) { - - appStoreAppVersion, err := impl.appStoreApplicationVersionRepository.FindById(installAppVersionRequest.AppStoreVersion) - if err != nil { - impl.Logger.Errorw("fetching error", "err", err) - return nil, err - } - valuesString, err := impl.appStoreDeploymentCommonService.GetValuesString(appStoreAppVersion.Name, installAppVersionRequest.ValuesOverrideYaml) +func (impl AppStoreDeploymentArgoCdServiceImpl) GetAcdAppGitOpsRepoName(appName string, environmentName string) (string, error) { + gitOpsRepoName := "" + //this method should only call in case of argo-integration and gitops configured + acdToken, err := impl.argoUserService.GetLatestDevtronArgoCdUserToken() if err != nil { - impl.Logger.Errorw("error in building requirements config for helm app", "err", err) - return nil, err + impl.Logger.Errorw("error in getting acd token", "err", err) + return "", err } - valuesGitConfig, err := impl.appStoreDeploymentCommonService.GetGitCommitConfig(installAppVersionRequest, valuesString, appStoreBean.VALUES_YAML_FILE) + ctx := context.Background() + ctx = context.WithValue(ctx, "token", acdToken) + acdAppName := fmt.Sprintf("%s-%s", appName, environmentName) + acdApplication, err := impl.acdClient.Get(ctx, &application.ApplicationQuery{Name: &acdAppName}) if err != nil { - impl.Logger.Errorw("error in getting git config for helm app", "err", err) - return nil, err + impl.Logger.Errorw("no argo app exists", "acdAppName", acdAppName, "err", err) + return "", err } - gitHash, _, err := impl.gitOperationService.CommitValues(valuesGitConfig) - if err != nil { - impl.Logger.Errorw("error in git commit", "err", err) - _ = impl.SaveTimelineForACDHelmApps(installAppVersionRequest, pipelineConfig.TIMELINE_STATUS_GIT_COMMIT_FAILED, fmt.Sprintf("Git commit failed - %v", err), time.Now(), tx) - return nil, err + if acdApplication != nil { + gitOpsRepoUrl := acdApplication.Spec.Source.RepoURL + gitOpsRepoName = impl.gitOpsConfigReadService.GetGitOpsRepoNameFromUrl(gitOpsRepoUrl) } - _ = impl.SaveTimelineForACDHelmApps(installAppVersionRequest, pipelineConfig.TIMELINE_STATUS_GIT_COMMIT, "Git commit done successfully.", time.Now(), tx) - //update timeline status for git commit state - installAppVersionRequest.GitHash = gitHash - return installAppVersionRequest, nil + return gitOpsRepoName, nil } func (impl AppStoreDeploymentArgoCdServiceImpl) DeleteDeploymentApp(ctx context.Context, appName string, environmentName string, installAppVersionRequest *appStoreBean.InstallAppVersionDTO) error { @@ -579,3 +580,87 @@ func (impl AppStoreDeploymentArgoCdServiceImpl) DeleteDeploymentApp(ctx context. } return nil } + +func (impl AppStoreDeploymentArgoCdServiceImpl) deleteACD(acdAppName string, ctx context.Context, isNonCascade bool) error { + req := new(application.ApplicationDeleteRequest) + req.Name = &acdAppName + cascadeDelete := !isNonCascade + req.Cascade = &cascadeDelete + if ctx == nil { + impl.Logger.Errorw("err in delete ACD for AppStore, ctx is NULL", "acdAppName", acdAppName) + return fmt.Errorf("context is null") + } + if _, err := impl.acdClient.Delete(ctx, req); err != nil { + impl.Logger.Errorw("err in delete ACD for AppStore", "acdAppName", acdAppName, "err", err) + return err + } + return nil +} + +func (impl AppStoreDeploymentArgoCdServiceImpl) getSourcesFromManifest(chartYaml string) ([]string, error) { + var b map[string]interface{} + var sources []string + err := json.Unmarshal([]byte(chartYaml), &b) + if err != nil { + impl.Logger.Errorw("error while unmarshal chart yaml", "error", err) + return sources, err + } + if b != nil && b["sources"] != nil { + slice := b["sources"].([]interface{}) + for _, item := range slice { + sources = append(sources, item.(string)) + } + } + return sources, nil +} + +func (impl AppStoreDeploymentArgoCdServiceImpl) createInArgo(chartGitAttribute *commonBean.ChartGitAttribute, envModel repository5.Environment, argocdAppName string) error { + appNamespace := envModel.Namespace + if appNamespace == "" { + appNamespace = "default" + } + appreq := &argocdServer.AppTemplate{ + ApplicationName: argocdAppName, + Namespace: impl.aCDAuthConfig.ACDConfigMapNamespace, + TargetNamespace: appNamespace, + TargetServer: envModel.Cluster.ServerUrl, + Project: "default", + ValuesFile: fmt.Sprintf("values.yaml"), + RepoPath: chartGitAttribute.ChartLocation, + RepoUrl: chartGitAttribute.RepoUrl, + AutoSyncEnabled: impl.acdConfig.ArgoCDAutoSyncEnabled, + } + _, err := impl.argoK8sClient.CreateAcdApp(appreq, envModel.Cluster, argocdServer.ARGOCD_APPLICATION_TEMPLATE) + //create + if err != nil { + impl.Logger.Errorw("error in creating argo cd app ", "err", err) + return err + } + return nil +} + +func (impl AppStoreDeploymentArgoCdServiceImpl) patchAcdApp(ctx context.Context, installAppVersionRequest *appStoreBean.InstallAppVersionDTO, chartGitAttr *commonBean.ChartGitAttribute) (*appStoreBean.InstallAppVersionDTO, error) { + ctx, cancel := context.WithTimeout(ctx, 1*time.Minute) + defer cancel() + //registerInArgo + err := impl.argoClientWrapperService.RegisterGitOpsRepoInArgo(ctx, chartGitAttr.RepoUrl) + if err != nil { + impl.Logger.Errorw("error in argo registry", "err", err) + return nil, err + } + // update acd app + patchReq := v1alpha1.Application{Spec: v1alpha1.ApplicationSpec{Source: &v1alpha1.ApplicationSource{Path: chartGitAttr.ChartLocation, RepoURL: chartGitAttr.RepoUrl, TargetRevision: "master"}}} + reqbyte, err := json.Marshal(patchReq) + if err != nil { + impl.Logger.Errorw("error in creating patch", "err", err) + } + reqString := string(reqbyte) + patchType := "merge" + _, err = impl.acdClient.Patch(ctx, &application.ApplicationPatchRequest{Patch: &reqString, Name: &installAppVersionRequest.ACDAppName, PatchType: &patchType}) + if err != nil { + impl.Logger.Errorw("error in creating argo app ", "name", installAppVersionRequest.ACDAppName, "patch", string(reqbyte), "err", err) + return nil, err + } + //impl.appStoreDeploymentFullModeService.SyncACD(installAppVersionRequest.ACDAppName, ctx) + return installAppVersionRequest, nil +} diff --git a/pkg/appStore/deployment/tool/AppStoreDeploymentGitOpsService.go b/pkg/appStore/deployment/tool/AppStoreDeploymentGitOpsService.go new file mode 100644 index 00000000000..4370d3e205e --- /dev/null +++ b/pkg/appStore/deployment/tool/AppStoreDeploymentGitOpsService.go @@ -0,0 +1,270 @@ +package appStoreDeploymentTool + +import ( + "errors" + "fmt" + bean2 "github.com/devtron-labs/devtron/api/bean" + "github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig" + "github.com/devtron-labs/devtron/internal/util" + appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" + "github.com/devtron-labs/devtron/pkg/appStore/deployment/adapter" + "github.com/devtron-labs/devtron/pkg/appStore/deployment/tool/bean" + appStoreDiscoverRepository "github.com/devtron-labs/devtron/pkg/appStore/discover/repository" + commonBean "github.com/devtron-labs/devtron/pkg/deployment/gitOps/common/bean" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git" + "github.com/google/go-github/github" + "github.com/microsoft/azure-devops-go-api/azuredevops" + "github.com/xanzy/go-gitlab" + "net/http" + "regexp" +) + +func (impl AppStoreDeploymentArgoCdServiceImpl) ParseGitRepoErrorResponse(err error) (bool, error) { + //update values yaml in chart + noTargetFound := false + if err != nil { + if errorResponse, ok := err.(*github.ErrorResponse); ok && errorResponse.Response.StatusCode == http.StatusNotFound { + impl.Logger.Errorw("no content found while updating git repo on github, do auto fix", "error", err) + noTargetFound = true + } + if errorResponse, ok := err.(azuredevops.WrappedError); ok && *errorResponse.StatusCode == http.StatusNotFound { + impl.Logger.Errorw("no content found while updating git repo on azure, do auto fix", "error", err) + noTargetFound = true + } + if errorResponse, ok := err.(*azuredevops.WrappedError); ok && *errorResponse.StatusCode == http.StatusNotFound { + impl.Logger.Errorw("no content found while updating git repo on azure, do auto fix", "error", err) + noTargetFound = true + } + if errorResponse, ok := err.(*gitlab.ErrorResponse); ok && errorResponse.Response.StatusCode == http.StatusNotFound { + impl.Logger.Errorw("no content found while updating git repo gitlab, do auto fix", "error", err) + noTargetFound = true + } + if err.Error() == git.BITBUCKET_REPO_NOT_FOUND_ERROR { + impl.Logger.Errorw("no content found while updating git repo bitbucket, do auto fix", "error", err) + noTargetFound = true + } + } + return noTargetFound, err +} + +func (impl AppStoreDeploymentArgoCdServiceImpl) GenerateManifestAndPerformGitOperations(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*bean.AppStoreGitOpsResponse, error) { + appStoreGitOpsResponse := &bean.AppStoreGitOpsResponse{} + manifest, err := impl.GenerateManifest(installAppVersionRequest) + if err != nil { + impl.Logger.Errorw("error in performing manifest and git operations", "err", err) + return nil, err + } + gitOpsResponse, err := impl.GitOpsOperations(manifest, installAppVersionRequest) + if err != nil { + impl.Logger.Errorw("error in performing gitops operation", "err", err) + return nil, err + } + installAppVersionRequest.GitHash = gitOpsResponse.GitHash + appStoreGitOpsResponse.ChartGitAttribute = gitOpsResponse.ChartGitAttribute + return appStoreGitOpsResponse, nil +} + +// GitOpsOperations handles all git operations for Helm App +func (impl AppStoreDeploymentArgoCdServiceImpl) GitOpsOperations(manifestResponse *bean.AppStoreManifestResponse, installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*bean.AppStoreGitOpsResponse, error) { + appStoreGitOpsResponse := &bean.AppStoreGitOpsResponse{} + chartGitAttribute, isNew, githash, err := impl.createGitOpsRepoAndPushChart(installAppVersionRequest, manifestResponse.ChartResponse.BuiltChartPath, manifestResponse.RequirementsConfig, manifestResponse.ValuesConfig) + if err != nil { + impl.Logger.Errorw("Error in pushing chart to git", "err", err) + return appStoreGitOpsResponse, err + } + space := regexp.MustCompile(`\s+`) + appStoreName := space.ReplaceAllString(installAppVersionRequest.AppName, "-") + + // Checking this is the first time chart has been pushed , if yes requirements.yaml has been already pushed with chart as there was sync-delay with github api. + // step-2 commit dependencies and values in git + if !isNew { + githash, err = impl.gitOperationService.CommitRequirementsAndValues(appStoreName, chartGitAttribute.RepoUrl, manifestResponse.RequirementsConfig, manifestResponse.ValuesConfig) + if err != nil { + impl.Logger.Errorw("error in committing config to git", "err", err) + return appStoreGitOpsResponse, err + } + } + appStoreGitOpsResponse.ChartGitAttribute = chartGitAttribute + appStoreGitOpsResponse.GitHash = githash + return appStoreGitOpsResponse, nil +} + +func (impl AppStoreDeploymentArgoCdServiceImpl) GenerateManifest(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (manifestResponse *bean.AppStoreManifestResponse, err error) { + + manifestResponse = &bean.AppStoreManifestResponse{} + + ChartCreateResponse, err := impl.createChartProxyAndGetPath(installAppVersionRequest) + if err != nil { + impl.Logger.Errorw("Error in building chart while generating manifest", "err", err) + return manifestResponse, err + } + valuesConfig, dependencyConfig, err := impl.getValuesAndRequirementForGitConfig(installAppVersionRequest) + if err != nil { + impl.Logger.Errorw("error in fetching values and requirements.yaml config while generating manifest", "err", err) + return manifestResponse, err + } + + manifestResponse.ChartResponse = ChartCreateResponse + manifestResponse.ValuesConfig = valuesConfig + manifestResponse.RequirementsConfig = dependencyConfig + + return manifestResponse, nil +} + +// createGitOpsRepoAndPushChart is a wrapper for creating GitOps repo and pushing chart to created repo +func (impl AppStoreDeploymentArgoCdServiceImpl) createGitOpsRepoAndPushChart(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, builtChartPath string, requirementsConfig *git.ChartConfig, valuesConfig *git.ChartConfig) (*commonBean.ChartGitAttribute, bool, string, error) { + repoURL, isNew, err := impl.createGitOpsRepo(installAppVersionRequest) + if err != nil { + impl.Logger.Errorw("Error in creating gitops repo for ", "appName", installAppVersionRequest.AppName, "err", err) + return nil, false, "", err + } + pushChartToGitRequest := adapter.ParseChartGitPushRequest(installAppVersionRequest, repoURL, builtChartPath) + chartGitAttribute, commitHash, err := impl.gitOperationService.PushChartToGitOpsRepoForHelmApp(pushChartToGitRequest, requirementsConfig, valuesConfig) + if err != nil { + impl.Logger.Errorw("error in pushing chart to git", "err", err) + return nil, false, "", err + } + return chartGitAttribute, isNew, commitHash, err +} + +// createGitOpsRepo creates a gitOps repo with readme +func (impl AppStoreDeploymentArgoCdServiceImpl) createGitOpsRepo(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (string, bool, error) { + if len(installAppVersionRequest.GitOpsRepoName) == 0 { + //here gitops repo will be the app name, to breaking the mono repo structure + gitOpsRepoName := impl.gitOpsConfigReadService.GetGitOpsRepoName(installAppVersionRequest.AppName) + installAppVersionRequest.GitOpsRepoName = gitOpsRepoName + } + bitbucketMetadata, err := impl.gitOpsConfigReadService.GetBitbucketMetadata() + if err != nil { + impl.Logger.Errorw("error in getting bitbucket metadata", "err", err) + return "", false, err + } + //getting user name & emailId for commit author data + gitRepoRequest := &bean2.GitOpsConfigDto{ + GitRepoName: installAppVersionRequest.GitOpsRepoName, + Description: "helm chart for " + installAppVersionRequest.GitOpsRepoName, + BitBucketWorkspaceId: bitbucketMetadata.BitBucketWorkspaceId, + BitBucketProjectKey: bitbucketMetadata.BitBucketProjectKey, + } + repoUrl, isNew, err := impl.gitOperationService.CreateRepository(gitRepoRequest, installAppVersionRequest.UserId) + if err != nil { + impl.Logger.Errorw("error in creating git project", "name", installAppVersionRequest.GitOpsRepoName, "err", err) + return "", false, err + } + return repoUrl, isNew, err +} + +func (impl AppStoreDeploymentArgoCdServiceImpl) updateValuesYamlInGit(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*appStoreBean.InstallAppVersionDTO, error) { + valuesString, err := impl.appStoreDeploymentCommonService.GetValuesString(installAppVersionRequest.AppStoreName, installAppVersionRequest.ValuesOverrideYaml) + if err != nil { + impl.Logger.Errorw("error in getting values string", "err", err) + return nil, err + } + + valuesGitConfig, err := impl.getGitCommitConfig(installAppVersionRequest, valuesString, appStoreBean.VALUES_YAML_FILE) + if err != nil { + impl.Logger.Errorw("error in getting git commit config", "err", err) + } + + commitHash, _, err := impl.gitOperationService.CommitValues(valuesGitConfig) + if err != nil { + impl.Logger.Errorw("error in git commit", "err", err) + return installAppVersionRequest, errors.New(pipelineConfig.TIMELINE_STATUS_GIT_COMMIT_FAILED) + } + //update timeline status for git commit state + installAppVersionRequest.GitHash = commitHash + return installAppVersionRequest, nil +} + +func (impl AppStoreDeploymentArgoCdServiceImpl) updateRequirementYamlInGit(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, appStoreAppVersion *appStoreDiscoverRepository.AppStoreApplicationVersion) error { + requirementsString, err := impl.appStoreDeploymentCommonService.GetRequirementsString(appStoreAppVersion.Id) + if err != nil { + impl.Logger.Errorw("error in getting requirements string", "err", err) + return err + } + + requirementsGitConfig, err := impl.getGitCommitConfig(installAppVersionRequest, requirementsString, appStoreBean.REQUIREMENTS_YAML_FILE) + if err != nil { + impl.Logger.Errorw("error in getting git commit config", "err", err) + return err + } + + _, _, err = impl.gitOperationService.CommitValues(requirementsGitConfig) + if err != nil { + impl.Logger.Errorw("error in values commit", "err", err) + return errors.New(pipelineConfig.TIMELINE_STATUS_GIT_COMMIT_FAILED) + } + + return nil +} + +// createChartProxyAndGetPath parse chart in local directory and returns path of local dir and values.yaml +func (impl AppStoreDeploymentArgoCdServiceImpl) createChartProxyAndGetPath(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*util.ChartCreateResponse, error) { + chartCreateRequest := adapter.ParseChartCreateRequest(installAppVersionRequest.AppName) + chartCreateResponse, err := impl.appStoreDeploymentCommonService.CreateChartProxyAndGetPath(chartCreateRequest) + if err != nil { + impl.Logger.Errorw("Error in building chart proxy", "err", err) + return chartCreateResponse, err + } + return chartCreateResponse, nil + +} + +// getGitCommitConfig will return util.ChartConfig (git commit config) for GitOps +func (impl AppStoreDeploymentArgoCdServiceImpl) getGitCommitConfig(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, fileString string, filename string) (*git.ChartConfig, error) { + appStoreAppVersion, err := impl.appStoreApplicationVersionRepository.FindById(installAppVersionRequest.AppStoreVersion) + if err != nil { + impl.Logger.Errorw("fetching error", "err", err) + return nil, err + } + environment, err := impl.environmentRepository.FindById(installAppVersionRequest.EnvironmentId) + if err != nil { + impl.Logger.Errorw("fetching error", "err", err) + return nil, err + } + + argocdAppName := installAppVersionRequest.AppName + "-" + environment.Name + gitOpsRepoName := impl.gitOpsConfigReadService.GetGitOpsRepoName(installAppVersionRequest.AppName) + userEmailId, userName := impl.gitOpsConfigReadService.GetUserEmailIdAndNameForGitOpsCommit(installAppVersionRequest.UserId) + YamlConfig := &git.ChartConfig{ + FileName: filename, + FileContent: fileString, + ChartName: installAppVersionRequest.AppName, + ChartLocation: argocdAppName, + ChartRepoName: gitOpsRepoName, + ReleaseMessage: fmt.Sprintf("release-%d-env-%d ", appStoreAppVersion.Id, environment.Id), + UserEmailId: userEmailId, + UserName: userName, + } + return YamlConfig, nil +} + +// getValuesAndRequirementForGitConfig will return chart values(*util.ChartConfig) and requirements(*util.ChartConfig) for git commit +func (impl AppStoreDeploymentArgoCdServiceImpl) getValuesAndRequirementForGitConfig(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*git.ChartConfig, *git.ChartConfig, error) { + appStoreAppVersion, err := impl.appStoreApplicationVersionRepository.FindById(installAppVersionRequest.AppStoreVersion) + if err != nil { + impl.Logger.Errorw("fetching error", "err", err) + return nil, nil, err + } + values, err := impl.appStoreDeploymentCommonService.GetValuesString(appStoreAppVersion.AppStore.Name, installAppVersionRequest.ValuesOverrideYaml) + if err != nil { + impl.Logger.Errorw("error in getting values fot installedAppVersionRequest", "err", err) + return nil, nil, err + } + dependency, err := impl.appStoreDeploymentCommonService.GetRequirementsString(installAppVersionRequest.AppStoreVersion) + if err != nil { + impl.Logger.Errorw("error in getting dependency array fot installedAppVersionRequest", "err", err) + return nil, nil, err + } + valuesConfig, err := impl.getGitCommitConfig(installAppVersionRequest, values, appStoreBean.VALUES_YAML_FILE) + if err != nil { + impl.Logger.Errorw("error in creating values config for git", "err", err) + return nil, nil, err + } + RequirementConfig, err := impl.getGitCommitConfig(installAppVersionRequest, dependency, appStoreBean.REQUIREMENTS_YAML_FILE) + if err != nil { + impl.Logger.Errorw("error in creating dependency config for git", "err", err) + return nil, nil, err + } + return valuesConfig, RequirementConfig, nil +} diff --git a/pkg/appStore/deployment/tool/AppStoreDeploymentHelmService.go b/pkg/appStore/deployment/tool/AppStoreDeploymentHelmService.go index e57416218ca..4f4d28c7a8c 100644 --- a/pkg/appStore/deployment/tool/AppStoreDeploymentHelmService.go +++ b/pkg/appStore/deployment/tool/AppStoreDeploymentHelmService.go @@ -3,16 +3,17 @@ package appStoreDeploymentTool import ( "context" "errors" + bean2 "github.com/devtron-labs/devtron/api/helm-app/bean" + "github.com/devtron-labs/devtron/api/helm-app/gRPC" + client "github.com/devtron-labs/devtron/api/helm-app/service" repository2 "github.com/devtron-labs/devtron/internal/sql/repository/dockerRegistry" + "github.com/devtron-labs/devtron/pkg/appStore/deployment/tool/bean" commonBean "github.com/devtron-labs/devtron/pkg/deployment/gitOps/common/bean" - "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git" "time" - client "github.com/devtron-labs/devtron/api/helm-app" openapi "github.com/devtron-labs/devtron/api/helm-app/openapiClient" "github.com/devtron-labs/devtron/internal/util" appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean" - appStoreDeploymentCommon "github.com/devtron-labs/devtron/pkg/appStore/deployment/common" "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" appStoreDiscoverRepository "github.com/devtron-labs/devtron/pkg/appStore/discover/repository" "github.com/go-pg/pg" @@ -25,7 +26,7 @@ type AppStoreDeploymentHelmService interface { InstallApp(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, chartGitAttr *commonBean.ChartGitAttribute, ctx context.Context, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, error) DeleteInstalledApp(ctx context.Context, appName string, environmentName string, installAppVersionRequest *appStoreBean.InstallAppVersionDTO, installedApps *repository.InstalledApps, dbTransaction *pg.Tx) error RollbackRelease(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO, deploymentVersion int32, tx *pg.Tx) (*appStoreBean.InstallAppVersionDTO, bool, error) - GetDeploymentHistory(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO) (*client.HelmAppDeploymentHistory, error) + GetDeploymentHistory(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO) (*gRPC.HelmAppDeploymentHistory, error) GetDeploymentHistoryInfo(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO, version int32) (*openapi.HelmAppDeploymentManifestDetail, error) DeleteDeploymentApp(ctx context.Context, appName string, environmentName string, installAppVersionRequest *appStoreBean.InstallAppVersionDTO) error UpdateChartInfo(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ChartGitAttribute *commonBean.ChartGitAttribute, installedAppVersionHistoryId int, ctx context.Context) error @@ -35,28 +36,24 @@ type AppStoreDeploymentHelmServiceImpl struct { Logger *zap.SugaredLogger helmAppService client.HelmAppService appStoreApplicationVersionRepository appStoreDiscoverRepository.AppStoreApplicationVersionRepository - helmAppClient client.HelmAppClient - installedAppRepository repository.InstalledAppRepository - appStoreDeploymentCommonService appStoreDeploymentCommon.AppStoreDeploymentCommonService - OCIRegistryConfigRepository repository2.OCIRegistryConfigRepository - gitOperationService git.GitOperationService + // TODO fix me next + helmAppClient gRPC.HelmAppClient // TODO refactoring: use HelmAppService instead + installedAppRepository repository.InstalledAppRepository + OCIRegistryConfigRepository repository2.OCIRegistryConfigRepository } func NewAppStoreDeploymentHelmServiceImpl(logger *zap.SugaredLogger, helmAppService client.HelmAppService, appStoreApplicationVersionRepository appStoreDiscoverRepository.AppStoreApplicationVersionRepository, - helmAppClient client.HelmAppClient, - installedAppRepository repository.InstalledAppRepository, appStoreDeploymentCommonService appStoreDeploymentCommon.AppStoreDeploymentCommonService, - OCIRegistryConfigRepository repository2.OCIRegistryConfigRepository, - gitOperationService git.GitOperationService) *AppStoreDeploymentHelmServiceImpl { + helmAppClient gRPC.HelmAppClient, + installedAppRepository repository.InstalledAppRepository, + OCIRegistryConfigRepository repository2.OCIRegistryConfigRepository) *AppStoreDeploymentHelmServiceImpl { return &AppStoreDeploymentHelmServiceImpl{ Logger: logger, helmAppService: helmAppService, appStoreApplicationVersionRepository: appStoreApplicationVersionRepository, helmAppClient: helmAppClient, installedAppRepository: installedAppRepository, - appStoreDeploymentCommonService: appStoreDeploymentCommonService, OCIRegistryConfigRepository: OCIRegistryConfigRepository, - gitOperationService: gitOperationService, } } @@ -77,8 +74,8 @@ func (impl AppStoreDeploymentHelmServiceImpl) InstallApp(installAppVersionReques return installAppVersionRequest, err } var IsOCIRepo bool - var registryCredential *client.RegistryCredential - var chartRepository *client.ChartRepository + var registryCredential *gRPC.RegistryCredential + var chartRepository *gRPC.ChartRepository dockerRegistryId := appStoreAppVersion.AppStore.DockerArtifactStoreId if dockerRegistryId != "" { ociRegistryConfigs, err := impl.OCIRegistryConfigRepository.FindByDockerRegistryId(dockerRegistryId) @@ -94,7 +91,7 @@ func (impl AppStoreDeploymentHelmServiceImpl) InstallApp(installAppVersionReques } } IsOCIRepo = true - registryCredential = &client.RegistryCredential{ + registryCredential = &gRPC.RegistryCredential{ RegistryUrl: appStoreAppVersion.AppStore.DockerArtifactStore.RegistryURL, Username: appStoreAppVersion.AppStore.DockerArtifactStore.Username, Password: appStoreAppVersion.AppStore.DockerArtifactStore.Password, @@ -106,19 +103,19 @@ func (impl AppStoreDeploymentHelmServiceImpl) InstallApp(installAppVersionReques IsPublic: ociRegistryConfig.IsPublic, } } else { - chartRepository = &client.ChartRepository{ + chartRepository = &gRPC.ChartRepository{ Name: appStoreAppVersion.AppStore.ChartRepo.Name, Url: appStoreAppVersion.AppStore.ChartRepo.Url, Username: appStoreAppVersion.AppStore.ChartRepo.UserName, Password: appStoreAppVersion.AppStore.ChartRepo.Password, } } - installReleaseRequest := &client.InstallReleaseRequest{ + installReleaseRequest := &gRPC.InstallReleaseRequest{ ChartName: appStoreAppVersion.Name, ChartVersion: appStoreAppVersion.Version, ValuesYaml: installAppVersionRequest.ValuesOverrideYaml, ChartRepository: chartRepository, - ReleaseIdentifier: &client.ReleaseIdentifier{ + ReleaseIdentifier: &gRPC.ReleaseIdentifier{ ReleaseNamespace: installAppVersionRequest.Namespace, ReleaseName: installAppVersionRequest.AppName, }, @@ -198,23 +195,13 @@ func (impl AppStoreDeploymentHelmServiceImpl) RollbackRelease(ctx context.Contex return installedApp, success, nil } -func (impl *AppStoreDeploymentHelmServiceImpl) GetDeploymentHistory(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO) (*client.HelmAppDeploymentHistory, error) { - helmAppIdeltifier := &client.AppIdentifier{ +func (impl *AppStoreDeploymentHelmServiceImpl) GetDeploymentHistory(ctx context.Context, installedApp *appStoreBean.InstallAppVersionDTO) (*gRPC.HelmAppDeploymentHistory, error) { + helmAppIdentifier := &client.AppIdentifier{ ClusterId: installedApp.ClusterId, Namespace: installedApp.Namespace, ReleaseName: installedApp.AppName, } - config, err := impl.helmAppService.GetClusterConf(helmAppIdeltifier.ClusterId) - if err != nil { - impl.Logger.Errorw("error in fetching cluster detail", "err", err) - return nil, err - } - req := &client.AppDetailRequest{ - ClusterConfig: config, - Namespace: helmAppIdeltifier.Namespace, - ReleaseName: helmAppIdeltifier.ReleaseName, - } - history, err := impl.helmAppClient.GetDeploymentHistory(ctx, req) + history, err := impl.helmAppService.GetDeploymentHistory(ctx, helmAppIdentifier) return history, err } @@ -230,8 +217,8 @@ func (impl *AppStoreDeploymentHelmServiceImpl) GetDeploymentHistoryInfo(ctx cont return nil, err } - req := &client.DeploymentDetailRequest{ - ReleaseIdentifier: &client.ReleaseIdentifier{ + req := &gRPC.DeploymentDetailRequest{ + ReleaseIdentifier: &gRPC.ReleaseIdentifier{ ClusterConfig: config, ReleaseName: helmAppIdeltifier.ReleaseName, ReleaseNamespace: helmAppIdeltifier.Namespace, @@ -254,36 +241,7 @@ func (impl *AppStoreDeploymentHelmServiceImpl) GetDeploymentHistoryInfo(ctx cont return response, nil } -func (impl *AppStoreDeploymentHelmServiceImpl) GetGitOpsRepoName(appName string, environmentName string) (string, error) { - return "", errors.New("method GetGitOpsRepoName not implemented") -} - -func (impl *AppStoreDeploymentHelmServiceImpl) UpdateValuesDependencies(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) error { - appStoreAppVersion, err := impl.appStoreApplicationVersionRepository.FindById(installAppVersionRequest.AppStoreVersion) - if err != nil { - impl.Logger.Errorw("fetching error", "err", err) - return err - } - valuesString, err := impl.appStoreDeploymentCommonService.GetValuesString(appStoreAppVersion.Name, installAppVersionRequest.ValuesOverrideYaml) - if err != nil { - impl.Logger.Errorw("error in building requirements config for helm app", "err", err) - return err - } - valuesGitConfig, err := impl.appStoreDeploymentCommonService.GetGitCommitConfig(installAppVersionRequest, valuesString, appStoreBean.VALUES_YAML_FILE) - if err != nil { - impl.Logger.Errorw("error in getting git config for helm app", "err", err) - return err - } - _, _, err = impl.gitOperationService.CommitValues(valuesGitConfig) - if err != nil { - impl.Logger.Errorw("error in committing config to git for helm app", "err", err) - return err - } - return nil -} - func (impl *AppStoreDeploymentHelmServiceImpl) updateApplicationWithChartInfo(ctx context.Context, installedAppId int, appStoreApplicationVersionId int, valuesOverrideYaml string, installAppVersionHistoryId int) error { - installedApp, err := impl.installedAppRepository.GetInstalledApp(installedAppId) if err != nil { impl.Logger.Errorw("error in getting in installedApp", "installedAppId", installedAppId, "err", err) @@ -295,8 +253,8 @@ func (impl *AppStoreDeploymentHelmServiceImpl) updateApplicationWithChartInfo(ct return err } var IsOCIRepo bool - var registryCredential *client.RegistryCredential - var chartRepository *client.ChartRepository + var registryCredential *gRPC.RegistryCredential + var chartRepository *gRPC.ChartRepository dockerRegistryId := appStoreApplicationVersion.AppStore.DockerArtifactStoreId if dockerRegistryId != "" { ociRegistryConfigs, err := impl.OCIRegistryConfigRepository.FindByDockerRegistryId(dockerRegistryId) @@ -312,7 +270,7 @@ func (impl *AppStoreDeploymentHelmServiceImpl) updateApplicationWithChartInfo(ct } } IsOCIRepo = true - registryCredential = &client.RegistryCredential{ + registryCredential = &gRPC.RegistryCredential{ RegistryUrl: appStoreApplicationVersion.AppStore.DockerArtifactStore.RegistryURL, Username: appStoreApplicationVersion.AppStore.DockerArtifactStore.Username, Password: appStoreApplicationVersion.AppStore.DockerArtifactStore.Password, @@ -324,7 +282,7 @@ func (impl *AppStoreDeploymentHelmServiceImpl) updateApplicationWithChartInfo(ct IsPublic: ociRegistryConfig.IsPublic, } } else { - chartRepository = &client.ChartRepository{ + chartRepository = &gRPC.ChartRepository{ Name: appStoreApplicationVersion.AppStore.ChartRepo.Name, Url: appStoreApplicationVersion.AppStore.ChartRepo.Url, Username: appStoreApplicationVersion.AppStore.ChartRepo.UserName, @@ -332,10 +290,10 @@ func (impl *AppStoreDeploymentHelmServiceImpl) updateApplicationWithChartInfo(ct } } - updateReleaseRequest := &client.UpdateApplicationWithChartInfoRequestDto{ - InstallReleaseRequest: &client.InstallReleaseRequest{ + updateReleaseRequest := &bean2.UpdateApplicationWithChartInfoRequestDto{ + InstallReleaseRequest: &gRPC.InstallReleaseRequest{ ValuesYaml: valuesOverrideYaml, - ReleaseIdentifier: &client.ReleaseIdentifier{ + ReleaseIdentifier: &gRPC.ReleaseIdentifier{ ReleaseNamespace: installedApp.Environment.Namespace, ReleaseName: installedApp.App.AppName, }, @@ -346,7 +304,7 @@ func (impl *AppStoreDeploymentHelmServiceImpl) updateApplicationWithChartInfo(ct IsOCIRepo: IsOCIRepo, InstallAppVersionHistoryId: int32(installAppVersionHistoryId), }, - SourceAppType: client.SOURCE_HELM_APP, + SourceAppType: bean2.SOURCE_HELM_APP, } res, err := impl.helmAppService.UpdateApplicationWithChartInfo(ctx, installedApp.Environment.ClusterId, updateReleaseRequest) if err != nil { @@ -358,16 +316,21 @@ func (impl *AppStoreDeploymentHelmServiceImpl) updateApplicationWithChartInfo(ct } return nil } + +func (impl *AppStoreDeploymentHelmServiceImpl) GetAcdAppGitOpsRepoName(appName string, environmentName string) (string, error) { + return "", errors.New("method GetGitOpsRepoName not implemented") +} + func (impl *AppStoreDeploymentHelmServiceImpl) DeleteDeploymentApp(ctx context.Context, appName string, environmentName string, installAppVersionRequest *appStoreBean.InstallAppVersionDTO) error { - return nil + return errors.New("this is not implemented") } func (impl *AppStoreDeploymentHelmServiceImpl) SaveTimelineForACDHelmApps(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, status string, statusDetail string, statusTime time.Time, tx *pg.Tx) error { - return nil + return errors.New("this is not implemented") } func (impl *AppStoreDeploymentHelmServiceImpl) UpdateInstalledAppAndPipelineStatusForFailedDeploymentStatus(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, triggeredAt time.Time, err error) error { - return nil + return errors.New("this is not implemented") } // TODO: Need to refactor this,refer below reason @@ -376,3 +339,23 @@ func (impl *AppStoreDeploymentHelmServiceImpl) UpdateInstalledAppAndPipelineStat func (impl *AppStoreDeploymentHelmServiceImpl) UpdateAndSyncACDApps(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, ChartGitAttribute *commonBean.ChartGitAttribute, isMonoRepoMigrationRequired bool, ctx context.Context, tx *pg.Tx) error { return errors.New("this is not implemented") } + +func (impl *AppStoreDeploymentHelmServiceImpl) UpdateValuesDependencies(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) error { + return errors.New("this is not implemented") +} + +func (impl *AppStoreDeploymentHelmServiceImpl) ParseGitRepoErrorResponse(err error) (bool, error) { + return false, errors.New("this is not implemented") +} + +func (impl *AppStoreDeploymentHelmServiceImpl) GitOpsOperations(manifestResponse *bean.AppStoreManifestResponse, installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*bean.AppStoreGitOpsResponse, error) { + return nil, errors.New("this is not implemented") +} + +func (impl *AppStoreDeploymentHelmServiceImpl) GenerateManifestAndPerformGitOperations(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*bean.AppStoreGitOpsResponse, error) { + return nil, errors.New("this is not implemented") +} + +func (impl *AppStoreDeploymentHelmServiceImpl) GenerateManifest(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (manifestResponse *bean.AppStoreManifestResponse, err error) { + return nil, errors.New("this is not implemented") +} diff --git a/pkg/appStore/deployment/tool/bean/bean.go b/pkg/appStore/deployment/tool/bean/bean.go new file mode 100644 index 00000000000..bcd00a6c6bc --- /dev/null +++ b/pkg/appStore/deployment/tool/bean/bean.go @@ -0,0 +1,18 @@ +package bean + +import ( + "github.com/devtron-labs/devtron/internal/util" + commonBean "github.com/devtron-labs/devtron/pkg/deployment/gitOps/common/bean" + "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git" +) + +type AppStoreManifestResponse struct { + ChartResponse *util.ChartCreateResponse + ValuesConfig *git.ChartConfig + RequirementsConfig *git.ChartConfig +} + +type AppStoreGitOpsResponse struct { + ChartGitAttribute *commonBean.ChartGitAttribute + GitHash string +} diff --git a/pkg/appStore/util/util.go b/pkg/appStore/util/util.go index 7367f847028..a340742d3c1 100644 --- a/pkg/appStore/util/util.go +++ b/pkg/appStore/util/util.go @@ -1,6 +1,8 @@ package util -import "os" +import ( + "os" +) func MoveFileToDestination(filePath, destinationPath string) error { err := os.Rename(filePath, destinationPath) @@ -9,3 +11,16 @@ func MoveFileToDestination(filePath, destinationPath string) error { } return nil } + +func CreateFileAtFilePathAndWrite(filePath, fileContent string) (string, error) { + file, err := os.Create(filePath) + defer file.Close() + if err != nil { + return filePath, err + } + _, err = file.Write([]byte(fileContent)) + if err != nil { + return filePath, err + } + return filePath, err +} diff --git a/pkg/bean/app.go b/pkg/bean/app.go index 275b051f76c..8ae77b8afd9 100644 --- a/pkg/bean/app.go +++ b/pkg/bean/app.go @@ -100,6 +100,8 @@ type CiPipeline struct { ParentCiPipeline int `json:"parentCiPipeline"` ParentAppId int `json:"parentAppId"` AppId int `json:"appId"` + AppName string `json:"appName,omitempty"` + AppType helper.AppType `json:"appType,omitempty"` ExternalCiConfig ExternalCiConfig `json:"externalCiConfig"` CiMaterial []*CiMaterial `json:"ciMaterial,omitempty" validate:"dive,min=1"` Name string `json:"name,omitempty" validate:"name-component,max=100"` //name suffix of corresponding pipeline. required, unique, validation corresponding to gocd pipelineName will be applicable diff --git a/pkg/bulkAction/BulkUpdateService.go b/pkg/bulkAction/BulkUpdateService.go index 754cd140672..b4fba18f209 100644 --- a/pkg/bulkAction/BulkUpdateService.go +++ b/pkg/bulkAction/BulkUpdateService.go @@ -9,8 +9,8 @@ import ( pubsub "github.com/devtron-labs/common-lib/pubsub-lib" "github.com/devtron-labs/common-lib/pubsub-lib/model" "github.com/devtron-labs/devtron/api/bean" - client "github.com/devtron-labs/devtron/api/helm-app" openapi "github.com/devtron-labs/devtron/api/helm-app/openapiClient" + client "github.com/devtron-labs/devtron/api/helm-app/service" "github.com/devtron-labs/devtron/client/argocdServer/application" "github.com/devtron-labs/devtron/internal/sql/models" "github.com/devtron-labs/devtron/internal/sql/repository/app" diff --git a/pkg/chart/mocks/ChartService.go b/pkg/chart/mocks/ChartService.go index 3cf2e392d64..b68ade434e4 100644 --- a/pkg/chart/mocks/ChartService.go +++ b/pkg/chart/mocks/ChartService.go @@ -680,7 +680,6 @@ func (_m *ChartService) ReadChartMetaDataForLocation(chartDir string, fileName s return r0, r1 } - // UpdateAppOverride provides a mock function with given fields: ctx, templateRequest func (_m *ChartService) UpdateAppOverride(ctx context.Context, templateRequest *chart.TemplateRequest) (*chart.TemplateRequest, error) { ret := _m.Called(ctx, templateRequest) diff --git a/pkg/chartRepo/ChartRepositoryService.go b/pkg/chartRepo/ChartRepositoryService.go index e529c28e6da..b722dee023a 100644 --- a/pkg/chartRepo/ChartRepositoryService.go +++ b/pkg/chartRepo/ChartRepositoryService.go @@ -199,6 +199,14 @@ func (impl *ChartRepositoryServiceImpl) CreateChartRepo(request *ChartRepoDto) ( secretData := impl.CreateSecretDataForHelmChart(request, isPrivateChart) _, err = impl.K8sUtil.CreateSecret(impl.aCDAuthConfig.ACDConfigMapNamespace, nil, chartRepo.Name, "", client, secretLabel, secretData) if err != nil { + // TODO refactoring: Implement the below error handling if secret name already exists + //if statusError, ok := err.(*k8sErrors.StatusError); ok && + // statusError != nil && + // statusError.Status().Code == http.StatusConflict && + // statusError.ErrStatus.Reason == metav1.StatusReasonAlreadyExists { + // impl.logger.Errorw("secret already exists", "err", statusError.Error()) + // return nil, fmt.Errorf(statusError.Error()) + //} continue } if err == nil { diff --git a/pkg/clusterTerminalAccess/UserTerminalAccessService.go b/pkg/clusterTerminalAccess/UserTerminalAccessService.go index 90c7760e939..9e876eb7dc3 100644 --- a/pkg/clusterTerminalAccess/UserTerminalAccessService.go +++ b/pkg/clusterTerminalAccess/UserTerminalAccessService.go @@ -7,7 +7,7 @@ import ( "fmt" "github.com/caarlos0/env/v6" k8s2 "github.com/devtron-labs/common-lib/utils/k8s" - client "github.com/devtron-labs/devtron/api/helm-app" + client "github.com/devtron-labs/devtron/api/helm-app/service" "github.com/devtron-labs/devtron/internal/sql/models" "github.com/devtron-labs/devtron/internal/sql/repository" utils1 "github.com/devtron-labs/devtron/pkg/clusterTerminalAccess/clusterTerminalUtils" diff --git a/pkg/deployment/gitOps/git/GitOperationService.go b/pkg/deployment/gitOps/git/GitOperationService.go index 70c88e3f826..f020c89fc06 100644 --- a/pkg/deployment/gitOps/git/GitOperationService.go +++ b/pkg/deployment/gitOps/git/GitOperationService.go @@ -4,31 +4,32 @@ import ( "fmt" bean2 "github.com/devtron-labs/devtron/api/bean" "github.com/devtron-labs/devtron/internal/util" + util2 "github.com/devtron-labs/devtron/pkg/appStore/util" commonBean "github.com/devtron-labs/devtron/pkg/deployment/gitOps/common/bean" "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config" "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git/bean" dirCopy "github.com/otiai10/copy" "go.uber.org/zap" - "k8s.io/helm/pkg/proto/hapi/chart" "os" "path/filepath" "regexp" - "sigs.k8s.io/yaml" "time" ) type GitOperationService interface { CreateGitRepositoryForApp(gitOpsRepoName, baseTemplateName, version string, userId int32) (chartGitAttribute *commonBean.ChartGitAttribute, err error) - PushChartToGitRepo(gitOpsRepoName, referenceTemplate, version, - tempReferenceTemplateDir string, repoUrl string, userId int32) (err error) CreateReadmeInGitRepo(gitOpsRepoName string, userId int32) error - CreateChartProxy(chartMetaData *chart.Metadata, refChartLocation string, envName string, - chartProxyReq *bean.ChartProxyReqDto) (string, *commonBean.ChartGitAttribute, error) GitPull(clonedDir string, repoUrl string, appStoreName string) error CommitValues(chartGitAttr *ChartConfig) (commitHash string, commitTime time.Time, err error) + CommitRequirementsAndValues(appStoreName, repoUrl string, requirementsConfig *ChartConfig, + valuesConfig *ChartConfig) (gitHash string, err error) CommitAndPushAllChanges(clonedDir, commitMsg, userName, userEmailId string) (commitHash string, err error) + PushChartToGitRepo(gitOpsRepoName, referenceTemplate, version, + tempReferenceTemplateDir string, repoUrl string, userId int32) (err error) + PushChartToGitOpsRepoForHelmApp(PushChartToGitRequest *bean.PushChartToGitRequestDTO, + requirementsConfig *ChartConfig, valuesConfig *ChartConfig) (*commonBean.ChartGitAttribute, string, error) CreateRepository(dto *bean2.GitOpsConfigDto, userId int32) (string, bool, error) GetRepoUrlByRepoName(repoName string) (string, error) @@ -182,47 +183,6 @@ func (impl *GitOperationServiceImpl) CreateReadmeInGitRepo(gitOpsRepoName string return nil } -func (impl *GitOperationServiceImpl) CreateChartProxy(chartMetaData *chart.Metadata, refChartLocation string, envName string, - chartProxyReq *bean.ChartProxyReqDto) (string, *commonBean.ChartGitAttribute, error) { - chartMetaData.ApiVersion = "v2" // ensure always v2 - dir := impl.chartTemplateService.GetDir() - chartDir := filepath.Join(util.CHART_WORKING_DIR_PATH, dir) - impl.logger.Debugw("chart dir ", "chart", chartMetaData.Name, "dir", chartDir) - err := os.MkdirAll(chartDir, os.ModePerm) //hack for concurrency handling - if err != nil { - impl.logger.Errorw("err in creating dir", "dir", chartDir, "err", err) - return "", nil, err - } - defer impl.chartTemplateService.CleanDir(chartDir) - err = dirCopy.Copy(refChartLocation, chartDir) - - if err != nil { - impl.logger.Errorw("error in copying chart for app", "app", chartMetaData.Name, "error", err) - return "", nil, err - } - archivePath, valuesYaml, err := impl.chartTemplateService.PackageChart(chartDir, chartMetaData) - if err != nil { - impl.logger.Errorw("error in creating archive", "err", err) - return "", nil, err - } - - chartGitAttr, err := impl.createAndPushToGitChartProxy(chartMetaData.Name, chartDir, envName, chartProxyReq) - if err != nil { - impl.logger.Errorw("error in pushing chart to git ", "path", archivePath, "err", err) - return "", nil, err - } - if valuesYaml == "" { - valuesYaml = "{}" - } else { - valuesYamlByte, err := yaml.YAMLToJSON([]byte(valuesYaml)) - if err != nil { - return "", nil, err - } - valuesYaml = string(valuesYamlByte) - } - return valuesYaml, chartGitAttr, nil -} - func (impl *GitOperationServiceImpl) createAndPushToGitChartProxy(appStoreName, tmpChartLocation string, envName string, chartProxyReq *bean.ChartProxyReqDto) (chartGitAttribute *commonBean.ChartGitAttribute, err error) { //baseTemplateName replace whitespace @@ -306,7 +266,10 @@ func (impl *GitOperationServiceImpl) createAndPushToGitChartProxy(appStoreName, } func (impl *GitOperationServiceImpl) GitPull(clonedDir string, repoUrl string, appStoreName string) error { - err := impl.gitFactory.GitService.Pull(clonedDir) //TODO check for local repo exists before clone + //TODO refactoring: remove invalid param appStoreName + //TODO check for local repo exists before clone + //TODO verify remote has repoUrl; or delete and clone + err := impl.gitFactory.GitService.Pull(clonedDir) if err != nil { impl.logger.Errorw("error in pulling git", "clonedDir", clonedDir, "err", err) _, err := impl.gitFactory.GitService.Clone(repoUrl, appStoreName) @@ -380,6 +343,99 @@ func (impl *GitOperationServiceImpl) GetRepoUrlByRepoName(repoName string) (stri return repoUrl, nil } +// TODO refactoring: Make a common method for both PushChartToGitRepo and PushChartToGitOpsRepoForHelmApp +// PushChartToGitOpsRepoForHelmApp pushes built chart to GitOps repo (Specific implementation for Helm Apps) +func (impl *GitOperationServiceImpl) PushChartToGitOpsRepoForHelmApp(PushChartToGitRequest *bean.PushChartToGitRequestDTO, requirementsConfig *ChartConfig, valuesConfig *ChartConfig) (*commonBean.ChartGitAttribute, string, error) { + space := regexp.MustCompile(`\s+`) + appStoreName := space.ReplaceAllString(PushChartToGitRequest.ChartAppStoreName, "-") + chartDir := fmt.Sprintf("%s-%s", PushChartToGitRequest.AppName, impl.chartTemplateService.GetDir()) + clonedDir := impl.gitFactory.GitService.GetCloneDirectory(chartDir) + if _, err := os.Stat(clonedDir); os.IsNotExist(err) { + clonedDir, err = impl.gitFactory.GitService.Clone(PushChartToGitRequest.RepoURL, chartDir) + if err != nil { + impl.logger.Errorw("error in cloning repo", "url", PushChartToGitRequest.RepoURL, "err", err) + return nil, "", err + } + } else { + err = impl.GitPull(clonedDir, PushChartToGitRequest.RepoURL, appStoreName) + if err != nil { + return nil, "", err + } + } + acdAppName := fmt.Sprintf("%s-%s", PushChartToGitRequest.AppName, PushChartToGitRequest.EnvName) + dir := filepath.Join(clonedDir, acdAppName) + err := os.MkdirAll(dir, os.ModePerm) + if err != nil { + impl.logger.Errorw("error in making dir", "err", err) + return nil, "", err + } + err = dirCopy.Copy(PushChartToGitRequest.TempChartRefDir, dir) + if err != nil { + impl.logger.Errorw("error copying dir", "err", err) + return nil, "", err + } + err = impl.addConfigFileToChart(requirementsConfig, dir, clonedDir) + if err != nil { + impl.logger.Errorw("error in adding requirements.yaml to chart", "err", err, "appName", PushChartToGitRequest.AppName) + return nil, "", err + } + err = impl.addConfigFileToChart(valuesConfig, dir, clonedDir) + if err != nil { + impl.logger.Errorw("error in adding values.yaml to chart", "err", err, "appName", PushChartToGitRequest.AppName) + return nil, "", err + } + userEmailId, userName := impl.gitOpsConfigReadService.GetUserEmailIdAndNameForGitOpsCommit(PushChartToGitRequest.UserId) + commit, err := impl.gitFactory.GitService.CommitAndPushAllChanges(clonedDir, "first commit", userName, userEmailId) + if err != nil { + impl.logger.Errorw("error in pushing git", "err", err) + impl.logger.Warn("re-trying, taking pull and then push again") + err = impl.GitPull(clonedDir, PushChartToGitRequest.RepoURL, acdAppName) + if err != nil { + impl.logger.Errorw("error in git pull", "err", err, "appName", acdAppName) + return nil, "", err + } + err = dirCopy.Copy(PushChartToGitRequest.TempChartRefDir, dir) + if err != nil { + impl.logger.Errorw("error copying dir", "err", err) + return nil, "", err + } + commit, err = impl.gitFactory.GitService.CommitAndPushAllChanges(clonedDir, "first commit", userName, userEmailId) + if err != nil { + impl.logger.Errorw("error in pushing git", "err", err) + return nil, "", err + } + } + impl.logger.Debugw("template committed", "url", PushChartToGitRequest.RepoURL, "commit", commit) + defer impl.chartTemplateService.CleanDir(clonedDir) + return &commonBean.ChartGitAttribute{RepoUrl: PushChartToGitRequest.RepoURL, ChartLocation: acdAppName}, commit, err +} + +func (impl *GitOperationServiceImpl) CommitRequirementsAndValues(appStoreName, repoUrl string, requirementsConfig *ChartConfig, valuesConfig *ChartConfig) (gitHash string, err error) { + clonedDir := GIT_WORKING_DIR + appStoreName + _, _, err = impl.CommitValues(requirementsConfig) + if err != nil { + impl.logger.Errorw("error in committing dependency config to git", "err", err) + return gitHash, err + } + err = impl.GitPull(clonedDir, repoUrl, appStoreName) + if err != nil { + impl.logger.Errorw("error in git pull", "err", err) + return gitHash, err + } + + gitHash, _, err = impl.CommitValues(valuesConfig) + if err != nil { + impl.logger.Errorw("error in committing values config to git", "err", err) + return gitHash, err + } + err = impl.GitPull(clonedDir, repoUrl, appStoreName) + if err != nil { + impl.logger.Errorw("error in git pull", "err", err) + return gitHash, err + } + return gitHash, nil +} + func (impl *GitOperationServiceImpl) GetClonedDir(chartDir, repoUrl string) (string, error) { clonedDir := impl.gitFactory.GitService.GetCloneDirectory(chartDir) if _, err := os.Stat(clonedDir); os.IsNotExist(err) { @@ -399,3 +455,20 @@ func (impl *GitOperationServiceImpl) CloneInDir(repoUrl, chartDir string) (strin } return clonedDir, nil } + +// addConfigFileToChart will override requirements.yaml or values.yaml file in chart +func (impl *GitOperationServiceImpl) addConfigFileToChart(config *ChartConfig, destinationDir string, clonedDir string) error { + filePath := filepath.Join(clonedDir, config.FileName) + filePath, err := util2.CreateFileAtFilePathAndWrite(filePath, config.FileContent) + if err != nil { + impl.logger.Errorw("error in creating yaml file", "err", err) + return err + } + destinationFilePath := filepath.Join(destinationDir, config.FileName) + err = util2.MoveFileToDestination(filePath, destinationFilePath) + if err != nil { + impl.logger.Errorw("error in moving file from source to destination", "err", err) + return err + } + return nil +} diff --git a/pkg/deployment/gitOps/git/bean/bean.go b/pkg/deployment/gitOps/git/bean/bean.go index c806e552516..ec951be5c85 100644 --- a/pkg/deployment/gitOps/git/bean/bean.go +++ b/pkg/deployment/gitOps/git/bean/bean.go @@ -19,3 +19,12 @@ type GitConfig struct { BitbucketWorkspaceId string BitbucketProjectKey string } + +type PushChartToGitRequestDTO struct { + AppName string + EnvName string + ChartAppStoreName string + RepoURL string + TempChartRefDir string + UserId int32 +} diff --git a/pkg/generateManifest/DeployementTemplateService.go b/pkg/generateManifest/DeployementTemplateService.go index 82b8a909a8e..4e4db124711 100644 --- a/pkg/generateManifest/DeployementTemplateService.go +++ b/pkg/generateManifest/DeployementTemplateService.go @@ -4,7 +4,9 @@ import ( "context" "fmt" "github.com/devtron-labs/common-lib/utils/k8s" - client "github.com/devtron-labs/devtron/api/helm-app" + "github.com/devtron-labs/devtron/api/helm-app/bean" + "github.com/devtron-labs/devtron/api/helm-app/gRPC" + client "github.com/devtron-labs/devtron/api/helm-app/service" openapi2 "github.com/devtron-labs/devtron/api/openapi/openapiClient" "github.com/devtron-labs/devtron/internal/sql/repository" appRepository "github.com/devtron-labs/devtron/internal/sql/repository/app" @@ -46,14 +48,14 @@ const ( Manifest RequestDataMode = 2 ) -var ChartRepository = &client.ChartRepository{ +var ChartRepository = &gRPC.ChartRepository{ Name: "repo", Url: "http://localhost:8080/", Username: "admin", Password: "password", } -var ReleaseIdentifier = &client.ReleaseIdentifier{ +var ReleaseIdentifier = &gRPC.ReleaseIdentifier{ ReleaseNamespace: "devtron-demo", ReleaseName: "release-name", } @@ -79,7 +81,7 @@ type DeploymentTemplateServiceImpl struct { chartRepository chartRepoRepository.ChartRepository chartTemplateServiceImpl util.ChartTemplateService K8sUtil *k8s.K8sServiceImpl - helmAppClient client.HelmAppClient + helmAppClient gRPC.HelmAppClient propertiesConfigService pipeline.PropertiesConfigService deploymentTemplateHistoryService history.DeploymentTemplateHistoryService environmentRepository repository3.EnvironmentRepository @@ -95,7 +97,7 @@ func NewDeploymentTemplateServiceImpl(Logger *zap.SugaredLogger, chartService ch helmAppService client.HelmAppService, chartRepository chartRepoRepository.ChartRepository, chartTemplateServiceImpl util.ChartTemplateService, - helmAppClient client.HelmAppClient, + helmAppClient gRPC.HelmAppClient, K8sUtil *k8s.K8sServiceImpl, propertiesConfigService pipeline.PropertiesConfigService, deploymentTemplateHistoryService history.DeploymentTemplateHistoryService, @@ -340,18 +342,18 @@ func (impl DeploymentTemplateServiceImpl) GenerateManifest(ctx context.Context, impl.Logger.Errorw("exception caught in getting k8sServerVersion", "err", err) return nil, err } - installReleaseRequest := &client.InstallReleaseRequest{ + installReleaseRequest := &gRPC.InstallReleaseRequest{ ChartName: template, ChartVersion: version, ValuesYaml: valuesYaml, K8SVersion: k8sServerVersion.String(), ChartRepository: ChartRepository, ReleaseIdentifier: ReleaseIdentifier, - ChartContent: &client.ChartContent{ + ChartContent: &gRPC.ChartContent{ Content: chartBytes, }, } - config, err := impl.helmAppService.GetClusterConf(client.DEFAULT_CLUSTER_ID) + config, err := impl.helmAppService.GetClusterConf(bean.DEFAULT_CLUSTER_ID) if err != nil { impl.Logger.Errorw("error in fetching cluster detail", "clusterId", 1, "err", err) return nil, err diff --git a/pkg/generateManifest/DeployementTemplateService_test.go b/pkg/generateManifest/DeployementTemplateService_test.go index d2aac53148f..b3254cbcc40 100644 --- a/pkg/generateManifest/DeployementTemplateService_test.go +++ b/pkg/generateManifest/DeployementTemplateService_test.go @@ -6,7 +6,7 @@ import ( client2 "github.com/devtron-labs/authenticator/client" "github.com/devtron-labs/common-lib/utils/k8s" "github.com/devtron-labs/devtron/api/bean" - client "github.com/devtron-labs/devtron/api/helm-app" + client "github.com/devtron-labs/devtron/api/helm-app/gRPC" mocks4 "github.com/devtron-labs/devtron/api/helm-app/mocks" "github.com/devtron-labs/devtron/internal/sql/repository" mocks3 "github.com/devtron-labs/devtron/internal/sql/repository/mocks" diff --git a/pkg/k8s/K8sCommonService.go b/pkg/k8s/K8sCommonService.go index 1549b71e6e2..813d64b7a37 100644 --- a/pkg/k8s/K8sCommonService.go +++ b/pkg/k8s/K8sCommonService.go @@ -7,7 +7,7 @@ import ( "github.com/devtron-labs/common-lib/utils/k8s" k8sCommonBean "github.com/devtron-labs/common-lib/utils/k8s/commonBean" "github.com/devtron-labs/devtron/api/bean" - "github.com/devtron-labs/devtron/api/helm-app" + "github.com/devtron-labs/devtron/api/helm-app/service" util2 "github.com/devtron-labs/devtron/internal/util" "github.com/devtron-labs/devtron/pkg/cluster" bean3 "github.com/devtron-labs/devtron/pkg/k8s/application/bean" @@ -166,7 +166,7 @@ func (impl *K8sCommonServiceImpl) FilterK8sResources(ctx context.Context, resour req := ResourceRequestBean{ AppId: appId, ClusterId: appDetail.ClusterId, - AppIdentifier: &client.AppIdentifier{ + AppIdentifier: &service.AppIdentifier{ ClusterId: appDetail.ClusterId, }, K8sRequest: &k8s.K8sRequestBean{ diff --git a/pkg/k8s/application/k8sApplicationService.go b/pkg/k8s/application/k8sApplicationService.go index a8811a35f08..084245cdad4 100644 --- a/pkg/k8s/application/k8sApplicationService.go +++ b/pkg/k8s/application/k8sApplicationService.go @@ -5,6 +5,8 @@ import ( "encoding/json" "errors" "fmt" + "github.com/devtron-labs/devtron/api/helm-app/gRPC" + client "github.com/devtron-labs/devtron/api/helm-app/service" "io" "net/http" "strconv" @@ -18,7 +20,6 @@ import ( yamlUtil "github.com/devtron-labs/common-lib/utils/yaml" "github.com/devtron-labs/devtron/api/connector" - client "github.com/devtron-labs/devtron/api/helm-app" "github.com/devtron-labs/devtron/api/helm-app/openapiClient" "github.com/devtron-labs/devtron/pkg/auth/authorisation/casbin" "github.com/devtron-labs/devtron/pkg/cluster" @@ -390,7 +391,7 @@ func (impl *K8sApplicationServiceImpl) ValidateResourceRequest(ctx context.Conte return impl.validateContainerNameIfReqd(valid, request, app), nil } -func (impl *K8sApplicationServiceImpl) validateContainerNameIfReqd(valid bool, request *k8s2.K8sRequestBean, app *client.AppDetail) bool { +func (impl *K8sApplicationServiceImpl) validateContainerNameIfReqd(valid bool, request *k8s2.K8sRequestBean, app *gRPC.AppDetail) bool { if !valid { requestContainerName := request.PodLogsRequest.ContainerName podName := request.ResourceIdentifier.Name diff --git a/pkg/k8s/application/k8sApplicationService_test.go b/pkg/k8s/application/k8sApplicationService_test.go index 12ce800ddf2..6b68e2cbaea 100644 --- a/pkg/k8s/application/k8sApplicationService_test.go +++ b/pkg/k8s/application/k8sApplicationService_test.go @@ -5,7 +5,7 @@ import ( "encoding/json" "fmt" k8s2 "github.com/devtron-labs/common-lib/utils/k8s" - client "github.com/devtron-labs/devtron/api/helm-app" + client "github.com/devtron-labs/devtron/api/helm-app/service" "github.com/devtron-labs/devtron/pkg/cluster" "github.com/devtron-labs/devtron/pkg/cluster/repository" "github.com/devtron-labs/devtron/pkg/k8s" diff --git a/pkg/k8s/application/mocks/K8sApplicationService.go b/pkg/k8s/application/mocks/K8sApplicationService.go index 638606d14d6..434f01ffd42 100644 --- a/pkg/k8s/application/mocks/K8sApplicationService.go +++ b/pkg/k8s/application/mocks/K8sApplicationService.go @@ -5,7 +5,7 @@ package mocks import ( "github.com/devtron-labs/common-lib/utils/k8s" bean "github.com/devtron-labs/devtron/api/bean" - client "github.com/devtron-labs/devtron/api/helm-app" + client "github.com/devtron-labs/devtron/api/helm-app/service" k8s2 "github.com/devtron-labs/devtron/pkg/k8s" bean2 "github.com/devtron-labs/devtron/pkg/k8s/application/bean" diff --git a/pkg/k8s/bean.go b/pkg/k8s/bean.go index 61edcd2f570..bdd072a34ce 100644 --- a/pkg/k8s/bean.go +++ b/pkg/k8s/bean.go @@ -2,7 +2,7 @@ package k8s import ( "github.com/devtron-labs/common-lib/utils/k8s" - client "github.com/devtron-labs/devtron/api/helm-app" + client "github.com/devtron-labs/devtron/api/helm-app/service" "github.com/devtron-labs/devtron/pkg/k8s/application/bean" ) diff --git a/pkg/kubernetesResourceAuditLogs/kubernetesResourceHistoryService.go b/pkg/kubernetesResourceAuditLogs/kubernetesResourceHistoryService.go index 10ab04489d5..859a5f258b6 100644 --- a/pkg/kubernetesResourceAuditLogs/kubernetesResourceHistoryService.go +++ b/pkg/kubernetesResourceAuditLogs/kubernetesResourceHistoryService.go @@ -3,7 +3,7 @@ package kubernetesResourceAuditLogs import ( "github.com/argoproj/argo-cd/v2/pkg/apiclient/application" "github.com/devtron-labs/common-lib/utils/k8s" - client "github.com/devtron-labs/devtron/api/helm-app" + client "github.com/devtron-labs/devtron/api/helm-app/service" "github.com/devtron-labs/devtron/internal/sql/repository/app" repository2 "github.com/devtron-labs/devtron/pkg/cluster/repository" "github.com/devtron-labs/devtron/pkg/kubernetesResourceAuditLogs/repository" diff --git a/pkg/module/ModuleCronService.go b/pkg/module/ModuleCronService.go index bd295644638..3f62ca58c69 100644 --- a/pkg/module/ModuleCronService.go +++ b/pkg/module/ModuleCronService.go @@ -21,7 +21,8 @@ import ( "context" "encoding/json" "fmt" - client "github.com/devtron-labs/devtron/api/helm-app" + "github.com/devtron-labs/devtron/api/helm-app/gRPC" + client "github.com/devtron-labs/devtron/api/helm-app/service" moduleRepo "github.com/devtron-labs/devtron/pkg/module/repo" moduleDataStore "github.com/devtron-labs/devtron/pkg/module/store" serverBean "github.com/devtron-labs/devtron/pkg/server/bean" @@ -159,7 +160,7 @@ func (impl *ModuleCronServiceImpl) handleModuleStatus(moduleNameInput string) { } -func (impl *ModuleCronServiceImpl) saveModuleResourcesStatus(moduleId int, appDetail *client.AppDetail) error { +func (impl *ModuleCronServiceImpl) saveModuleResourcesStatus(moduleId int, appDetail *gRPC.AppDetail) error { impl.logger.Infow("updating module resources status", "moduleId", moduleId) if appDetail == nil || appDetail.ResourceTreeResponse == nil { return nil @@ -234,7 +235,7 @@ func (impl *ModuleCronServiceImpl) saveModuleResourcesStatus(moduleId int, appDe return nil } -func (impl *ModuleCronServiceImpl) buildResourceTreeFilter(moduleName string) (*client.ResourceTreeFilter, error) { +func (impl *ModuleCronServiceImpl) buildResourceTreeFilter(moduleName string) (*gRPC.ResourceTreeFilter, error) { moduleMetaData, err := impl.moduleServiceHelper.GetModuleMetadata(moduleName) if err != nil { impl.logger.Errorw("Error in getting module metadata", "moduleName", moduleName, "err", err) @@ -255,13 +256,13 @@ func (impl *ModuleCronServiceImpl) buildResourceTreeFilter(moduleName string) (* return nil, err } - var resourceTreeFilter *client.ResourceTreeFilter + var resourceTreeFilter *gRPC.ResourceTreeFilter // handle global filter globalFilter := resourceFilterIfaceValue.GlobalFilter if globalFilter != nil { - resourceTreeFilter = &client.ResourceTreeFilter{ - GlobalFilter: &client.ResourceIdentifier{ + resourceTreeFilter = &gRPC.ResourceTreeFilter{ + GlobalFilter: &gRPC.ResourceIdentifier{ Labels: globalFilter.Labels, }, } @@ -269,21 +270,21 @@ func (impl *ModuleCronServiceImpl) buildResourceTreeFilter(moduleName string) (* } // otherwise handle gvk level - var resourceFilters []*client.ResourceFilter + var resourceFilters []*gRPC.ResourceFilter for _, gvkLevelFilters := range resourceFilterIfaceValue.GvkLevelFilters { gvk := gvkLevelFilters.Gvk - resourceFilters = append(resourceFilters, &client.ResourceFilter{ - Gvk: &client.Gvk{ + resourceFilters = append(resourceFilters, &gRPC.ResourceFilter{ + Gvk: &gRPC.Gvk{ Group: gvk.Group, Version: gvk.Version, Kind: gvk.Kind, }, - ResourceIdentifier: &client.ResourceIdentifier{ + ResourceIdentifier: &gRPC.ResourceIdentifier{ Labels: gvkLevelFilters.ResourceIdentifier.Labels, }, }) } - resourceTreeFilter = &client.ResourceTreeFilter{ + resourceTreeFilter = &gRPC.ResourceTreeFilter{ ResourceFilters: resourceFilters, } return resourceTreeFilter, nil diff --git a/pkg/module/ModuleService.go b/pkg/module/ModuleService.go index 9e677148fcc..297888cfeac 100644 --- a/pkg/module/ModuleService.go +++ b/pkg/module/ModuleService.go @@ -21,7 +21,8 @@ import ( "context" "errors" "github.com/caarlos0/env/v6" - client "github.com/devtron-labs/devtron/api/helm-app" + "github.com/devtron-labs/devtron/api/helm-app/gRPC" + client "github.com/devtron-labs/devtron/api/helm-app/service" "github.com/devtron-labs/devtron/internal/sql/repository/security" moduleRepo "github.com/devtron-labs/devtron/pkg/module/repo" moduleUtil "github.com/devtron-labs/devtron/pkg/module/util" @@ -395,7 +396,7 @@ func (impl ModuleServiceImpl) HandleModuleAction(userId int32, moduleName string // HELM_OPERATION Starts devtronHelmAppIdentifier := impl.helmAppService.GetDevtronHelmAppIdentifier() - chartRepository := &client.ChartRepository{ + chartRepository := &gRPC.ChartRepository{ Name: impl.serverEnvConfig.DevtronHelmRepoName, Url: impl.serverEnvConfig.DevtronHelmRepoUrl, } diff --git a/pkg/pipeline/AppDeploymentTypeChangeManager.go b/pkg/pipeline/AppDeploymentTypeChangeManager.go index 5f340c755f4..fcc6e1563c8 100644 --- a/pkg/pipeline/AppDeploymentTypeChangeManager.go +++ b/pkg/pipeline/AppDeploymentTypeChangeManager.go @@ -21,7 +21,7 @@ import ( "context" "fmt" "github.com/argoproj/argo-cd/v2/pkg/apiclient/application" - "github.com/devtron-labs/devtron/api/helm-app" + "github.com/devtron-labs/devtron/api/helm-app/service" application2 "github.com/devtron-labs/devtron/client/argocdServer/application" "github.com/devtron-labs/devtron/internal/sql/repository/app" "github.com/devtron-labs/devtron/internal/sql/repository/appStatus" @@ -62,7 +62,7 @@ type AppDeploymentTypeChangeManagerImpl struct { workflowDagExecutor WorkflowDagExecutor appService app2.AppService appStatusRepository appStatus.AppStatusRepository - helmAppService client.HelmAppService + helmAppService service.HelmAppService application application2.ServiceClient appArtifactManager AppArtifactManager @@ -77,7 +77,7 @@ func NewAppDeploymentTypeChangeManagerImpl( workflowDagExecutor WorkflowDagExecutor, appService app2.AppService, appStatusRepository appStatus.AppStatusRepository, - helmAppService client.HelmAppService, + helmAppService service.HelmAppService, application application2.ServiceClient, appArtifactManager AppArtifactManager, cdPipelineConfigService CdPipelineConfigService, @@ -628,7 +628,7 @@ func (impl *AppDeploymentTypeChangeManagerImpl) FetchDeletedApp(ctx context.Cont deploymentAppName := fmt.Sprintf("%s-%s", pipeline.App.AppName, pipeline.Environment.Name) var err error if pipeline.DeploymentAppType == string(bean.ArgoCd) { - appIdentifier := &client.AppIdentifier{ + appIdentifier := &service.AppIdentifier{ ClusterId: pipeline.Environment.ClusterId, ReleaseName: pipeline.DeploymentAppName, Namespace: pipeline.Environment.Namespace, @@ -720,7 +720,7 @@ func (impl *AppDeploymentTypeChangeManagerImpl) deleteHelmApp(ctx context.Contex } // create app identifier - appIdentifier := &client.AppIdentifier{ + appIdentifier := &service.AppIdentifier{ ClusterId: pipeline.Environment.ClusterId, ReleaseName: pipeline.DeploymentAppName, Namespace: pipeline.Environment.Namespace, diff --git a/pkg/pipeline/CdHandler.go b/pkg/pipeline/CdHandler.go index bd912ff04b2..0e4ea796fc2 100644 --- a/pkg/pipeline/CdHandler.go +++ b/pkg/pipeline/CdHandler.go @@ -22,6 +22,7 @@ import ( "context" "errors" "fmt" + client "github.com/devtron-labs/devtron/api/helm-app/service" "os" "path/filepath" "strconv" @@ -34,7 +35,6 @@ import ( pubub "github.com/devtron-labs/common-lib/pubsub-lib" "github.com/devtron-labs/common-lib/utils/k8s" "github.com/devtron-labs/devtron/api/bean" - client "github.com/devtron-labs/devtron/api/helm-app" "github.com/devtron-labs/devtron/client/argocdServer" "github.com/devtron-labs/devtron/client/argocdServer/application" client2 "github.com/devtron-labs/devtron/client/events" diff --git a/pkg/pipeline/DeploymentPipelineConfigService.go b/pkg/pipeline/DeploymentPipelineConfigService.go index 016dc73d06d..30723f84173 100644 --- a/pkg/pipeline/DeploymentPipelineConfigService.go +++ b/pkg/pipeline/DeploymentPipelineConfigService.go @@ -24,8 +24,8 @@ import ( "fmt" application2 "github.com/argoproj/argo-cd/v2/pkg/apiclient/application" bean2 "github.com/devtron-labs/devtron/api/bean" - client "github.com/devtron-labs/devtron/api/helm-app" models2 "github.com/devtron-labs/devtron/api/helm-app/models" + client "github.com/devtron-labs/devtron/api/helm-app/service" "github.com/devtron-labs/devtron/client/argocdServer" "github.com/devtron-labs/devtron/client/argocdServer/application" "github.com/devtron-labs/devtron/internal/sql/models" diff --git a/pkg/pipeline/DockerRegistryConfig.go b/pkg/pipeline/DockerRegistryConfig.go index 2bc7a6c9415..e327c62d3cc 100644 --- a/pkg/pipeline/DockerRegistryConfig.go +++ b/pkg/pipeline/DockerRegistryConfig.go @@ -20,7 +20,8 @@ package pipeline import ( "context" "fmt" - client "github.com/devtron-labs/devtron/api/helm-app" + bean2 "github.com/devtron-labs/devtron/api/helm-app/gRPC" + client "github.com/devtron-labs/devtron/api/helm-app/service" "github.com/devtron-labs/devtron/pkg/pipeline/types" "github.com/devtron-labs/devtron/pkg/sql" "github.com/go-pg/pg" @@ -863,7 +864,7 @@ func (impl DockerRegistryConfigImpl) ValidateRegistryCredentials(bean *types.Doc bean.RegistryType == repository.REGISTRYTYPE_OTHER { return true } - request := &client.RegistryCredential{ + request := &bean2.RegistryCredential{ RegistryUrl: bean.RegistryURL, Username: bean.Username, Password: bean.Password, diff --git a/pkg/pipeline/DockerRegistryConfig_test.go b/pkg/pipeline/DockerRegistryConfig_test.go index 139b810cb9f..2a5e20e1077 100644 --- a/pkg/pipeline/DockerRegistryConfig_test.go +++ b/pkg/pipeline/DockerRegistryConfig_test.go @@ -3,7 +3,7 @@ package pipeline import ( "context" "fmt" - client "github.com/devtron-labs/devtron/api/helm-app" + client "github.com/devtron-labs/devtron/api/helm-app/gRPC" "github.com/devtron-labs/devtron/api/helm-app/mocks" repository "github.com/devtron-labs/devtron/internal/sql/repository/dockerRegistry" "github.com/devtron-labs/devtron/pkg/dockerRegistry" diff --git a/pkg/pipeline/WorkflowDagExecutor.go b/pkg/pipeline/WorkflowDagExecutor.go index 02a44d41d0d..c62ed46d835 100644 --- a/pkg/pipeline/WorkflowDagExecutor.go +++ b/pkg/pipeline/WorkflowDagExecutor.go @@ -22,6 +22,9 @@ import ( "encoding/json" errors3 "errors" "fmt" + bean6 "github.com/devtron-labs/devtron/api/helm-app/bean" + "github.com/devtron-labs/devtron/api/helm-app/gRPC" + client2 "github.com/devtron-labs/devtron/api/helm-app/service" "github.com/devtron-labs/devtron/pkg/deployment/gitOps/config" "github.com/devtron-labs/devtron/pkg/deployment/gitOps/git" "github.com/devtron-labs/devtron/pkg/deployment/manifest/deployedAppMetrics" @@ -40,7 +43,6 @@ import ( "github.com/devtron-labs/common-lib/pubsub-lib/model" util5 "github.com/devtron-labs/common-lib/utils/k8s" "github.com/devtron-labs/common-lib/utils/k8s/health" - client2 "github.com/devtron-labs/devtron/api/helm-app" "github.com/devtron-labs/devtron/client/argocdServer" "github.com/devtron-labs/devtron/client/argocdServer/application" application2 "github.com/devtron-labs/devtron/client/argocdServer/application" @@ -184,15 +186,16 @@ type WorkflowDagExecutorImpl struct { configMapRepository chartConfig.ConfigMapRepository configMapHistoryRepository repository3.ConfigMapHistoryRepository helmAppService client2.HelmAppService - helmAppClient client2.HelmAppClient - environmentConfigRepository chartConfig.EnvConfigOverrideRepository - mergeUtil *util.MergeUtil - acdClient application2.ServiceClient - argoClientWrapperService argocdServer.ArgoClientWrapperService - customTagService CustomTagService - ACDConfig *argocdServer.ACDConfig - deployedAppMetricsService deployedAppMetrics.DeployedAppMetricsService - chartRefService chartRef.ChartRefService + //TODO fix me next + helmAppClient gRPC.HelmAppClient //TODO refactoring: use helm app service instead + environmentConfigRepository chartConfig.EnvConfigOverrideRepository + mergeUtil *util.MergeUtil + acdClient application2.ServiceClient + argoClientWrapperService argocdServer.ArgoClientWrapperService + customTagService CustomTagService + ACDConfig *argocdServer.ACDConfig + deployedAppMetricsService deployedAppMetrics.DeployedAppMetricsService + chartRefService chartRef.ChartRefService gitOpsConfigReadService config.GitOpsConfigReadService gitOperationService git.GitOperationService imageDigestPolicyService imageDigestPolicy.ImageDigestPolicyService @@ -305,7 +308,7 @@ func NewWorkflowDagExecutorImpl(Logger *zap.SugaredLogger, pipelineRepository pi configMapRepository chartConfig.ConfigMapRepository, configMapHistoryRepository repository3.ConfigMapHistoryRepository, helmAppService client2.HelmAppService, - helmAppClient client2.HelmAppClient, + helmAppClient gRPC.HelmAppClient, environmentConfigRepository chartConfig.EnvConfigOverrideRepository, mergeUtil *util.MergeUtil, acdClient application2.ServiceClient, @@ -502,7 +505,7 @@ func (impl *WorkflowDagExecutorImpl) UpdateWorkflowRunnerStatusForDeployment(app if err != nil { impl.logger.Errorw("error in getting helm app release status", "appIdentifier", appIdentifier, "err", err) // Handle release not found errors - if skipReleaseNotFound && util.GetGRPCErrorDetailedMessage(err) != client2.ErrReleaseNotFound { + if skipReleaseNotFound && util.GetGRPCErrorDetailedMessage(err) != bean6.ErrReleaseNotFound { // skip this error and continue for next workflow status impl.logger.Warnw("found error, skipping helm apps status update for this trigger", "appIdentifier", appIdentifier, "err", err) return false @@ -3693,7 +3696,7 @@ func (impl *WorkflowDagExecutorImpl) createHelmAppForCdPipeline(overrideRequest releaseName := pipeline.DeploymentAppName cluster := envOverride.Environment.Cluster bearerToken := cluster.Config[util5.BearerToken] - clusterConfig := &client2.ClusterConfig{ + clusterConfig := &gRPC.ClusterConfig{ ClusterName: cluster.ClusterName, Token: bearerToken, ApiServerUrl: cluster.ServerUrl, @@ -3704,18 +3707,18 @@ func (impl *WorkflowDagExecutorImpl) createHelmAppForCdPipeline(overrideRequest clusterConfig.CertData = cluster.Config[util5.CertData] clusterConfig.CaData = cluster.Config[util5.CertificateAuthorityData] } - releaseIdentifier := &client2.ReleaseIdentifier{ + releaseIdentifier := &gRPC.ReleaseIdentifier{ ReleaseName: releaseName, ReleaseNamespace: envOverride.Namespace, ClusterConfig: clusterConfig, } if pipeline.DeploymentAppCreated { - req := &client2.UpgradeReleaseRequest{ + req := &gRPC.UpgradeReleaseRequest{ ReleaseIdentifier: releaseIdentifier, ValuesYaml: mergeAndSave, - HistoryMax: impl.helmAppService.GetRevisionHistoryMaxValue(client2.SOURCE_DEVTRON_APP), - ChartContent: &client2.ChartContent{Content: referenceChartByte}, + HistoryMax: impl.helmAppService.GetRevisionHistoryMaxValue(bean6.SOURCE_DEVTRON_APP), + ChartContent: &gRPC.ChartContent{Content: referenceChartByte}, } if impl.appService.IsDevtronAsyncInstallModeEnabled(bean2.Helm) { req.RunInCtx = true @@ -4435,11 +4438,11 @@ func (impl *WorkflowDagExecutorImpl) updatePipeline(pipeline *pipelineConfig.Pip } // helmInstallReleaseWithCustomChart performs helm install with custom chart -func (impl *WorkflowDagExecutorImpl) helmInstallReleaseWithCustomChart(ctx context.Context, releaseIdentifier *client2.ReleaseIdentifier, referenceChartByte []byte, valuesYaml string) (*client2.HelmInstallCustomResponse, error) { +func (impl *WorkflowDagExecutorImpl) helmInstallReleaseWithCustomChart(ctx context.Context, releaseIdentifier *gRPC.ReleaseIdentifier, referenceChartByte []byte, valuesYaml string) (*gRPC.HelmInstallCustomResponse, error) { - helmInstallRequest := client2.HelmInstallCustomRequest{ + helmInstallRequest := gRPC.HelmInstallCustomRequest{ ValuesYaml: valuesYaml, - ChartContent: &client2.ChartContent{Content: referenceChartByte}, + ChartContent: &gRPC.ChartContent{Content: referenceChartByte}, ReleaseIdentifier: releaseIdentifier, } if impl.appService.IsDevtronAsyncInstallModeEnabled(bean2.Helm) { diff --git a/pkg/server/ServerCacheService.go b/pkg/server/ServerCacheService.go index 8ac2b334494..27d67a85ded 100644 --- a/pkg/server/ServerCacheService.go +++ b/pkg/server/ServerCacheService.go @@ -19,7 +19,7 @@ package server import ( "context" - client "github.com/devtron-labs/devtron/api/helm-app" + client "github.com/devtron-labs/devtron/api/helm-app/service" serverBean "github.com/devtron-labs/devtron/pkg/server/bean" serverEnvConfig "github.com/devtron-labs/devtron/pkg/server/config" serverDataStore "github.com/devtron-labs/devtron/pkg/server/store" diff --git a/pkg/server/ServerService.go b/pkg/server/ServerService.go index 731bce828a4..75a19c99f61 100644 --- a/pkg/server/ServerService.go +++ b/pkg/server/ServerService.go @@ -20,7 +20,8 @@ package server import ( "context" "errors" - client "github.com/devtron-labs/devtron/api/helm-app" + "github.com/devtron-labs/devtron/api/helm-app/gRPC" + client "github.com/devtron-labs/devtron/api/helm-app/service" moduleRepo "github.com/devtron-labs/devtron/pkg/module/repo" moduleUtil "github.com/devtron-labs/devtron/pkg/module/util" serverBean "github.com/devtron-labs/devtron/pkg/server/bean" @@ -130,7 +131,7 @@ func (impl ServerServiceImpl) HandleServerAction(userId int32, serverActionReque // HELM_OPERATION Starts devtronHelmAppIdentifier := impl.helmAppService.GetDevtronHelmAppIdentifier() - chartRepository := &client.ChartRepository{ + chartRepository := &gRPC.ChartRepository{ Name: impl.serverEnvConfig.DevtronHelmRepoName, Url: impl.serverEnvConfig.DevtronHelmRepoUrl, } diff --git a/pkg/sql/UtilStructs.go b/pkg/sql/UtilStructs.go index bb8553f1e5d..a067135431a 100644 --- a/pkg/sql/UtilStructs.go +++ b/pkg/sql/UtilStructs.go @@ -36,3 +36,17 @@ func NewDefaultAuditLog(userId int32) AuditLog { UpdatedBy: userId, } } + +// CreateAuditLog can be used by any repository to create AuditLog for insert operation +func (model *AuditLog) CreateAuditLog(userId int32) { + model.CreatedOn = time.Now() + model.UpdatedOn = time.Now() + model.CreatedBy = userId + model.UpdatedBy = userId +} + +// UpdateAuditLog can be used by any repository to update AuditLog for update operation +func (model *AuditLog) UpdateAuditLog(userId int32) { + model.UpdatedOn = time.Now() + model.UpdatedBy = userId +} diff --git a/pkg/webhook/helm/WebhookHelmService.go b/pkg/webhook/helm/WebhookHelmService.go index f52f453cb0b..1058bd728ca 100644 --- a/pkg/webhook/helm/WebhookHelmService.go +++ b/pkg/webhook/helm/WebhookHelmService.go @@ -20,7 +20,9 @@ package webhookHelm import ( "context" "fmt" - client "github.com/devtron-labs/devtron/api/helm-app" + "github.com/devtron-labs/devtron/api/helm-app/bean" + bean2 "github.com/devtron-labs/devtron/api/helm-app/gRPC" + client "github.com/devtron-labs/devtron/api/helm-app/service" "github.com/devtron-labs/devtron/api/restHandler/common" "github.com/devtron-labs/devtron/pkg/attributes" "github.com/devtron-labs/devtron/pkg/chartRepo" @@ -119,15 +121,15 @@ func (impl WebhookHelmServiceImpl) CreateOrUpdateHelmApplication(ctx context.Con // STEP-6 install/update release chart := request.Chart chartRepo := request.Chart.Repo - installReleaseRequest := &client.InstallReleaseRequest{ - ReleaseIdentifier: &client.ReleaseIdentifier{ + installReleaseRequest := &bean2.InstallReleaseRequest{ + ReleaseIdentifier: &bean2.ReleaseIdentifier{ ReleaseName: appIdentifier.ReleaseName, ReleaseNamespace: appIdentifier.Namespace, }, ChartName: chart.ChartName, ChartVersion: chart.ChartVersion, ValuesYaml: request.ValuesOverrideYaml, - ChartRepository: &client.ChartRepository{ + ChartRepository: &bean2.ChartRepository{ Name: chartRepo.Name, Url: chartRepo.Identifier.Url, Username: chartRepo.Identifier.Username, @@ -135,9 +137,9 @@ func (impl WebhookHelmServiceImpl) CreateOrUpdateHelmApplication(ctx context.Con }, } if isInstalled { - updateReleaseRequest := &client.UpdateApplicationWithChartInfoRequestDto{ + updateReleaseRequest := &bean.UpdateApplicationWithChartInfoRequestDto{ InstallReleaseRequest: installReleaseRequest, - SourceAppType: client.SOURCE_HELM_APP, + SourceAppType: bean.SOURCE_HELM_APP, } res, err := impl.helmAppService.UpdateApplicationWithChartInfo(ctx, clusterId, updateReleaseRequest) if err != nil { diff --git a/wire_gen.go b/wire_gen.go index 1c0ba9a9bfd..e232c9c7ec2 100644 --- a/wire_gen.go +++ b/wire_gen.go @@ -29,6 +29,8 @@ import ( "github.com/devtron-labs/devtron/api/deployment" externalLink2 "github.com/devtron-labs/devtron/api/externalLink" client3 "github.com/devtron-labs/devtron/api/helm-app" + "github.com/devtron-labs/devtron/api/helm-app/gRPC" + "github.com/devtron-labs/devtron/api/helm-app/service" application3 "github.com/devtron-labs/devtron/api/k8s/application" capacity2 "github.com/devtron-labs/devtron/api/k8s/capacity" module2 "github.com/devtron-labs/devtron/api/module" @@ -80,14 +82,13 @@ import ( repository15 "github.com/devtron-labs/devtron/pkg/appStore/chartGroup/repository" "github.com/devtron-labs/devtron/pkg/appStore/chartProvider" "github.com/devtron-labs/devtron/pkg/appStore/deployment/common" - "github.com/devtron-labs/devtron/pkg/appStore/deployment/fullMode" repository3 "github.com/devtron-labs/devtron/pkg/appStore/deployment/repository" - service2 "github.com/devtron-labs/devtron/pkg/appStore/deployment/service" + service3 "github.com/devtron-labs/devtron/pkg/appStore/deployment/service" "github.com/devtron-labs/devtron/pkg/appStore/deployment/tool" "github.com/devtron-labs/devtron/pkg/appStore/discover/repository" - service3 "github.com/devtron-labs/devtron/pkg/appStore/discover/service" + service4 "github.com/devtron-labs/devtron/pkg/appStore/discover/service" "github.com/devtron-labs/devtron/pkg/appStore/values/repository" - "github.com/devtron-labs/devtron/pkg/appStore/values/service" + service2 "github.com/devtron-labs/devtron/pkg/appStore/values/service" appWorkflow2 "github.com/devtron-labs/devtron/pkg/appWorkflow" "github.com/devtron-labs/devtron/pkg/attributes" "github.com/devtron-labs/devtron/pkg/auth/authentication" @@ -263,11 +264,11 @@ func InitializeApp() (*App, error) { } gitOpsConfigReadServiceImpl := config.NewGitOpsConfigReadServiceImpl(sugaredLogger, gitOpsConfigRepositoryImpl, userServiceImpl, globalEnvVariables) clusterServiceImplExtended := cluster2.NewClusterServiceImplExtended(clusterRepositoryImpl, environmentRepositoryImpl, grafanaClientImpl, sugaredLogger, installedAppRepositoryImpl, k8sServiceImpl, serviceClientImpl, k8sInformerFactoryImpl, userAuthRepositoryImpl, userRepositoryImpl, roleGroupRepositoryImpl, gitOpsConfigReadServiceImpl) - helmClientConfig, err := client3.GetConfig() + helmClientConfig, err := gRPC.GetConfig() if err != nil { return nil, err } - helmAppClientImpl := client3.NewHelmAppClientImpl(sugaredLogger, helmClientConfig) + helmAppClientImpl := gRPC.NewHelmAppClientImpl(sugaredLogger, helmClientConfig) pumpImpl := connector.NewPumpImpl(sugaredLogger) teamRepositoryImpl := team.NewTeamRepositoryImpl(db) appRepositoryImpl := app.NewAppRepositoryImpl(db, sugaredLogger) @@ -277,11 +278,11 @@ func InitializeApp() (*App, error) { loginService := middleware.NewUserLogin(sessionManager, k8sClient) userAuthServiceImpl := user.NewUserAuthServiceImpl(userAuthRepositoryImpl, sessionManager, loginService, sugaredLogger, userRepositoryImpl, roleGroupRepositoryImpl, userServiceImpl) environmentServiceImpl := cluster2.NewEnvironmentServiceImpl(environmentRepositoryImpl, clusterServiceImplExtended, sugaredLogger, k8sServiceImpl, k8sInformerFactoryImpl, userAuthServiceImpl, attributesRepositoryImpl) - helmReleaseConfig, err := client3.GetHelmReleaseConfig() + helmReleaseConfig, err := service.GetHelmReleaseConfig() if err != nil { return nil, err } - helmAppServiceImpl := client3.NewHelmAppServiceImpl(sugaredLogger, clusterServiceImplExtended, helmAppClientImpl, pumpImpl, enforcerUtilHelmImpl, serverDataStoreServerDataStore, serverEnvConfigServerEnvConfig, appStoreApplicationVersionRepositoryImpl, environmentServiceImpl, pipelineRepositoryImpl, installedAppRepositoryImpl, appRepositoryImpl, clusterRepositoryImpl, k8sServiceImpl, helmReleaseConfig) + helmAppServiceImpl := service.NewHelmAppServiceImpl(sugaredLogger, clusterServiceImplExtended, helmAppClientImpl, pumpImpl, enforcerUtilHelmImpl, serverDataStoreServerDataStore, serverEnvConfigServerEnvConfig, appStoreApplicationVersionRepositoryImpl, environmentServiceImpl, pipelineRepositoryImpl, installedAppRepositoryImpl, appRepositoryImpl, clusterRepositoryImpl, k8sServiceImpl, helmReleaseConfig) serverCacheServiceImpl := server.NewServerCacheServiceImpl(sugaredLogger, serverEnvConfigServerEnvConfig, serverDataStoreServerDataStore, helmAppServiceImpl) moduleEnvConfig, err := module.ParseModuleEnvConfig() if err != nil { @@ -536,22 +537,21 @@ func InitializeApp() (*App, error) { pipelineStatusTimelineRestHandlerImpl := restHandler.NewPipelineStatusTimelineRestHandlerImpl(sugaredLogger, pipelineStatusTimelineServiceImpl, enforcerUtilImpl, enforcerImpl) pipelineConfigRouterImpl := router.NewPipelineRouterImpl(pipelineConfigRestHandlerImpl, appWorkflowRestHandlerImpl, webhookDataRestHandlerImpl, pipelineHistoryRestHandlerImpl, pipelineStatusTimelineRestHandlerImpl) appStoreVersionValuesRepositoryImpl := appStoreValuesRepository.NewAppStoreVersionValuesRepositoryImpl(sugaredLogger, db) - appStoreValuesServiceImpl := service.NewAppStoreValuesServiceImpl(sugaredLogger, appStoreApplicationVersionRepositoryImpl, installedAppRepositoryImpl, appStoreVersionValuesRepositoryImpl, userServiceImpl) + appStoreValuesServiceImpl := service2.NewAppStoreValuesServiceImpl(sugaredLogger, appStoreApplicationVersionRepositoryImpl, installedAppRepositoryImpl, appStoreVersionValuesRepositoryImpl, userServiceImpl) chartGroupDeploymentRepositoryImpl := repository15.NewChartGroupDeploymentRepositoryImpl(db, sugaredLogger) acdAuthConfig, err := util3.GetACDAuthConfig() if err != nil { return nil, err } - appStoreDeploymentCommonServiceImpl := appStoreDeploymentCommon.NewAppStoreDeploymentCommonServiceImpl(sugaredLogger, installedAppRepositoryImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl, chartTemplateServiceImpl, gitFactory, gitOpsConfigReadServiceImpl, gitOperationServiceImpl) - appStoreDeploymentFullModeServiceImpl := appStoreDeploymentFullMode.NewAppStoreDeploymentFullModeServiceImpl(sugaredLogger, applicationServiceClientImpl, argoK8sClientImpl, acdAuthConfig, argoUserServiceImpl, pipelineStatusTimelineServiceImpl, appStoreDeploymentCommonServiceImpl, argoClientWrapperServiceImpl, pubSubClientServiceImpl, installedAppVersionHistoryRepositoryImpl, acdConfig, gitOpsConfigReadServiceImpl, gitOperationServiceImpl) clusterInstalledAppsRepositoryImpl := repository3.NewClusterInstalledAppsRepositoryImpl(db, sugaredLogger) - appStoreDeploymentHelmServiceImpl := appStoreDeploymentTool.NewAppStoreDeploymentHelmServiceImpl(sugaredLogger, helmAppServiceImpl, appStoreApplicationVersionRepositoryImpl, helmAppClientImpl, installedAppRepositoryImpl, appStoreDeploymentCommonServiceImpl, ociRegistryConfigRepositoryImpl, gitOperationServiceImpl) - appStoreDeploymentArgoCdServiceImpl := appStoreDeploymentTool.NewAppStoreDeploymentArgoCdServiceImpl(sugaredLogger, appStoreDeploymentFullModeServiceImpl, applicationServiceClientImpl, chartGroupDeploymentRepositoryImpl, installedAppRepositoryImpl, installedAppVersionHistoryRepositoryImpl, appStoreDeploymentCommonServiceImpl, helmAppServiceImpl, appStatusServiceImpl, pipelineStatusTimelineServiceImpl, userServiceImpl, pipelineStatusTimelineRepositoryImpl, appStoreApplicationVersionRepositoryImpl, argoClientWrapperServiceImpl, acdConfig, gitOperationServiceImpl) - serviceDeploymentServiceTypeConfig, err := service2.GetDeploymentServiceTypeConfig() + appStoreDeploymentHelmServiceImpl := appStoreDeploymentTool.NewAppStoreDeploymentHelmServiceImpl(sugaredLogger, helmAppServiceImpl, appStoreApplicationVersionRepositoryImpl, helmAppClientImpl, installedAppRepositoryImpl, ociRegistryConfigRepositoryImpl) + appStoreDeploymentCommonServiceImpl := appStoreDeploymentCommon.NewAppStoreDeploymentCommonServiceImpl(sugaredLogger, appStoreApplicationVersionRepositoryImpl, chartTemplateServiceImpl) + appStoreDeploymentArgoCdServiceImpl := appStoreDeploymentTool.NewAppStoreDeploymentArgoCdServiceImpl(sugaredLogger, applicationServiceClientImpl, argoK8sClientImpl, acdAuthConfig, chartGroupDeploymentRepositoryImpl, installedAppRepositoryImpl, installedAppVersionHistoryRepositoryImpl, argoUserServiceImpl, appStoreDeploymentCommonServiceImpl, helmAppServiceImpl, appStatusServiceImpl, pipelineStatusTimelineServiceImpl, userServiceImpl, pipelineStatusTimelineRepositoryImpl, appStoreApplicationVersionRepositoryImpl, argoClientWrapperServiceImpl, acdConfig, gitOperationServiceImpl, gitOpsConfigReadServiceImpl, environmentRepositoryImpl) + serviceDeploymentServiceTypeConfig, err := service3.GetDeploymentServiceTypeConfig() if err != nil { return nil, err } - appStoreDeploymentServiceImpl := service2.NewAppStoreDeploymentServiceImpl(sugaredLogger, installedAppRepositoryImpl, chartGroupDeploymentRepositoryImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl, clusterInstalledAppsRepositoryImpl, appRepositoryImpl, appStoreDeploymentHelmServiceImpl, appStoreDeploymentArgoCdServiceImpl, environmentServiceImpl, clusterServiceImplExtended, helmAppServiceImpl, appStoreDeploymentCommonServiceImpl, installedAppVersionHistoryRepositoryImpl, serviceDeploymentServiceTypeConfig, acdConfig, gitOpsConfigReadServiceImpl, gitOperationServiceImpl) + appStoreDeploymentServiceImpl := service3.NewAppStoreDeploymentServiceImpl(sugaredLogger, installedAppRepositoryImpl, chartGroupDeploymentRepositoryImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl, clusterInstalledAppsRepositoryImpl, appRepositoryImpl, appStoreDeploymentHelmServiceImpl, appStoreDeploymentArgoCdServiceImpl, environmentServiceImpl, clusterServiceImplExtended, helmAppServiceImpl, appStoreDeploymentCommonServiceImpl, installedAppVersionHistoryRepositoryImpl, serviceDeploymentServiceTypeConfig, acdConfig, gitOpsConfigReadServiceImpl, gitOperationServiceImpl) k8sResourceHistoryRepositoryImpl := repository16.NewK8sResourceHistoryRepositoryImpl(db, sugaredLogger) k8sResourceHistoryServiceImpl := kubernetesResourceAuditLogs.Newk8sResourceHistoryServiceImpl(k8sResourceHistoryRepositoryImpl, sugaredLogger, appRepositoryImpl, environmentRepositoryImpl) ephemeralContainersRepositoryImpl := repository2.NewEphemeralContainersRepositoryImpl(db) @@ -561,7 +561,7 @@ func InitializeApp() (*App, error) { if err != nil { return nil, err } - installedAppServiceImpl, err := service2.NewInstalledAppServiceImpl(sugaredLogger, installedAppRepositoryImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl, teamRepositoryImpl, appRepositoryImpl, applicationServiceClientImpl, appStoreValuesServiceImpl, pubSubClientServiceImpl, chartGroupDeploymentRepositoryImpl, environmentServiceImpl, acdAuthConfig, userServiceImpl, appStoreDeploymentFullModeServiceImpl, appStoreDeploymentServiceImpl, installedAppVersionHistoryRepositoryImpl, argoUserServiceImpl, helmAppClientImpl, helmAppServiceImpl, appStatusServiceImpl, k8sServiceImpl, pipelineStatusTimelineServiceImpl, appStoreDeploymentCommonServiceImpl, k8sCommonServiceImpl, k8sApplicationServiceImpl, acdConfig, gitOpsConfigReadServiceImpl, gitOperationServiceImpl) + installedAppServiceImpl, err := service3.NewInstalledAppServiceImpl(sugaredLogger, installedAppRepositoryImpl, appStoreApplicationVersionRepositoryImpl, environmentRepositoryImpl, teamRepositoryImpl, appRepositoryImpl, applicationServiceClientImpl, appStoreValuesServiceImpl, pubSubClientServiceImpl, chartGroupDeploymentRepositoryImpl, environmentServiceImpl, userServiceImpl, acdAuthConfig, appStoreDeploymentServiceImpl, installedAppVersionHistoryRepositoryImpl, argoUserServiceImpl, helmAppClientImpl, helmAppServiceImpl, appStatusServiceImpl, k8sServiceImpl, pipelineStatusTimelineServiceImpl, k8sCommonServiceImpl, k8sApplicationServiceImpl, acdConfig, gitOperationServiceImpl, appStoreDeploymentArgoCdServiceImpl) if err != nil { return nil, err } @@ -648,7 +648,7 @@ func InitializeApp() (*App, error) { installedAppRestHandlerImpl := appStore.NewInstalledAppRestHandlerImpl(sugaredLogger, userServiceImpl, enforcerImpl, enforcerUtilImpl, enforcerUtilHelmImpl, installedAppServiceImpl, validate, clusterServiceImplExtended, applicationServiceClientImpl, appStoreDeploymentServiceImpl, helmAppClientImpl, argoUserServiceImpl, cdApplicationStatusUpdateHandlerImpl, installedAppRepositoryImpl, appCrudOperationServiceImpl) appStoreValuesRestHandlerImpl := appStoreValues.NewAppStoreValuesRestHandlerImpl(sugaredLogger, userServiceImpl, appStoreValuesServiceImpl) appStoreValuesRouterImpl := appStoreValues.NewAppStoreValuesRouterImpl(appStoreValuesRestHandlerImpl) - appStoreServiceImpl := service3.NewAppStoreServiceImpl(sugaredLogger, appStoreApplicationVersionRepositoryImpl) + appStoreServiceImpl := service4.NewAppStoreServiceImpl(sugaredLogger, appStoreApplicationVersionRepositoryImpl) appStoreRestHandlerImpl := appStoreDiscover.NewAppStoreRestHandlerImpl(sugaredLogger, userServiceImpl, appStoreServiceImpl, enforcerImpl) appStoreDiscoverRouterImpl := appStoreDiscover.NewAppStoreDiscoverRouterImpl(appStoreRestHandlerImpl) chartProviderRestHandlerImpl := chartProvider2.NewChartProviderRestHandlerImpl(sugaredLogger, userServiceImpl, validate, chartProviderServiceImpl, enforcerImpl) @@ -740,7 +740,7 @@ func InitializeApp() (*App, error) { appRouterImpl := router.NewAppRouterImpl(sugaredLogger, appRestHandlerImpl) coreAppRestHandlerImpl := restHandler.NewCoreAppRestHandlerImpl(sugaredLogger, userServiceImpl, validate, enforcerUtilImpl, enforcerImpl, appCrudOperationServiceImpl, pipelineBuilderImpl, gitRegistryConfigImpl, chartServiceImpl, configMapServiceImpl, appListingServiceImpl, propertiesConfigServiceImpl, appWorkflowServiceImpl, materialRepositoryImpl, gitProviderRepositoryImpl, appWorkflowRepositoryImpl, environmentRepositoryImpl, configMapRepositoryImpl, chartRepositoryImpl, teamServiceImpl, argoUserServiceImpl, pipelineStageServiceImpl, ciPipelineRepositoryImpl) coreAppRouterImpl := router.NewCoreAppRouterImpl(coreAppRestHandlerImpl) - helmAppRestHandlerImpl := client3.NewHelmAppRestHandlerImpl(sugaredLogger, helmAppServiceImpl, enforcerImpl, clusterServiceImplExtended, enforcerUtilHelmImpl, appStoreDeploymentCommonServiceImpl, userServiceImpl, attributesServiceImpl, serverEnvConfigServerEnvConfig) + helmAppRestHandlerImpl := client3.NewHelmAppRestHandlerImpl(sugaredLogger, helmAppServiceImpl, enforcerImpl, clusterServiceImplExtended, enforcerUtilHelmImpl, appStoreDeploymentServiceImpl, userServiceImpl, attributesServiceImpl, serverEnvConfigServerEnvConfig) helmAppRouterImpl := client3.NewHelmAppRouterImpl(helmAppRestHandlerImpl) k8sApplicationRestHandlerImpl := application3.NewK8sApplicationRestHandlerImpl(sugaredLogger, k8sApplicationServiceImpl, pumpImpl, terminalSessionHandlerImpl, enforcerImpl, enforcerUtilHelmImpl, enforcerUtilImpl, helmAppServiceImpl, userServiceImpl, k8sCommonServiceImpl, validate) k8sApplicationRouterImpl := application3.NewK8sApplicationRouterImpl(k8sApplicationRestHandlerImpl) @@ -750,7 +750,7 @@ func InitializeApp() (*App, error) { deploymentConfigRouterImpl := deployment.NewDeploymentRouterImpl(deploymentConfigRestHandlerImpl) dashboardTelemetryRestHandlerImpl := dashboardEvent.NewDashboardTelemetryRestHandlerImpl(sugaredLogger, telemetryEventClientImplExtended) dashboardTelemetryRouterImpl := dashboardEvent.NewDashboardTelemetryRouterImpl(dashboardTelemetryRestHandlerImpl) - commonDeploymentRestHandlerImpl := appStoreDeployment.NewCommonDeploymentRestHandlerImpl(sugaredLogger, userServiceImpl, enforcerImpl, enforcerUtilImpl, enforcerUtilHelmImpl, appStoreDeploymentServiceImpl, validate, helmAppServiceImpl, appStoreDeploymentCommonServiceImpl, helmAppRestHandlerImpl, argoUserServiceImpl) + commonDeploymentRestHandlerImpl := appStoreDeployment.NewCommonDeploymentRestHandlerImpl(sugaredLogger, userServiceImpl, enforcerImpl, enforcerUtilImpl, enforcerUtilHelmImpl, appStoreDeploymentServiceImpl, validate, helmAppServiceImpl, helmAppRestHandlerImpl, argoUserServiceImpl) commonDeploymentRouterImpl := appStoreDeployment.NewCommonDeploymentRouterImpl(commonDeploymentRestHandlerImpl) externalLinkMonitoringToolRepositoryImpl := externalLink.NewExternalLinkMonitoringToolRepositoryImpl(db) externalLinkIdentifierMappingRepositoryImpl := externalLink.NewExternalLinkIdentifierMappingRepositoryImpl(db)