diff --git a/api/argoApplication/ArgoApplicationRestHandler.go b/api/argoApplication/ArgoApplicationRestHandler.go index 5478f62e47f..a48812d3290 100644 --- a/api/argoApplication/ArgoApplicationRestHandler.go +++ b/api/argoApplication/ArgoApplicationRestHandler.go @@ -20,6 +20,7 @@ import ( "errors" "github.com/devtron-labs/devtron/api/restHandler/common" "github.com/devtron-labs/devtron/pkg/argoApplication" + "github.com/devtron-labs/devtron/pkg/argoApplication/read" "github.com/devtron-labs/devtron/pkg/auth/authorisation/casbin" "go.uber.org/zap" "net/http" @@ -34,14 +35,16 @@ type ArgoApplicationRestHandler interface { type ArgoApplicationRestHandlerImpl struct { argoApplicationService argoApplication.ArgoApplicationService + readService read.ArgoApplicationReadService logger *zap.SugaredLogger enforcer casbin.Enforcer } func NewArgoApplicationRestHandlerImpl(argoApplicationService argoApplication.ArgoApplicationService, - logger *zap.SugaredLogger, enforcer casbin.Enforcer) *ArgoApplicationRestHandlerImpl { + readService read.ArgoApplicationReadService, logger *zap.SugaredLogger, enforcer casbin.Enforcer) *ArgoApplicationRestHandlerImpl { return &ArgoApplicationRestHandlerImpl{ argoApplicationService: argoApplicationService, + readService: readService, logger: logger, enforcer: enforcer, } @@ -101,9 +104,9 @@ func (handler *ArgoApplicationRestHandlerImpl) GetApplicationDetail(w http.Respo return } } - resp, err := handler.argoApplicationService.GetAppDetail(resourceName, namespace, clusterId) + resp, err := handler.readService.GetAppDetail(resourceName, namespace, clusterId) if err != nil { - handler.logger.Errorw("error in listing all argo applications", "err", err, "resourceName", resourceName, "clusterId", clusterId) + handler.logger.Errorw("error in getting argo application app detail", "err", err, "resourceName", resourceName, "clusterId", clusterId) common.WriteJsonResp(w, err, nil, http.StatusInternalServerError) return } diff --git a/api/argoApplication/wire_argoApplication.go b/api/argoApplication/wire_argoApplication.go index a65ac47028f..d70cfd30822 100644 --- a/api/argoApplication/wire_argoApplication.go +++ b/api/argoApplication/wire_argoApplication.go @@ -18,10 +18,14 @@ package argoApplication import ( "github.com/devtron-labs/devtron/pkg/argoApplication" + "github.com/devtron-labs/devtron/pkg/argoApplication/read" "github.com/google/wire" ) var ArgoApplicationWireSet = wire.NewSet( + read.NewArgoApplicationReadServiceImpl, + wire.Bind(new(read.ArgoApplicationReadService), new(*read.ArgoApplicationReadServiceImpl)), + argoApplication.NewArgoApplicationServiceImpl, wire.Bind(new(argoApplication.ArgoApplicationService), new(*argoApplication.ArgoApplicationServiceImpl)), diff --git a/api/helm-app/HelmAppRestHandler.go b/api/helm-app/HelmAppRestHandler.go index 9a46413f698..3762a109901 100644 --- a/api/helm-app/HelmAppRestHandler.go +++ b/api/helm-app/HelmAppRestHandler.go @@ -25,6 +25,7 @@ import ( "github.com/devtron-labs/devtron/pkg/appStore/installedApp/service" "github.com/devtron-labs/devtron/pkg/appStore/installedApp/service/EAMode" "github.com/devtron-labs/devtron/pkg/argoApplication" + "github.com/devtron-labs/devtron/pkg/argoApplication/helper" clientErrors "github.com/devtron-labs/devtron/pkg/errors" "github.com/devtron-labs/devtron/pkg/fluxApplication" bean2 "github.com/devtron-labs/devtron/pkg/k8s/application/bean" @@ -232,7 +233,7 @@ func (handler *HelmAppRestHandlerImpl) handleFluxApplicationHibernate(r *http.Re return handler.fluxApplication.HibernateFluxApplication(r.Context(), appIdentifier, hibernateRequest) } func (handler *HelmAppRestHandlerImpl) handleArgoApplicationHibernate(r *http.Request, token string, hibernateRequest *openapi.HibernateRequest) ([]*openapi.HibernateStatus, error) { - appIdentifier, err := argoApplication.DecodeExternalArgoAppId(*hibernateRequest.AppId) + appIdentifier, err := helper.DecodeExternalArgoAppId(*hibernateRequest.AppId) if err != nil { return nil, err } @@ -316,7 +317,7 @@ func (handler *HelmAppRestHandlerImpl) handleFluxApplicationUnHibernate(r *http. return handler.fluxApplication.UnHibernateFluxApplication(r.Context(), appIdentifier, hibernateRequest) } func (handler *HelmAppRestHandlerImpl) handleArgoApplicationUnHibernate(r *http.Request, token string, hibernateRequest *openapi.HibernateRequest) ([]*openapi.HibernateStatus, error) { - appIdentifier, err := argoApplication.DecodeExternalArgoAppId(*hibernateRequest.AppId) + appIdentifier, err := helper.DecodeExternalArgoAppId(*hibernateRequest.AppId) if err != nil { return nil, err } diff --git a/api/k8s/application/k8sApplicationRestHandler.go b/api/k8s/application/k8sApplicationRestHandler.go index d153d84c980..8f5e7ee968b 100644 --- a/api/k8s/application/k8sApplicationRestHandler.go +++ b/api/k8s/application/k8sApplicationRestHandler.go @@ -33,7 +33,8 @@ import ( client "github.com/devtron-labs/devtron/api/helm-app/service" "github.com/devtron-labs/devtron/api/restHandler/common" util2 "github.com/devtron-labs/devtron/internal/util" - "github.com/devtron-labs/devtron/pkg/argoApplication" + "github.com/devtron-labs/devtron/pkg/argoApplication/helper" + "github.com/devtron-labs/devtron/pkg/argoApplication/read" "github.com/devtron-labs/devtron/pkg/auth/authorisation/casbin" "github.com/devtron-labs/devtron/pkg/auth/user" "github.com/devtron-labs/devtron/pkg/cluster" @@ -81,39 +82,39 @@ type K8sApplicationRestHandler interface { } type K8sApplicationRestHandlerImpl struct { - logger *zap.SugaredLogger - k8sApplicationService application2.K8sApplicationService - pump connector.Pump - terminalSessionHandler terminal.TerminalSessionHandler - enforcer casbin.Enforcer - validator *validator.Validate - enforcerUtil rbac.EnforcerUtil - enforcerUtilHelm rbac.EnforcerUtilHelm - helmAppService client.HelmAppService - userService user.UserService - k8sCommonService k8s.K8sCommonService - terminalEnvVariables *util.TerminalEnvVariables - fluxAppService fluxApplication.FluxApplicationService - argoApplication argoApplication.ArgoApplicationService + logger *zap.SugaredLogger + k8sApplicationService application2.K8sApplicationService + pump connector.Pump + terminalSessionHandler terminal.TerminalSessionHandler + enforcer casbin.Enforcer + validator *validator.Validate + enforcerUtil rbac.EnforcerUtil + enforcerUtilHelm rbac.EnforcerUtilHelm + helmAppService client.HelmAppService + userService user.UserService + k8sCommonService k8s.K8sCommonService + terminalEnvVariables *util.TerminalEnvVariables + fluxAppService fluxApplication.FluxApplicationService + argoApplicationReadService read.ArgoApplicationReadService } -func NewK8sApplicationRestHandlerImpl(logger *zap.SugaredLogger, k8sApplicationService application2.K8sApplicationService, pump connector.Pump, terminalSessionHandler terminal.TerminalSessionHandler, enforcer casbin.Enforcer, enforcerUtilHelm rbac.EnforcerUtilHelm, enforcerUtil rbac.EnforcerUtil, helmAppService client.HelmAppService, userService user.UserService, k8sCommonService k8s.K8sCommonService, validator *validator.Validate, envVariables *util.EnvironmentVariables, fluxAppService fluxApplication.FluxApplicationService, argoApplication argoApplication.ArgoApplicationService, +func NewK8sApplicationRestHandlerImpl(logger *zap.SugaredLogger, k8sApplicationService application2.K8sApplicationService, pump connector.Pump, terminalSessionHandler terminal.TerminalSessionHandler, enforcer casbin.Enforcer, enforcerUtilHelm rbac.EnforcerUtilHelm, enforcerUtil rbac.EnforcerUtil, helmAppService client.HelmAppService, userService user.UserService, k8sCommonService k8s.K8sCommonService, validator *validator.Validate, envVariables *util.EnvironmentVariables, fluxAppService fluxApplication.FluxApplicationService, argoApplicationReadService read.ArgoApplicationReadService, ) *K8sApplicationRestHandlerImpl { return &K8sApplicationRestHandlerImpl{ - logger: logger, - k8sApplicationService: k8sApplicationService, - pump: pump, - terminalSessionHandler: terminalSessionHandler, - enforcer: enforcer, - validator: validator, - enforcerUtilHelm: enforcerUtilHelm, - enforcerUtil: enforcerUtil, - helmAppService: helmAppService, - userService: userService, - k8sCommonService: k8sCommonService, - terminalEnvVariables: envVariables.TerminalEnvVariables, - fluxAppService: fluxAppService, - argoApplication: argoApplication, + logger: logger, + k8sApplicationService: k8sApplicationService, + pump: pump, + terminalSessionHandler: terminalSessionHandler, + enforcer: enforcer, + validator: validator, + enforcerUtilHelm: enforcerUtilHelm, + enforcerUtil: enforcerUtil, + helmAppService: helmAppService, + userService: userService, + k8sCommonService: k8sCommonService, + terminalEnvVariables: envVariables.TerminalEnvVariables, + fluxAppService: fluxAppService, + argoApplicationReadService: argoApplicationReadService, } } @@ -289,7 +290,7 @@ func (handler *K8sApplicationRestHandlerImpl) GetHostUrlsByBatch(w http.Response resourceTreeResponse = appDetail.ResourceTreeResponse } else if appType == bean2.ArgoAppType { - appIdentifier, err := argoApplication.DecodeExternalArgoAppId(appIdString) + appIdentifier, err := helper.DecodeExternalArgoAppId(appIdString) if err != nil { common.WriteJsonResp(w, err, nil, http.StatusBadRequest) return @@ -301,7 +302,7 @@ func (handler *K8sApplicationRestHandlerImpl) GetHostUrlsByBatch(w http.Response } //RBAC enforcer Ends - appDetail, err := handler.argoApplication.GetAppDetail(appIdentifier.AppName, appIdentifier.Namespace, appIdentifier.ClusterId) + appDetail, err := handler.argoApplicationReadService.GetAppDetail(appIdentifier.AppName, appIdentifier.Namespace, appIdentifier.ClusterId) if err != nil { apiError := clientErrors.ConvertToApiError(err) if apiError != nil { @@ -721,12 +722,12 @@ func (handler *K8sApplicationRestHandlerImpl) requestValidationAndRBAC(w http.Re } //RBAC enforcer ends here } else if request.AppType == bean2.ArgoAppType && request.ExternalArgoApplicationName != "" { - appIdentifier, err := argoApplication.DecodeExternalArgoAppId(request.AppId) + appIdentifier, err := helper.DecodeExternalArgoAppId(request.AppId) if err != nil { handler.logger.Errorw(bean2.AppIdDecodingError, "err", err, "appIdentifier", request.AppIdentifier) common.WriteJsonResp(w, err, nil, http.StatusBadRequest) } - valid, err := handler.k8sApplicationService.ValidateArgoResourceRequest(r.Context(), appIdentifier, request.K8sRequest) + valid, err := handler.argoApplicationReadService.ValidateArgoResourceRequest(r.Context(), appIdentifier, request.K8sRequest) if err != nil || !valid { handler.logger.Errorw("error in validating resource request", "err", err) common.WriteJsonResp(w, err, nil, http.StatusBadRequest) @@ -1145,14 +1146,14 @@ func (handler *K8sApplicationRestHandlerImpl) verifyRbacForAppRequests(token str envObject := "" switch request.AppType { case bean2.ArgoAppType: - argoAppIdentifier, err := argoApplication.DecodeExternalArgoAppId(request.AppId) + argoAppIdentifier, err := helper.DecodeExternalArgoAppId(request.AppId) if err != nil { handler.logger.Errorw("error in decoding appId", "err", err, "appId", request.AppId) return false, err } request.ClusterId = argoAppIdentifier.ClusterId request.ExternalArgoApplicationName = argoAppIdentifier.AppName - valid, err := handler.k8sApplicationService.ValidateArgoResourceRequest(r.Context(), argoAppIdentifier, request.K8sRequest) + valid, err := handler.argoApplicationReadService.ValidateArgoResourceRequest(r.Context(), argoAppIdentifier, request.K8sRequest) if err != nil || !valid { handler.logger.Errorw("error in validating resource request", "err", err) return false, err diff --git a/cmd/external-app/wire_gen.go b/cmd/external-app/wire_gen.go index 5271cca4cdd..ab3bca55cdc 100644 --- a/cmd/external-app/wire_gen.go +++ b/cmd/external-app/wire_gen.go @@ -67,6 +67,7 @@ import ( "github.com/devtron-labs/devtron/pkg/appStore/values/repository" service4 "github.com/devtron-labs/devtron/pkg/appStore/values/service" "github.com/devtron-labs/devtron/pkg/argoApplication" + "github.com/devtron-labs/devtron/pkg/argoApplication/read" "github.com/devtron-labs/devtron/pkg/argoRepositoryCreds" "github.com/devtron-labs/devtron/pkg/attributes" "github.com/devtron-labs/devtron/pkg/auth/authentication" @@ -297,24 +298,25 @@ func InitializeApp() (*App, error) { deletePostProcessorImpl := service2.NewDeletePostProcessorImpl(sugaredLogger) appStoreDeploymentServiceImpl := service2.NewAppStoreDeploymentServiceImpl(sugaredLogger, installedAppRepositoryImpl, installedAppDBServiceImpl, appStoreDeploymentDBServiceImpl, chartGroupDeploymentRepositoryImpl, appStoreApplicationVersionRepositoryImpl, appRepositoryImpl, eaModeDeploymentServiceImpl, eaModeDeploymentServiceImpl, environmentServiceImpl, helmAppServiceImpl, installedAppVersionHistoryRepositoryImpl, environmentVariables, acdConfig, gitOpsConfigReadServiceImpl, deletePostProcessorImpl, appStoreValidatorImpl, deploymentConfigServiceImpl) fluxApplicationServiceImpl := fluxApplication.NewFluxApplicationServiceImpl(sugaredLogger, helmAppServiceImpl, clusterServiceImpl, helmAppClientImpl, pumpImpl) - argoApplicationServiceImpl := argoApplication.NewArgoApplicationServiceImpl(sugaredLogger, clusterRepositoryImpl, k8sServiceImpl, helmUserServiceImpl, helmAppClientImpl, helmAppServiceImpl) - helmAppRestHandlerImpl := client2.NewHelmAppRestHandlerImpl(sugaredLogger, helmAppServiceImpl, enforcerImpl, clusterServiceImpl, enforcerUtilHelmImpl, appStoreDeploymentServiceImpl, installedAppDBServiceImpl, userServiceImpl, attributesServiceImpl, serverEnvConfigServerEnvConfig, fluxApplicationServiceImpl, argoApplicationServiceImpl) - helmAppRouterImpl := client2.NewHelmAppRouterImpl(helmAppRestHandlerImpl) - k8sCommonServiceImpl := k8s2.NewK8sCommonServiceImpl(sugaredLogger, k8sServiceImpl, clusterServiceImpl, argoApplicationServiceImpl) - environmentRestHandlerImpl := cluster2.NewEnvironmentRestHandlerImpl(environmentServiceImpl, sugaredLogger, userServiceImpl, validate, enforcerImpl, deleteServiceImpl, k8sServiceImpl, k8sCommonServiceImpl) - environmentRouterImpl := cluster2.NewEnvironmentRouterImpl(environmentRestHandlerImpl) k8sResourceHistoryRepositoryImpl := repository8.NewK8sResourceHistoryRepositoryImpl(db, sugaredLogger) k8sResourceHistoryServiceImpl := kubernetesResourceAuditLogs.Newk8sResourceHistoryServiceImpl(k8sResourceHistoryRepositoryImpl, sugaredLogger, appRepositoryImpl, environmentRepositoryImpl) + argoApplicationReadServiceImpl := read.NewArgoApplicationReadServiceImpl(sugaredLogger, clusterRepositoryImpl, k8sServiceImpl, helmUserServiceImpl, helmAppClientImpl, helmAppServiceImpl) + k8sCommonServiceImpl := k8s2.NewK8sCommonServiceImpl(sugaredLogger, k8sServiceImpl, clusterServiceImpl, argoApplicationReadServiceImpl) ephemeralContainersRepositoryImpl := repository2.NewEphemeralContainersRepositoryImpl(db, transactionUtilImpl) ephemeralContainerServiceImpl := cluster.NewEphemeralContainerServiceImpl(ephemeralContainersRepositoryImpl, sugaredLogger) - terminalSessionHandlerImpl := terminal.NewTerminalSessionHandlerImpl(environmentServiceImpl, clusterServiceImpl, sugaredLogger, k8sServiceImpl, ephemeralContainerServiceImpl, argoApplicationServiceImpl) - k8sApplicationServiceImpl, err := application.NewK8sApplicationServiceImpl(sugaredLogger, clusterServiceImpl, pumpImpl, helmAppServiceImpl, k8sServiceImpl, acdAuthConfig, k8sResourceHistoryServiceImpl, k8sCommonServiceImpl, terminalSessionHandlerImpl, ephemeralContainerServiceImpl, ephemeralContainersRepositoryImpl, argoApplicationServiceImpl, fluxApplicationServiceImpl) + terminalSessionHandlerImpl := terminal.NewTerminalSessionHandlerImpl(environmentServiceImpl, clusterServiceImpl, sugaredLogger, k8sServiceImpl, ephemeralContainerServiceImpl, argoApplicationReadServiceImpl) + k8sApplicationServiceImpl, err := application.NewK8sApplicationServiceImpl(sugaredLogger, clusterServiceImpl, pumpImpl, helmAppServiceImpl, k8sServiceImpl, acdAuthConfig, k8sResourceHistoryServiceImpl, k8sCommonServiceImpl, terminalSessionHandlerImpl, ephemeralContainerServiceImpl, ephemeralContainersRepositoryImpl, fluxApplicationServiceImpl) if err != nil { return nil, err } + argoApplicationServiceImpl := argoApplication.NewArgoApplicationServiceImpl(sugaredLogger, clusterRepositoryImpl, k8sServiceImpl, helmUserServiceImpl, helmAppClientImpl, helmAppServiceImpl, k8sApplicationServiceImpl, argoApplicationReadServiceImpl) + helmAppRestHandlerImpl := client2.NewHelmAppRestHandlerImpl(sugaredLogger, helmAppServiceImpl, enforcerImpl, clusterServiceImpl, enforcerUtilHelmImpl, appStoreDeploymentServiceImpl, installedAppDBServiceImpl, userServiceImpl, attributesServiceImpl, serverEnvConfigServerEnvConfig, fluxApplicationServiceImpl, argoApplicationServiceImpl) + helmAppRouterImpl := client2.NewHelmAppRouterImpl(helmAppRestHandlerImpl) + environmentRestHandlerImpl := cluster2.NewEnvironmentRestHandlerImpl(environmentServiceImpl, sugaredLogger, userServiceImpl, validate, enforcerImpl, deleteServiceImpl, k8sServiceImpl, k8sCommonServiceImpl) + environmentRouterImpl := cluster2.NewEnvironmentRouterImpl(environmentRestHandlerImpl) ciPipelineRepositoryImpl := pipelineConfig.NewCiPipelineRepositoryImpl(db, sugaredLogger, transactionUtilImpl) 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, environmentVariables, fluxApplicationServiceImpl, argoApplicationServiceImpl) + k8sApplicationRestHandlerImpl := application2.NewK8sApplicationRestHandlerImpl(sugaredLogger, k8sApplicationServiceImpl, pumpImpl, terminalSessionHandlerImpl, enforcerImpl, enforcerUtilHelmImpl, enforcerUtilImpl, helmAppServiceImpl, userServiceImpl, k8sCommonServiceImpl, validate, environmentVariables, fluxApplicationServiceImpl, argoApplicationReadServiceImpl) k8sApplicationRouterImpl := application2.NewK8sApplicationRouterImpl(k8sApplicationRestHandlerImpl) chartRepositoryRestHandlerImpl := chartRepo2.NewChartRepositoryRestHandlerImpl(sugaredLogger, userServiceImpl, chartRepositoryServiceImpl, enforcerImpl, validate, deleteServiceImpl, attributesServiceImpl) chartRepositoryRouterImpl := chartRepo2.NewChartRepositoryRouterImpl(chartRepositoryRestHandlerImpl) @@ -428,7 +430,7 @@ func InitializeApp() (*App, error) { rbacRoleServiceImpl := user.NewRbacRoleServiceImpl(sugaredLogger, rbacRoleDataRepositoryImpl) rbacRoleRestHandlerImpl := user2.NewRbacRoleHandlerImpl(sugaredLogger, validate, rbacRoleServiceImpl, userServiceImpl, enforcerImpl, enforcerUtilImpl) rbacRoleRouterImpl := user2.NewRbacRoleRouterImpl(sugaredLogger, validate, rbacRoleRestHandlerImpl) - argoApplicationRestHandlerImpl := argoApplication2.NewArgoApplicationRestHandlerImpl(argoApplicationServiceImpl, sugaredLogger, enforcerImpl) + argoApplicationRestHandlerImpl := argoApplication2.NewArgoApplicationRestHandlerImpl(argoApplicationServiceImpl, argoApplicationReadServiceImpl, sugaredLogger, enforcerImpl) argoApplicationRouterImpl := argoApplication2.NewArgoApplicationRouterImpl(argoApplicationRestHandlerImpl) fluxApplicationRestHandlerImpl := fluxApplication2.NewFluxApplicationRestHandlerImpl(fluxApplicationServiceImpl, sugaredLogger, enforcerImpl) fluxApplicationRouterImpl := fluxApplication2.NewFluxApplicationRouterImpl(fluxApplicationRestHandlerImpl) diff --git a/pkg/argoApplication/ArgoApplicationService.go b/pkg/argoApplication/ArgoApplicationService.go index e75272b84f0..3f2908c7e88 100644 --- a/pkg/argoApplication/ArgoApplicationService.go +++ b/pkg/argoApplication/ArgoApplicationService.go @@ -18,57 +18,56 @@ package argoApplication import ( "context" - "encoding/json" - "fmt" + "github.com/devtron-labs/common-lib/utils/k8s" + k8sCommonBean "github.com/devtron-labs/common-lib/utils/k8s/commonBean" "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" - - "github.com/devtron-labs/common-lib/utils/k8s" - k8sCommonBean "github.com/devtron-labs/common-lib/utils/k8s/commonBean" "github.com/devtron-labs/devtron/pkg/argoApplication/bean" + "github.com/devtron-labs/devtron/pkg/argoApplication/helper" + "github.com/devtron-labs/devtron/pkg/argoApplication/read" cluster2 "github.com/devtron-labs/devtron/pkg/cluster" clusterRepository "github.com/devtron-labs/devtron/pkg/cluster/repository" + k8s2 "github.com/devtron-labs/devtron/pkg/k8s" + "github.com/devtron-labs/devtron/pkg/k8s/application" "github.com/devtron-labs/devtron/util/argo" "go.uber.org/zap" "k8s.io/apimachinery/pkg/api/errors" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/rest" ) type ArgoApplicationService interface { ListApplications(clusterIds []int) ([]*bean.ArgoApplicationListDto, error) - GetAppDetail(resourceName, resourceNamespace string, clusterId int) (*bean.ArgoApplicationDetailDto, error) - GetServerConfigIfClusterIsNotAddedOnDevtron(resourceResp *k8s.ManifestResponse, restConfig *rest.Config, - clusterWithApplicationObject clusterRepository.Cluster, clusterServerUrlIdMap map[string]int) (*rest.Config, error) - GetClusterConfigFromAllClusters(clusterId int) (*k8s.ClusterConfig, clusterRepository.Cluster, map[string]int, error) - GetRestConfigForExternalArgo(ctx context.Context, clusterId int, externalArgoApplicationName string) (*rest.Config, error) HibernateArgoApplication(ctx context.Context, app *bean.ArgoAppIdentifier, hibernateRequest *openapi.HibernateRequest) ([]*openapi.HibernateStatus, error) UnHibernateArgoApplication(ctx context.Context, app *bean.ArgoAppIdentifier, hibernateRequest *openapi.HibernateRequest) ([]*openapi.HibernateStatus, error) } type ArgoApplicationServiceImpl struct { - logger *zap.SugaredLogger - clusterRepository clusterRepository.ClusterRepository - k8sUtil *k8s.K8sServiceImpl - argoUserService argo.ArgoUserService - helmAppClient gRPC.HelmAppClient - helmAppService service.HelmAppService + logger *zap.SugaredLogger + clusterRepository clusterRepository.ClusterRepository + k8sUtil *k8s.K8sServiceImpl + argoUserService argo.ArgoUserService + helmAppClient gRPC.HelmAppClient + helmAppService service.HelmAppService + k8sApplicationService application.K8sApplicationService + readService read.ArgoApplicationReadService } func NewArgoApplicationServiceImpl(logger *zap.SugaredLogger, clusterRepository clusterRepository.ClusterRepository, k8sUtil *k8s.K8sServiceImpl, argoUserService argo.ArgoUserService, helmAppClient gRPC.HelmAppClient, - helmAppService service.HelmAppService) *ArgoApplicationServiceImpl { + helmAppService service.HelmAppService, + k8sApplicationService application.K8sApplicationService, + readService read.ArgoApplicationReadService) *ArgoApplicationServiceImpl { return &ArgoApplicationServiceImpl{ - logger: logger, - clusterRepository: clusterRepository, - k8sUtil: k8sUtil, - argoUserService: argoUserService, - helmAppService: helmAppService, - helmAppClient: helmAppClient, + logger: logger, + clusterRepository: clusterRepository, + k8sUtil: k8sUtil, + argoUserService: argoUserService, + helmAppService: helmAppService, + helmAppClient: helmAppClient, + k8sApplicationService: k8sApplicationService, + readService: readService, } } @@ -91,6 +90,14 @@ func (impl *ArgoApplicationServiceImpl) ListApplications(clusterIds []int) ([]*b } } + listReq := &k8s2.ResourceRequestBean{ + K8sRequest: &k8s.K8sRequestBean{ + ResourceIdentifier: k8s.ResourceIdentifier{ + Namespace: bean.AllNamespaces, + GroupVersionKind: bean.GvkForArgoApplication, + }, + }, + } // TODO: make goroutine and channel for optimization appListFinal := make([]*bean.ArgoApplicationListDto, 0) for _, cluster := range clusters { @@ -105,7 +112,7 @@ func (impl *ArgoApplicationServiceImpl) ListApplications(clusterIds []int) ([]*b impl.logger.Errorw("error in getting rest config by cluster Id", "err", err, "clusterId", clusterObj.Id) return nil, err } - resp, _, err := impl.k8sUtil.GetResourceList(context.Background(), restConfig, bean.GvkForArgoApplication, bean.AllNamespaces, true, nil) + resp, err := impl.k8sApplicationService.GetResourceListWithRestConfig(context.Background(), "", listReq, nil, restConfig, clusterObj.ClusterName) if err != nil { if errStatus, ok := err.(*errors.StatusError); ok { if errStatus.Status().Code == 404 { @@ -117,352 +124,57 @@ func (impl *ArgoApplicationServiceImpl) ListApplications(clusterIds []int) ([]*b impl.logger.Errorw("error in getting resource list", "err", err) return nil, err } - appLists := getApplicationListDtos(resp.Resources.Object, clusterObj.ClusterName, clusterObj.Id) + appLists := getApplicationListDtos(resp, clusterObj.ClusterName, clusterObj.Id) appListFinal = append(appListFinal, appLists...) } return appListFinal, nil } -func (impl *ArgoApplicationServiceImpl) GetAppDetail(resourceName, resourceNamespace string, clusterId int) (*bean.ArgoApplicationDetailDto, error) { - appDetail := &bean.ArgoApplicationDetailDto{ - ArgoApplicationListDto: &bean.ArgoApplicationListDto{ - Name: resourceName, - Namespace: resourceNamespace, - ClusterId: clusterId, - }, - } - clusters, err := impl.clusterRepository.FindAllActive() - if err != nil { - impl.logger.Errorw("error in getting all active clusters", "err", err) - return nil, err - } - var clusterWithApplicationObject clusterRepository.Cluster - clusterServerUrlIdMap := make(map[string]int, len(clusters)) - for _, cluster := range clusters { - if cluster.Id == clusterId { - clusterWithApplicationObject = cluster - } - clusterServerUrlIdMap[cluster.ServerUrl] = cluster.Id - } - if clusterWithApplicationObject.Id > 0 { - appDetail.ClusterName = clusterWithApplicationObject.ClusterName - } - if clusterWithApplicationObject.IsVirtualCluster { - return appDetail, nil - } else if len(clusterWithApplicationObject.ErrorInConnecting) != 0 { - return nil, fmt.Errorf("error in connecting to cluster") - } - clusterBean := cluster2.GetClusterBean(clusterWithApplicationObject) - clusterConfig := clusterBean.GetClusterConfig() - restConfig, err := impl.k8sUtil.GetRestConfigByCluster(clusterConfig) - if err != nil { - impl.logger.Errorw("error in getting rest config by cluster Id", "err", err, "clusterId", clusterWithApplicationObject.Id) - return nil, err - } - resp, err := impl.k8sUtil.GetResource(context.Background(), resourceNamespace, resourceName, bean.GvkForArgoApplication, restConfig) - if err != nil { - impl.logger.Errorw("error in getting resource list", "err", err) - return nil, err - } - var destinationServer string - var argoManagedResources []*bean.ArgoManagedResource - if resp != nil && resp.Manifest.Object != nil { - appDetail.Manifest = resp.Manifest.Object - appDetail.HealthStatus, appDetail.SyncStatus, destinationServer, argoManagedResources = - getHealthSyncStatusDestinationServerAndManagedResourcesForArgoK8sRawObject(resp.Manifest.Object) - } - appDeployedOnClusterId := 0 - if destinationServer == k8s.DefaultClusterUrl { - appDeployedOnClusterId = clusterWithApplicationObject.Id - } else if clusterIdFromMap, ok := clusterServerUrlIdMap[destinationServer]; ok { - appDeployedOnClusterId = clusterIdFromMap - } - var configOfClusterWhereAppIsDeployed bean.ArgoClusterConfigObj - if appDeployedOnClusterId < 1 { - // cluster is not added on devtron, need to get server config from secret which argo-cd saved - coreV1Client, err := impl.k8sUtil.GetCoreV1ClientByRestConfig(restConfig) - secrets, err := coreV1Client.Secrets(bean.AllNamespaces).List(context.Background(), v1.ListOptions{ - LabelSelector: labels.SelectorFromSet(labels.Set{"argocd.argoproj.io/secret-type": "cluster"}).String(), - }) - if err != nil { - impl.logger.Errorw("error in getting resource list, secrets", "err", err) - return nil, err - } - for _, secret := range secrets.Items { - if secret.Data != nil { - if val, ok := secret.Data["server"]; ok { - if string(val) == destinationServer { - if config, ok := secret.Data["config"]; ok { - err = json.Unmarshal(config, &configOfClusterWhereAppIsDeployed) - if err != nil { - impl.logger.Errorw("error in unmarshaling", "err", err) - return nil, err - } - break - } - } - } - } - } - } - resourceTreeResp, err := impl.getResourceTreeForExternalCluster(appDeployedOnClusterId, destinationServer, configOfClusterWhereAppIsDeployed, argoManagedResources) - if err != nil { - impl.logger.Errorw("error in getting resource tree response", "err", err) - return nil, err - } - appDetail.ResourceTree = resourceTreeResp - return appDetail, nil -} - -func (impl *ArgoApplicationServiceImpl) getResourceTreeForExternalCluster(clusterId int, destinationServer string, - configOfClusterWhereAppIsDeployed bean.ArgoClusterConfigObj, argoManagedResources []*bean.ArgoManagedResource) (*gRPC.ResourceTreeResponse, error) { - var resources []*gRPC.ExternalResourceDetail - for _, argoManagedResource := range argoManagedResources { - resources = append(resources, &gRPC.ExternalResourceDetail{ - Group: argoManagedResource.Group, - Kind: argoManagedResource.Kind, - Version: argoManagedResource.Version, - Name: argoManagedResource.Name, - Namespace: argoManagedResource.Namespace, - }) - } - var clusterConfigOfClusterWhereAppIsDeployed *gRPC.ClusterConfig - if len(configOfClusterWhereAppIsDeployed.BearerToken) > 0 { - clusterConfigOfClusterWhereAppIsDeployed = &gRPC.ClusterConfig{ - ApiServerUrl: destinationServer, - Token: configOfClusterWhereAppIsDeployed.BearerToken, - InsecureSkipTLSVerify: configOfClusterWhereAppIsDeployed.TlsClientConfig.Insecure, - KeyData: configOfClusterWhereAppIsDeployed.TlsClientConfig.KeyData, - CaData: configOfClusterWhereAppIsDeployed.TlsClientConfig.CaData, - CertData: configOfClusterWhereAppIsDeployed.TlsClientConfig.CertData, - } - } - resourceTreeResp, err := impl.helmAppService.GetResourceTreeForExternalResources(context.Background(), clusterId, clusterConfigOfClusterWhereAppIsDeployed, resources) - if err != nil { - impl.logger.Errorw("error in getting resource tree for external resources", "err", err) - return nil, err - } - return resourceTreeResp, nil -} - -func getApplicationListDtos(manifestObj map[string]interface{}, clusterName string, clusterId int) []*bean.ArgoApplicationListDto { +func getApplicationListDtos(resp *k8s.ClusterResourceListMap, clusterName string, clusterId int) []*bean.ArgoApplicationListDto { appLists := make([]*bean.ArgoApplicationListDto, 0) - // map of keys and index in row cells, initially set as 0 will be updated by object - keysToBeFetchedFromColumnDefinitions := map[string]int{k8sCommonBean.K8sResourceColumnDefinitionName: 0, - k8sCommonBean.K8sResourceColumnDefinitionHealthStatus: 0, k8sCommonBean.K8sResourceColumnDefinitionSyncStatus: 0} - keysToBeFetchedFromRawObject := []string{k8sCommonBean.K8sClusterResourceNamespaceKey} - - columnsDataRaw := manifestObj[k8sCommonBean.K8sClusterResourceColumnDefinitionKey] - if columnsDataRaw != nil { - columnsData := columnsDataRaw.([]interface{}) - for i, columnData := range columnsData { - columnDataMap := columnData.(map[string]interface{}) - for key := range keysToBeFetchedFromColumnDefinitions { - if columnDataMap[k8sCommonBean.K8sClusterResourceNameKey] == key { - keysToBeFetchedFromColumnDefinitions[key] = i - } + if resp != nil { + appLists = make([]*bean.ArgoApplicationListDto, len(resp.Data)) + for i, rowData := range resp.Data { + if rowData == nil { + continue } - } - } - - rowsDataRaw := manifestObj[k8sCommonBean.K8sClusterResourceRowsKey] - if rowsDataRaw != nil { - rowsData := rowsDataRaw.([]interface{}) - for _, rowData := range rowsData { appListDto := &bean.ArgoApplicationListDto{ ClusterId: clusterId, ClusterName: clusterName, } - rowDataMap := rowData.(map[string]interface{}) - rowCells := rowDataMap[k8sCommonBean.K8sClusterResourceCellKey].([]interface{}) - for key, value := range keysToBeFetchedFromColumnDefinitions { - resolvedValueFromRowCell := rowCells[value].(string) - switch key { - case k8sCommonBean.K8sResourceColumnDefinitionName: - appListDto.Name = resolvedValueFromRowCell - case k8sCommonBean.K8sResourceColumnDefinitionSyncStatus: - appListDto.SyncStatus = resolvedValueFromRowCell - case k8sCommonBean.K8sResourceColumnDefinitionHealthStatus: - appListDto.HealthStatus = resolvedValueFromRowCell + if rowData[k8sCommonBean.K8sClusterResourceNameKey] != nil { + if nameStr, ok := rowData[k8sCommonBean.K8sClusterResourceNameKey].(string); ok { + appListDto.Name = nameStr } } - rowObject := rowDataMap[k8sCommonBean.K8sClusterResourceObjectKey].(map[string]interface{}) - for _, key := range keysToBeFetchedFromRawObject { - switch key { - case k8sCommonBean.K8sClusterResourceNamespaceKey: - metadata := rowObject[k8sCommonBean.K8sClusterResourceMetadataKey].(map[string]interface{}) - appListDto.Namespace = metadata[k8sCommonBean.K8sClusterResourceNamespaceKey].(string) + if rowData[k8sCommonBean.K8sResourceColumnDefinitionSyncStatus] != nil { + if syncStatusStr, ok := rowData[k8sCommonBean.K8sResourceColumnDefinitionSyncStatus].(string); ok { + appListDto.SyncStatus = syncStatusStr } } - - appLists = append(appLists, appListDto) - } - } - return appLists -} - -func getHealthSyncStatusDestinationServerAndManagedResourcesForArgoK8sRawObject(obj map[string]interface{}) (string, - string, string, []*bean.ArgoManagedResource) { - var healthStatus, syncStatus, destinationServer string - argoManagedResources := make([]*bean.ArgoManagedResource, 0) - if specObjRaw, ok := obj[k8sCommonBean.Spec]; ok { - specObj := specObjRaw.(map[string]interface{}) - if destinationObjRaw, ok2 := specObj[bean.Destination]; ok2 { - destinationObj := destinationObjRaw.(map[string]interface{}) - if destinationServerIf, ok3 := destinationObj[bean.Server]; ok3 { - destinationServer = destinationServerIf.(string) - } - } - } - if statusObjRaw, ok := obj[k8sCommonBean.K8sClusterResourceStatusKey]; ok { - statusObj := statusObjRaw.(map[string]interface{}) - if healthObjRaw, ok2 := statusObj[k8sCommonBean.K8sClusterResourceHealthKey]; ok2 { - healthObj := healthObjRaw.(map[string]interface{}) - if healthStatusIf, ok3 := healthObj[k8sCommonBean.K8sClusterResourceStatusKey]; ok3 { - healthStatus = healthStatusIf.(string) - } - } - if syncObjRaw, ok2 := statusObj[k8sCommonBean.K8sClusterResourceSyncKey]; ok2 { - syncObj := syncObjRaw.(map[string]interface{}) - if syncStatusIf, ok3 := syncObj[k8sCommonBean.K8sClusterResourceStatusKey]; ok3 { - syncStatus = syncStatusIf.(string) - } - } - if resourceObjsRaw, ok2 := statusObj[k8sCommonBean.K8sClusterResourceResourcesKey]; ok2 { - resourceObjs := resourceObjsRaw.([]interface{}) - argoManagedResources = make([]*bean.ArgoManagedResource, 0, len(resourceObjs)) - for _, resourceObjRaw := range resourceObjs { - argoManagedResource := &bean.ArgoManagedResource{} - resourceObj := resourceObjRaw.(map[string]interface{}) - if groupRaw, ok := resourceObj[k8sCommonBean.K8sClusterResourceGroupKey]; ok { - argoManagedResource.Group = groupRaw.(string) - } - if kindRaw, ok := resourceObj[k8sCommonBean.K8sClusterResourceKindKey]; ok { - argoManagedResource.Kind = kindRaw.(string) + if rowData[k8sCommonBean.K8sResourceColumnDefinitionHealthStatus] != nil { + if healthStatusStr, ok := rowData[k8sCommonBean.K8sResourceColumnDefinitionHealthStatus].(string); ok { + appListDto.HealthStatus = healthStatusStr } - if versionRaw, ok := resourceObj[k8sCommonBean.K8sClusterResourceVersionKey]; ok { - argoManagedResource.Version = versionRaw.(string) - } - if nameRaw, ok := resourceObj[k8sCommonBean.K8sClusterResourceMetadataNameKey]; ok { - argoManagedResource.Name = nameRaw.(string) - } - if namespaceRaw, ok := resourceObj[k8sCommonBean.K8sClusterResourceNamespaceKey]; ok { - argoManagedResource.Namespace = namespaceRaw.(string) - } - argoManagedResources = append(argoManagedResources, argoManagedResource) } - } - } - return healthStatus, syncStatus, destinationServer, argoManagedResources -} - -func (impl *ArgoApplicationServiceImpl) GetServerConfigIfClusterIsNotAddedOnDevtron(resourceResp *k8s.ManifestResponse, restConfig *rest.Config, - clusterWithApplicationObject clusterRepository.Cluster, clusterServerUrlIdMap map[string]int) (*rest.Config, error) { - var destinationServer string - if resourceResp != nil && resourceResp.Manifest.Object != nil { - _, _, destinationServer, _ = - getHealthSyncStatusDestinationServerAndManagedResourcesForArgoK8sRawObject(resourceResp.Manifest.Object) - } - appDeployedOnClusterId := 0 - if destinationServer == k8s.DefaultClusterUrl { - appDeployedOnClusterId = clusterWithApplicationObject.Id - } else if clusterIdFromMap, ok := clusterServerUrlIdMap[destinationServer]; ok { - appDeployedOnClusterId = clusterIdFromMap - } - var configOfClusterWhereAppIsDeployed *bean.ArgoClusterConfigObj - if appDeployedOnClusterId < 1 { - // cluster is not added on devtron, need to get server config from secret which argo-cd saved - coreV1Client, err := impl.k8sUtil.GetCoreV1ClientByRestConfig(restConfig) - secrets, err := coreV1Client.Secrets(bean.AllNamespaces).List(context.Background(), v1.ListOptions{ - LabelSelector: labels.SelectorFromSet(labels.Set{"argocd.argoproj.io/secret-type": "cluster"}).String(), - }) - if err != nil { - impl.logger.Errorw("error in getting resource list, secrets", "err", err) - return nil, err - } - for _, secret := range secrets.Items { - if secret.Data != nil { - if val, ok := secret.Data[bean.Server]; ok { - if string(val) == destinationServer { - if config, ok := secret.Data[bean.Config]; ok { - err = json.Unmarshal(config, &configOfClusterWhereAppIsDeployed) - if err != nil { - impl.logger.Errorw("error in unmarshaling", "err", err) - return nil, err - } - break - } - } + if rowData[k8sCommonBean.K8sClusterResourceNamespaceKey] != nil { + if namespaceStr, ok := rowData[k8sCommonBean.K8sClusterResourceNamespaceKey].(string); ok { + appListDto.Namespace = namespaceStr } } - } - if configOfClusterWhereAppIsDeployed != nil { - restConfig.Host = destinationServer - restConfig.TLSClientConfig = rest.TLSClientConfig{ - Insecure: configOfClusterWhereAppIsDeployed.TlsClientConfig.Insecure, - KeyFile: configOfClusterWhereAppIsDeployed.TlsClientConfig.KeyData, - CAFile: configOfClusterWhereAppIsDeployed.TlsClientConfig.CaData, - CertFile: configOfClusterWhereAppIsDeployed.TlsClientConfig.CertData, - } - restConfig.BearerToken = configOfClusterWhereAppIsDeployed.BearerToken + appLists[i] = appListDto } } - return restConfig, nil -} - -func (impl *ArgoApplicationServiceImpl) GetClusterConfigFromAllClusters(clusterId int) (*k8s.ClusterConfig, clusterRepository.Cluster, map[string]int, error) { - clusters, err := impl.clusterRepository.FindAllActive() - var clusterWithApplicationObject clusterRepository.Cluster - if err != nil { - impl.logger.Errorw("error in getting all active clusters", "err", err) - return nil, clusterWithApplicationObject, nil, err - } - clusterServerUrlIdMap := make(map[string]int, len(clusters)) - for _, cluster := range clusters { - if cluster.Id == clusterId { - clusterWithApplicationObject = cluster - } - clusterServerUrlIdMap[cluster.ServerUrl] = cluster.Id - } - if len(clusterWithApplicationObject.ErrorInConnecting) != 0 { - return nil, clusterWithApplicationObject, nil, fmt.Errorf("error in connecting to cluster") - } - clusterBean := cluster2.GetClusterBean(clusterWithApplicationObject) - clusterConfig := clusterBean.GetClusterConfig() - return clusterConfig, clusterWithApplicationObject, clusterServerUrlIdMap, err -} - -func (impl *ArgoApplicationServiceImpl) GetRestConfigForExternalArgo(ctx context.Context, clusterId int, externalArgoApplicationName string) (*rest.Config, error) { - clusterConfig, clusterWithApplicationObject, clusterServerUrlIdMap, err := impl.GetClusterConfigFromAllClusters(clusterId) - if err != nil { - impl.logger.Errorw("error in getting cluster config", "err", err, "clusterId", clusterId) - return nil, err - } - restConfig, err := impl.k8sUtil.GetRestConfigByCluster(clusterConfig) - if err != nil { - impl.logger.Errorw("error in getting rest config", "err", err, "clusterId", clusterId) - return nil, err - } - resourceResp, err := impl.k8sUtil.GetResource(ctx, bean.DevtronCDNamespae, externalArgoApplicationName, bean.GvkForArgoApplication, restConfig) - if err != nil { - impl.logger.Errorw("not on external cluster", "err", err, "externalArgoApplicationName", externalArgoApplicationName) - return nil, err - } - restConfig, err = impl.GetServerConfigIfClusterIsNotAddedOnDevtron(resourceResp, restConfig, clusterWithApplicationObject, clusterServerUrlIdMap) - if err != nil { - impl.logger.Errorw("error in getting server config", "err", err, "cluster with application object", clusterWithApplicationObject) - return nil, err - } - return restConfig, nil + return appLists } func (impl *ArgoApplicationServiceImpl) HibernateArgoApplication(ctx context.Context, app *bean.ArgoAppIdentifier, hibernateRequest *openapi.HibernateRequest) ([]*openapi.HibernateStatus, error) { - _, clusterBean, _, err := impl.GetClusterConfigFromAllClusters(app.ClusterId) + _, clusterBean, _, err := impl.readService.GetClusterConfigFromAllClusters(app.ClusterId) if err != nil { impl.logger.Errorw("HibernateArgoApplication", "error in getting the cluster config", err, "clusterId", app.ClusterId, "appName", app.AppName) return nil, err } - conf := ConvertClusterBeanToGrpcConfig(clusterBean) + conf := helper.ConvertClusterBeanToGrpcConfig(clusterBean) req := service.HibernateReqAdaptor(hibernateRequest) req.ClusterConfig = conf @@ -476,12 +188,12 @@ func (impl *ArgoApplicationServiceImpl) HibernateArgoApplication(ctx context.Con } func (impl *ArgoApplicationServiceImpl) UnHibernateArgoApplication(ctx context.Context, app *bean.ArgoAppIdentifier, hibernateRequest *openapi.HibernateRequest) ([]*openapi.HibernateStatus, error) { - _, clusterBean, _, err := impl.GetClusterConfigFromAllClusters(app.ClusterId) + _, clusterBean, _, err := impl.readService.GetClusterConfigFromAllClusters(app.ClusterId) if err != nil { impl.logger.Errorw("HibernateArgoApplication", "error in getting the cluster config", err, "clusterId", app.ClusterId, "appName", app.AppName) return nil, err } - conf := ConvertClusterBeanToGrpcConfig(clusterBean) + conf := helper.ConvertClusterBeanToGrpcConfig(clusterBean) req := service.HibernateReqAdaptor(hibernateRequest) req.ClusterConfig = conf diff --git a/pkg/argoApplication/helper.go b/pkg/argoApplication/helper/helper.go similarity index 98% rename from pkg/argoApplication/helper.go rename to pkg/argoApplication/helper/helper.go index 97a80e2c4de..d931b078083 100644 --- a/pkg/argoApplication/helper.go +++ b/pkg/argoApplication/helper/helper.go @@ -1,4 +1,4 @@ -package argoApplication +package helper import ( "fmt" diff --git a/pkg/argoApplication/read/ArgoApplicationReadService.go b/pkg/argoApplication/read/ArgoApplicationReadService.go new file mode 100644 index 00000000000..4a815e99b44 --- /dev/null +++ b/pkg/argoApplication/read/ArgoApplicationReadService.go @@ -0,0 +1,402 @@ +package read + +import ( + "context" + "encoding/json" + "fmt" + "github.com/devtron-labs/common-lib/utils/k8s" + k8sCommonBean "github.com/devtron-labs/common-lib/utils/k8s/commonBean" + "github.com/devtron-labs/devtron/api/helm-app/gRPC" + "github.com/devtron-labs/devtron/api/helm-app/service" + "github.com/devtron-labs/devtron/pkg/argoApplication/bean" + cluster2 "github.com/devtron-labs/devtron/pkg/cluster" + clusterRepository "github.com/devtron-labs/devtron/pkg/cluster/repository" + clientErrors "github.com/devtron-labs/devtron/pkg/errors" + "github.com/devtron-labs/devtron/util/argo" + "go.uber.org/zap" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/rest" +) + +type ArgoApplicationReadService interface { + GetRestConfigForExternalArgo(ctx context.Context, clusterId int, externalArgoApplicationName string) (*rest.Config, error) + GetClusterConfigFromAllClusters(clusterId int) (*k8s.ClusterConfig, clusterRepository.Cluster, map[string]int, error) + ValidateArgoResourceRequest(ctx context.Context, appIdentifier *bean.ArgoAppIdentifier, request *k8s.K8sRequestBean) (bool, error) + GetAppDetail(resourceName, resourceNamespace string, clusterId int) (*bean.ArgoApplicationDetailDto, error) +} + +type ArgoApplicationReadServiceImpl struct { + logger *zap.SugaredLogger + clusterRepository clusterRepository.ClusterRepository + k8sUtil *k8s.K8sServiceImpl + argoUserService argo.ArgoUserService + helmAppClient gRPC.HelmAppClient + helmAppService service.HelmAppService +} + +func NewArgoApplicationReadServiceImpl(logger *zap.SugaredLogger, + clusterRepository clusterRepository.ClusterRepository, + k8sUtil *k8s.K8sServiceImpl, + argoUserService argo.ArgoUserService, helmAppClient gRPC.HelmAppClient, + helmAppService service.HelmAppService) *ArgoApplicationReadServiceImpl { + return &ArgoApplicationReadServiceImpl{ + logger: logger, + clusterRepository: clusterRepository, + k8sUtil: k8sUtil, + argoUserService: argoUserService, + helmAppService: helmAppService, + helmAppClient: helmAppClient, + } + +} + +func (impl *ArgoApplicationReadServiceImpl) GetRestConfigForExternalArgo(ctx context.Context, clusterId int, externalArgoApplicationName string) (*rest.Config, error) { + clusterConfig, clusterWithApplicationObject, clusterServerUrlIdMap, err := impl.GetClusterConfigFromAllClusters(clusterId) + if err != nil { + impl.logger.Errorw("error in getting cluster config", "err", err, "clusterId", clusterId) + return nil, err + } + restConfig, err := impl.k8sUtil.GetRestConfigByCluster(clusterConfig) + if err != nil { + impl.logger.Errorw("error in getting rest config", "err", err, "clusterId", clusterId) + return nil, err + } + resourceResp, err := impl.k8sUtil.GetResource(ctx, bean.DevtronCDNamespae, externalArgoApplicationName, bean.GvkForArgoApplication, restConfig) + if err != nil { + impl.logger.Errorw("not on external cluster", "err", err, "externalArgoApplicationName", externalArgoApplicationName) + return nil, err + } + restConfig, err = impl.GetServerConfigIfClusterIsNotAddedOnDevtron(resourceResp, restConfig, clusterWithApplicationObject, clusterServerUrlIdMap) + if err != nil { + impl.logger.Errorw("error in getting server config", "err", err, "cluster with application object", clusterWithApplicationObject) + return nil, err + } + return restConfig, nil +} + +func (impl *ArgoApplicationReadServiceImpl) GetServerConfigIfClusterIsNotAddedOnDevtron(resourceResp *k8s.ManifestResponse, restConfig *rest.Config, + clusterWithApplicationObject clusterRepository.Cluster, clusterServerUrlIdMap map[string]int) (*rest.Config, error) { + var destinationServer string + if resourceResp != nil && resourceResp.Manifest.Object != nil { + _, _, destinationServer, _ = + getHealthSyncStatusDestinationServerAndManagedResourcesForArgoK8sRawObject(resourceResp.Manifest.Object) + } + appDeployedOnClusterId := 0 + if destinationServer == k8s.DefaultClusterUrl { + appDeployedOnClusterId = clusterWithApplicationObject.Id + } else if clusterIdFromMap, ok := clusterServerUrlIdMap[destinationServer]; ok { + appDeployedOnClusterId = clusterIdFromMap + } + var configOfClusterWhereAppIsDeployed *bean.ArgoClusterConfigObj + if appDeployedOnClusterId < 1 { + // cluster is not added on devtron, need to get server config from secret which argo-cd saved + coreV1Client, err := impl.k8sUtil.GetCoreV1ClientByRestConfig(restConfig) + secrets, err := coreV1Client.Secrets(bean.AllNamespaces).List(context.Background(), v1.ListOptions{ + LabelSelector: labels.SelectorFromSet(labels.Set{"argocd.argoproj.io/secret-type": "cluster"}).String(), + }) + if err != nil { + impl.logger.Errorw("error in getting resource list, secrets", "err", err) + return nil, err + } + for _, secret := range secrets.Items { + if secret.Data != nil { + if val, ok := secret.Data[bean.Server]; ok { + if string(val) == destinationServer { + if config, ok := secret.Data[bean.Config]; ok { + err = json.Unmarshal(config, &configOfClusterWhereAppIsDeployed) + if err != nil { + impl.logger.Errorw("error in unmarshaling", "err", err) + return nil, err + } + break + } + } + } + } + } + if configOfClusterWhereAppIsDeployed != nil { + restConfig, err = impl.k8sUtil.GetRestConfigByCluster(&k8s.ClusterConfig{ + Host: destinationServer, + BearerToken: configOfClusterWhereAppIsDeployed.BearerToken, + InsecureSkipTLSVerify: configOfClusterWhereAppIsDeployed.TlsClientConfig.Insecure, + KeyData: configOfClusterWhereAppIsDeployed.TlsClientConfig.KeyData, + CAData: configOfClusterWhereAppIsDeployed.TlsClientConfig.CaData, + CertData: configOfClusterWhereAppIsDeployed.TlsClientConfig.CertData, + }) + if err != nil { + impl.logger.Errorw("error in GetRestConfigByCluster, GetServerConfigIfClusterIsNotAddedOnDevtron", "err", err, "serverUrl", destinationServer) + return nil, err + } + } + } + return restConfig, nil +} + +func (impl *ArgoApplicationReadServiceImpl) GetClusterConfigFromAllClusters(clusterId int) (*k8s.ClusterConfig, clusterRepository.Cluster, map[string]int, error) { + clusters, err := impl.clusterRepository.FindAllActive() + var clusterWithApplicationObject clusterRepository.Cluster + if err != nil { + impl.logger.Errorw("error in getting all active clusters", "err", err) + return nil, clusterWithApplicationObject, nil, err + } + clusterServerUrlIdMap := make(map[string]int, len(clusters)) + for _, cluster := range clusters { + if cluster.Id == clusterId { + clusterWithApplicationObject = cluster + } + clusterServerUrlIdMap[cluster.ServerUrl] = cluster.Id + } + if len(clusterWithApplicationObject.ErrorInConnecting) != 0 { + return nil, clusterWithApplicationObject, nil, fmt.Errorf("error in connecting to cluster") + } + clusterBean := cluster2.GetClusterBean(clusterWithApplicationObject) + clusterConfig := clusterBean.GetClusterConfig() + return clusterConfig, clusterWithApplicationObject, clusterServerUrlIdMap, err +} + +func (impl *ArgoApplicationReadServiceImpl) GetAppDetail(resourceName, resourceNamespace string, clusterId int) (*bean.ArgoApplicationDetailDto, error) { + appDetail := &bean.ArgoApplicationDetailDto{ + ArgoApplicationListDto: &bean.ArgoApplicationListDto{ + Name: resourceName, + Namespace: resourceNamespace, + ClusterId: clusterId, + }, + } + clusters, err := impl.clusterRepository.FindAllActive() + if err != nil { + impl.logger.Errorw("error in getting all active clusters", "err", err) + return nil, err + } + var clusterWithApplicationObject clusterRepository.Cluster + clusterServerUrlIdMap := make(map[string]int, len(clusters)) + for _, cluster := range clusters { + if cluster.Id == clusterId { + clusterWithApplicationObject = cluster + } + clusterServerUrlIdMap[cluster.ServerUrl] = cluster.Id + } + if clusterWithApplicationObject.Id > 0 { + appDetail.ClusterName = clusterWithApplicationObject.ClusterName + } + if clusterWithApplicationObject.IsVirtualCluster { + return appDetail, nil + } else if len(clusterWithApplicationObject.ErrorInConnecting) != 0 { + return nil, fmt.Errorf("error in connecting to cluster") + } + clusterBean := cluster2.GetClusterBean(clusterWithApplicationObject) + clusterConfig := clusterBean.GetClusterConfig() + restConfig, err := impl.k8sUtil.GetRestConfigByCluster(clusterConfig) + if err != nil { + impl.logger.Errorw("error in getting rest config by cluster Id", "err", err, "clusterId", clusterWithApplicationObject.Id) + return nil, err + } + resp, err := impl.k8sUtil.GetResource(context.Background(), resourceNamespace, resourceName, bean.GvkForArgoApplication, restConfig) + if err != nil { + impl.logger.Errorw("error in getting resource list", "err", err) + return nil, err + } + var destinationServer string + var argoManagedResources []*bean.ArgoManagedResource + if resp != nil && resp.Manifest.Object != nil { + appDetail.Manifest = resp.Manifest.Object + appDetail.HealthStatus, appDetail.SyncStatus, destinationServer, argoManagedResources = + getHealthSyncStatusDestinationServerAndManagedResourcesForArgoK8sRawObject(resp.Manifest.Object) + } + appDeployedOnClusterId := 0 + if destinationServer == k8s.DefaultClusterUrl { + appDeployedOnClusterId = clusterWithApplicationObject.Id + } else if clusterIdFromMap, ok := clusterServerUrlIdMap[destinationServer]; ok { + appDeployedOnClusterId = clusterIdFromMap + } + var configOfClusterWhereAppIsDeployed bean.ArgoClusterConfigObj + if appDeployedOnClusterId < 1 { + // cluster is not added on devtron, need to get server config from secret which argo-cd saved + coreV1Client, err := impl.k8sUtil.GetCoreV1ClientByRestConfig(restConfig) + secrets, err := coreV1Client.Secrets(bean.AllNamespaces).List(context.Background(), v1.ListOptions{ + LabelSelector: labels.SelectorFromSet(labels.Set{"argocd.argoproj.io/secret-type": "cluster"}).String(), + }) + if err != nil { + impl.logger.Errorw("error in getting resource list, secrets", "err", err) + return nil, err + } + for _, secret := range secrets.Items { + if secret.Data != nil { + if val, ok := secret.Data["server"]; ok { + if string(val) == destinationServer { + if config, ok := secret.Data["config"]; ok { + err = json.Unmarshal(config, &configOfClusterWhereAppIsDeployed) + if err != nil { + impl.logger.Errorw("error in unmarshaling", "err", err) + return nil, err + } + break + } + } + } + } + } + } + resourceTreeResp, err := impl.getResourceTreeForExternalCluster(appDeployedOnClusterId, destinationServer, configOfClusterWhereAppIsDeployed, argoManagedResources) + if err != nil { + impl.logger.Errorw("error in getting resource tree response", "err", err) + return nil, err + } + appDetail.ResourceTree = resourceTreeResp + return appDetail, nil +} + +func (impl *ArgoApplicationReadServiceImpl) getResourceTreeForExternalCluster(clusterId int, destinationServer string, + configOfClusterWhereAppIsDeployed bean.ArgoClusterConfigObj, argoManagedResources []*bean.ArgoManagedResource) (*gRPC.ResourceTreeResponse, error) { + var resources []*gRPC.ExternalResourceDetail + for _, argoManagedResource := range argoManagedResources { + resources = append(resources, &gRPC.ExternalResourceDetail{ + Group: argoManagedResource.Group, + Kind: argoManagedResource.Kind, + Version: argoManagedResource.Version, + Name: argoManagedResource.Name, + Namespace: argoManagedResource.Namespace, + }) + } + var clusterConfigOfClusterWhereAppIsDeployed *gRPC.ClusterConfig + if len(configOfClusterWhereAppIsDeployed.BearerToken) > 0 { + clusterConfigOfClusterWhereAppIsDeployed = &gRPC.ClusterConfig{ + ApiServerUrl: destinationServer, + Token: configOfClusterWhereAppIsDeployed.BearerToken, + InsecureSkipTLSVerify: configOfClusterWhereAppIsDeployed.TlsClientConfig.Insecure, + KeyData: configOfClusterWhereAppIsDeployed.TlsClientConfig.KeyData, + CaData: configOfClusterWhereAppIsDeployed.TlsClientConfig.CaData, + CertData: configOfClusterWhereAppIsDeployed.TlsClientConfig.CertData, + } + } + resourceTreeResp, err := impl.helmAppService.GetResourceTreeForExternalResources(context.Background(), clusterId, clusterConfigOfClusterWhereAppIsDeployed, resources) + if err != nil { + impl.logger.Errorw("error in getting resource tree for external resources", "err", err) + return nil, err + } + return resourceTreeResp, nil +} + +func (impl *ArgoApplicationReadServiceImpl) ValidateArgoResourceRequest(ctx context.Context, appIdentifier *bean.ArgoAppIdentifier, request *k8s.K8sRequestBean) (bool, error) { + app, err := impl.GetAppDetail(appIdentifier.AppName, appIdentifier.Namespace, appIdentifier.ClusterId) + if err != nil { + impl.logger.Errorw("error in getting app detail", "err", err, "appDetails", appIdentifier) + apiError := clientErrors.ConvertToApiError(err) + if apiError != nil { + err = apiError + } + return false, err + } + + valid := false + + for _, node := range app.ResourceTree.Nodes { + nodeDetails := k8s.ResourceIdentifier{ + Name: node.Name, + Namespace: node.Namespace, + GroupVersionKind: schema.GroupVersionKind{ + Group: node.Group, + Version: node.Version, + Kind: node.Kind, + }, + } + if nodeDetails == request.ResourceIdentifier { + valid = true + break + } + } + appDetail := &gRPC.AppDetail{ + ResourceTreeResponse: app.ResourceTree, + } + return validateContainerNameIfReqd(valid, request, appDetail), nil +} + +func validateContainerNameIfReqd(valid bool, request *k8s.K8sRequestBean, app *gRPC.AppDetail) bool { + if !valid { + requestContainerName := request.PodLogsRequest.ContainerName + podName := request.ResourceIdentifier.Name + for _, pod := range app.ResourceTreeResponse.PodMetadata { + if pod.Name == podName { + + // finding the container name in main Containers + for _, container := range pod.Containers { + if container == requestContainerName { + return true + } + } + + // finding the container name in init containers + for _, initContainer := range pod.InitContainers { + if initContainer == requestContainerName { + return true + } + } + + // finding the container name in ephemeral containers + for _, ephemeralContainer := range pod.EphemeralContainers { + if ephemeralContainer.Name == requestContainerName { + return true + } + } + + } + } + } + return valid +} + +func getHealthSyncStatusDestinationServerAndManagedResourcesForArgoK8sRawObject(obj map[string]interface{}) (string, + string, string, []*bean.ArgoManagedResource) { + var healthStatus, syncStatus, destinationServer string + argoManagedResources := make([]*bean.ArgoManagedResource, 0) + if specObjRaw, ok := obj[k8sCommonBean.Spec]; ok { + specObj := specObjRaw.(map[string]interface{}) + if destinationObjRaw, ok2 := specObj[bean.Destination]; ok2 { + destinationObj := destinationObjRaw.(map[string]interface{}) + if destinationServerIf, ok3 := destinationObj[bean.Server]; ok3 { + destinationServer = destinationServerIf.(string) + } + } + } + if statusObjRaw, ok := obj[k8sCommonBean.K8sClusterResourceStatusKey]; ok { + statusObj := statusObjRaw.(map[string]interface{}) + if healthObjRaw, ok2 := statusObj[k8sCommonBean.K8sClusterResourceHealthKey]; ok2 { + healthObj := healthObjRaw.(map[string]interface{}) + if healthStatusIf, ok3 := healthObj[k8sCommonBean.K8sClusterResourceStatusKey]; ok3 { + healthStatus = healthStatusIf.(string) + } + } + if syncObjRaw, ok2 := statusObj[k8sCommonBean.K8sClusterResourceSyncKey]; ok2 { + syncObj := syncObjRaw.(map[string]interface{}) + if syncStatusIf, ok3 := syncObj[k8sCommonBean.K8sClusterResourceStatusKey]; ok3 { + syncStatus = syncStatusIf.(string) + } + } + if resourceObjsRaw, ok2 := statusObj[k8sCommonBean.K8sClusterResourceResourcesKey]; ok2 { + resourceObjs := resourceObjsRaw.([]interface{}) + argoManagedResources = make([]*bean.ArgoManagedResource, 0, len(resourceObjs)) + for _, resourceObjRaw := range resourceObjs { + argoManagedResource := &bean.ArgoManagedResource{} + resourceObj := resourceObjRaw.(map[string]interface{}) + if groupRaw, ok := resourceObj[k8sCommonBean.K8sClusterResourceGroupKey]; ok { + argoManagedResource.Group = groupRaw.(string) + } + if kindRaw, ok := resourceObj[k8sCommonBean.K8sClusterResourceKindKey]; ok { + argoManagedResource.Kind = kindRaw.(string) + } + if versionRaw, ok := resourceObj[k8sCommonBean.K8sClusterResourceVersionKey]; ok { + argoManagedResource.Version = versionRaw.(string) + } + if nameRaw, ok := resourceObj[k8sCommonBean.K8sClusterResourceMetadataNameKey]; ok { + argoManagedResource.Name = nameRaw.(string) + } + if namespaceRaw, ok := resourceObj[k8sCommonBean.K8sClusterResourceNamespaceKey]; ok { + argoManagedResource.Namespace = namespaceRaw.(string) + } + argoManagedResources = append(argoManagedResources, argoManagedResource) + } + } + } + return healthStatus, syncStatus, destinationServer, argoManagedResources +} diff --git a/pkg/k8s/K8sCommonService.go b/pkg/k8s/K8sCommonService.go index 09717b059b6..6c8ecc2fb3c 100644 --- a/pkg/k8s/K8sCommonService.go +++ b/pkg/k8s/K8sCommonService.go @@ -25,7 +25,7 @@ import ( "github.com/devtron-labs/devtron/api/bean" helmBean "github.com/devtron-labs/devtron/api/helm-app/service/bean" internalUtil "github.com/devtron-labs/devtron/internal/util" - "github.com/devtron-labs/devtron/pkg/argoApplication" + "github.com/devtron-labs/devtron/pkg/argoApplication/read" "github.com/devtron-labs/devtron/pkg/cluster" bean3 "github.com/devtron-labs/devtron/pkg/k8s/application/bean" "github.com/devtron-labs/devtron/util" @@ -71,7 +71,7 @@ type K8sCommonServiceImpl struct { K8sUtil *k8s.K8sServiceImpl clusterService cluster.ClusterService K8sApplicationServiceConfig *K8sApplicationServiceConfig - argoApplicationService argoApplication.ArgoApplicationService + argoApplicationReadService read.ArgoApplicationReadService } type K8sApplicationServiceConfig struct { BatchSize int `env:"BATCH_SIZE" envDefault:"5"` @@ -80,7 +80,7 @@ type K8sApplicationServiceConfig struct { func NewK8sCommonServiceImpl(Logger *zap.SugaredLogger, k8sUtils *k8s.K8sServiceImpl, clusterService cluster.ClusterService, - argoApplicationService argoApplication.ArgoApplicationService) *K8sCommonServiceImpl { + argoApplicationReadService read.ArgoApplicationReadService) *K8sCommonServiceImpl { cfg := &K8sApplicationServiceConfig{} err := env.Parse(cfg) if err != nil { @@ -91,7 +91,7 @@ func NewK8sCommonServiceImpl(Logger *zap.SugaredLogger, k8sUtils *k8s.K8sService K8sUtil: k8sUtils, clusterService: clusterService, K8sApplicationServiceConfig: cfg, - argoApplicationService: argoApplicationService, + argoApplicationReadService: argoApplicationReadService, } } @@ -190,7 +190,7 @@ func (impl *K8sCommonServiceImpl) GetRestConfigOfCluster(ctx context.Context, re //getting rest config by clusterId clusterId := request.ClusterId if len(request.ExternalArgoApplicationName) > 0 { - restConfig, err := impl.argoApplicationService.GetRestConfigForExternalArgo(ctx, clusterId, request.ExternalArgoApplicationName) + restConfig, err := impl.argoApplicationReadService.GetRestConfigForExternalArgo(ctx, clusterId, request.ExternalArgoApplicationName) if err != nil { impl.logger.Errorw("error in getting rest config", "err", err, "clusterId", clusterId, "externalArgoApplicationName", request.ExternalArgoApplicationName) return nil, err @@ -457,7 +457,7 @@ func (impl *K8sCommonServiceImpl) GetCoreClientByClusterId(clusterId int) (*kube } func (impl *K8sCommonServiceImpl) GetCoreClientByClusterIdForExternalArgoApps(req *cluster.EphemeralContainerRequest) (*kubernetes.Clientset, *clientV1.CoreV1Client, error) { - restConfig, err := impl.argoApplicationService.GetRestConfigForExternalArgo(context.Background(), req.ClusterId, req.ExternalArgoApplicationName) + restConfig, err := impl.argoApplicationReadService.GetRestConfigForExternalArgo(context.Background(), req.ClusterId, req.ExternalArgoApplicationName) if err != nil { impl.logger.Errorw("error in getting rest config", "err", err, "clusterId", req.ClusterId, "externalArgoApplicationName", req.ExternalArgoApplicationName) } diff --git a/pkg/k8s/application/k8sApplicationService.go b/pkg/k8s/application/k8sApplicationService.go index 39b1902b17b..af5b7e33f27 100644 --- a/pkg/k8s/application/k8sApplicationService.go +++ b/pkg/k8s/application/k8sApplicationService.go @@ -25,7 +25,7 @@ import ( "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/helm-app/service/bean" - bean4 "github.com/devtron-labs/devtron/pkg/argoApplication/bean" + "github.com/devtron-labs/devtron/pkg/argoApplication/helper" "github.com/devtron-labs/devtron/pkg/auth/authorisation/casbin" clientErrors "github.com/devtron-labs/devtron/pkg/errors" "github.com/devtron-labs/devtron/pkg/fluxApplication" @@ -45,7 +45,6 @@ import ( yamlUtil "github.com/devtron-labs/common-lib/utils/yaml" "github.com/devtron-labs/devtron/api/connector" "github.com/devtron-labs/devtron/api/helm-app/openapiClient" - "github.com/devtron-labs/devtron/pkg/argoApplication" "github.com/devtron-labs/devtron/pkg/cluster" "github.com/devtron-labs/devtron/pkg/cluster/repository" "github.com/devtron-labs/devtron/pkg/k8s" @@ -81,6 +80,8 @@ type K8sApplicationService interface { GetAllApiResourceGVKWithoutAuthorization(ctx context.Context, clusterId int) (*k8s2.GetAllApiResourcesResponse, error) GetAllApiResources(ctx context.Context, clusterId int, isSuperAdmin bool, userId int32) (*k8s2.GetAllApiResourcesResponse, error) GetResourceList(ctx context.Context, token string, request *k8s.ResourceRequestBean, validateResourceAccess func(token string, clusterName string, request k8s.ResourceRequestBean, casbinAction string) bool) (*k8s2.ClusterResourceListMap, error) + GetResourceListWithRestConfig(ctx context.Context, token string, request *k8s.ResourceRequestBean, validateResourceAccess func(token string, clusterName string, request k8s.ResourceRequestBean, casbinAction string) bool, + restConfig *rest.Config, clusterName string) (*k8s2.ClusterResourceListMap, error) ApplyResources(ctx context.Context, token string, request *k8s2.ApplyResourcesRequest, resourceRbacHandler func(token string, clusterName string, request k8s.ResourceRequestBean, casbinAction string) bool) ([]*k8s2.ApplyResourcesResponse, error) CreatePodEphemeralContainers(req *cluster.EphemeralContainerRequest) error TerminatePodEphemeralContainer(req cluster.EphemeralContainerRequest) (bool, error) @@ -90,7 +91,6 @@ type K8sApplicationService interface { DeleteResourceWithAudit(ctx context.Context, request *k8s.ResourceRequestBean, userId int32) (*k8s2.ManifestResponse, error) GetUrlsByBatchForIngress(ctx context.Context, resp []k8s.BatchResourceResponse) []interface{} ValidateFluxResourceRequest(ctx context.Context, appIdentifier *bean2.FluxAppIdentifier, request *k8s2.K8sRequestBean) (bool, error) - ValidateArgoResourceRequest(ctx context.Context, appIdentifier *bean4.ArgoAppIdentifier, request *k8s2.K8sRequestBean) (bool, error) } type K8sApplicationServiceImpl struct { @@ -106,15 +106,15 @@ type K8sApplicationServiceImpl struct { ephemeralContainerService cluster.EphemeralContainerService ephemeralContainerRepository repository.EphemeralContainersRepository ephemeralContainerConfig *EphemeralContainerConfig - argoApplicationService argoApplication.ArgoApplicationService - fluxApplicationService fluxApplication.FluxApplicationService + //argoApplicationService argoApplication.ArgoApplicationService + fluxApplicationService fluxApplication.FluxApplicationService } func NewK8sApplicationServiceImpl(Logger *zap.SugaredLogger, clusterService cluster.ClusterService, pump connector.Pump, helmAppService client.HelmAppService, K8sUtil *k8s2.K8sServiceImpl, aCDAuthConfig *util3.ACDAuthConfig, K8sResourceHistoryService kubernetesResourceAuditLogs.K8sResourceHistoryService, k8sCommonService k8s.K8sCommonService, terminalSession terminal.TerminalSessionHandler, ephemeralContainerService cluster.EphemeralContainerService, ephemeralContainerRepository repository.EphemeralContainersRepository, - argoApplicationService argoApplication.ArgoApplicationService, fluxApplicationService fluxApplication.FluxApplicationService) (*K8sApplicationServiceImpl, error) { + fluxApplicationService fluxApplication.FluxApplicationService) (*K8sApplicationServiceImpl, error) { ephemeralContainerConfig := &EphemeralContainerConfig{} err := env.Parse(ephemeralContainerConfig) if err != nil { @@ -134,8 +134,8 @@ func NewK8sApplicationServiceImpl(Logger *zap.SugaredLogger, clusterService clus ephemeralContainerService: ephemeralContainerService, ephemeralContainerRepository: ephemeralContainerRepository, ephemeralContainerConfig: ephemeralContainerConfig, - argoApplicationService: argoApplicationService, - fluxApplicationService: fluxApplicationService, + //argoApplicationService: argoApplicationService, + fluxApplicationService: fluxApplicationService, }, nil } @@ -249,7 +249,7 @@ func (impl *K8sApplicationServiceImpl) ValidatePodLogsRequestQuery(r *http.Reque request.DeploymentType = deploymentType // Validate App Id if request.AppType == bean3.ArgoAppType { - appIdentifier, err := argoApplication.DecodeExternalArgoAppId(appId) + appIdentifier, err := helper.DecodeExternalArgoAppId(appId) if err != nil { impl.logger.Errorw(bean3.AppIdDecodingError, "err", err, "appId", appId) return nil, err @@ -356,7 +356,7 @@ func (impl *K8sApplicationServiceImpl) ValidateTerminalRequestQuery(r *http.Requ request.ClusterId = fluxAppIdentifier.ClusterId } else if appType == bean3.ArgoAppType { - appIdentifier, err := argoApplication.DecodeExternalArgoAppId(request.ApplicationId) + appIdentifier, err := helper.DecodeExternalArgoAppId(request.ApplicationId) if err != nil { impl.logger.Errorw(bean3.InvalidAppId, "err", err, "appId", request.ApplicationId) return nil, nil, err @@ -364,7 +364,7 @@ func (impl *K8sApplicationServiceImpl) ValidateTerminalRequestQuery(r *http.Requ resourceRequestBean.ExternalArgoApplicationName = appIdentifier.AppName resourceRequestBean.ClusterId = appIdentifier.ClusterId request.ClusterId = appIdentifier.ClusterId - //request.ExternalArgoApplicationName = appIdentifier.AppName + request.ExternalArgoApplicationName = appIdentifier.AppName } } else { // Validate Cluster Id @@ -522,39 +522,6 @@ func (impl *K8sApplicationServiceImpl) validateResourceRequest(ctx context.Conte } return impl.validateContainerNameIfReqd(valid, request, app), nil } -func (impl *K8sApplicationServiceImpl) ValidateArgoResourceRequest(ctx context.Context, appIdentifier *bean4.ArgoAppIdentifier, request *k8s2.K8sRequestBean) (bool, error) { - app, err := impl.argoApplicationService.GetAppDetail(appIdentifier.AppName, appIdentifier.Namespace, appIdentifier.ClusterId) - if err != nil { - impl.logger.Errorw("error in getting app detail", "err", err, "appDetails", appIdentifier) - apiError := clientErrors.ConvertToApiError(err) - if apiError != nil { - err = apiError - } - return false, err - } - - valid := false - - for _, node := range app.ResourceTree.Nodes { - nodeDetails := k8s2.ResourceIdentifier{ - Name: node.Name, - Namespace: node.Namespace, - GroupVersionKind: schema.GroupVersionKind{ - Group: node.Group, - Version: node.Version, - Kind: node.Kind, - }, - } - if nodeDetails == request.ResourceIdentifier { - valid = true - break - } - } - appDetail := &gRPC.AppDetail{ - ResourceTreeResponse: app.ResourceTree, - } - return impl.validateContainerNameIfReqd(valid, request, appDetail), nil -} func (impl *K8sApplicationServiceImpl) ValidateFluxResourceRequest(ctx context.Context, appIdentifier *bean2.FluxAppIdentifier, request *k8s2.K8sRequestBean) (bool, error) { app, err := impl.fluxApplicationService.GetFluxAppDetail(ctx, appIdentifier) @@ -766,6 +733,13 @@ func (impl *K8sApplicationServiceImpl) GetResourceList(ctx context.Context, toke impl.logger.Errorw("error in getting rest config by cluster Id", "err", err, "clusterId", request.ClusterId) return resourceList, err } + return impl.GetResourceListWithRestConfig(ctx, token, request, validateResourceAccess, restConfig, clusterBean.ClusterName) +} + +func (impl *K8sApplicationServiceImpl) GetResourceListWithRestConfig(ctx context.Context, token string, request *k8s.ResourceRequestBean, + validateResourceAccess func(token string, clusterName string, request k8s.ResourceRequestBean, casbinAction string) bool, + restConfig *rest.Config, clusterName string) (*k8s2.ClusterResourceListMap, error) { + resourceList := &k8s2.ClusterResourceListMap{} k8sRequest := request.K8sRequest // store the copy of requested resource identifier resourceIdentifierCloned := k8sRequest.ResourceIdentifier @@ -785,22 +759,13 @@ func (impl *K8sApplicationServiceImpl) GetResourceList(ctx context.Context, toke resourceIdentifier.GroupVersionKind = schema.GroupVersionKind{Group: group, Kind: kind} } k8sRequest.ResourceIdentifier = resourceIdentifier - return validateResourceAccess(token, clusterBean.ClusterName, *request, casbin.ActionGet) + return validateResourceAccess(token, clusterName, *request, casbin.ActionGet) } resourceList, err = impl.K8sUtil.BuildK8sObjectListTableData(&resp.Resources, namespaced, request.K8sRequest.ResourceIdentifier.GroupVersionKind, false, checkForResourceCallback) if err != nil { impl.logger.Errorw("error on parsing for k8s resource", "err", err) return resourceList, err } - // Not used in FE side - - //k8sServerVersion, err := impl.k8sCommonService.GetK8sServerVersion(clusterId) - //if err != nil { - // impl.logger.Errorw("error in getting k8s server version", "clusterId", clusterId, "err", err) - // // return nil, err - //} else { - // resourceList.ServerVersion = k8sServerVersion.String() - //} return resourceList, nil } diff --git a/pkg/terminal/terminalSesion.go b/pkg/terminal/terminalSesion.go index 6d0e2a8fa07..ba9a4859756 100644 --- a/pkg/terminal/terminalSesion.go +++ b/pkg/terminal/terminalSesion.go @@ -26,7 +26,7 @@ import ( "github.com/caarlos0/env" "github.com/devtron-labs/common-lib/utils/k8s" "github.com/devtron-labs/devtron/internal/middleware" - "github.com/devtron-labs/devtron/pkg/argoApplication" + "github.com/devtron-labs/devtron/pkg/argoApplication/read" "github.com/devtron-labs/devtron/pkg/cluster" "github.com/devtron-labs/devtron/pkg/cluster/repository" errors1 "github.com/juju/errors" @@ -447,24 +447,24 @@ type TerminalSessionHandler interface { } type TerminalSessionHandlerImpl struct { - environmentService cluster.EnvironmentService - clusterService cluster.ClusterService - logger *zap.SugaredLogger - k8sUtil *k8s.K8sServiceImpl - ephemeralContainerService cluster.EphemeralContainerService - argoApplicationService argoApplication.ArgoApplicationService + environmentService cluster.EnvironmentService + clusterService cluster.ClusterService + logger *zap.SugaredLogger + k8sUtil *k8s.K8sServiceImpl + ephemeralContainerService cluster.EphemeralContainerService + argoApplicationReadService read.ArgoApplicationReadService } func NewTerminalSessionHandlerImpl(environmentService cluster.EnvironmentService, clusterService cluster.ClusterService, logger *zap.SugaredLogger, k8sUtil *k8s.K8sServiceImpl, ephemeralContainerService cluster.EphemeralContainerService, - argoApplicationService argoApplication.ArgoApplicationService) *TerminalSessionHandlerImpl { + argoApplicationReadService read.ArgoApplicationReadService) *TerminalSessionHandlerImpl { return &TerminalSessionHandlerImpl{ - environmentService: environmentService, - clusterService: clusterService, - logger: logger, - k8sUtil: k8sUtil, - ephemeralContainerService: ephemeralContainerService, - argoApplicationService: argoApplicationService, + environmentService: environmentService, + clusterService: clusterService, + logger: logger, + k8sUtil: k8sUtil, + ephemeralContainerService: ephemeralContainerService, + argoApplicationReadService: argoApplicationReadService, } } @@ -531,7 +531,7 @@ func (impl *TerminalSessionHandlerImpl) getClientSetAndRestConfigForTerminalConn var restConfig *rest.Config var err error if len(req.ExternalArgoApplicationName) > 0 { - restConfig, err = impl.argoApplicationService.GetRestConfigForExternalArgo(context.Background(), req.ClusterId, req.ExternalArgoApplicationName) + restConfig, err = impl.argoApplicationReadService.GetRestConfigForExternalArgo(context.Background(), req.ClusterId, req.ExternalArgoApplicationName) if err != nil { impl.logger.Errorw("error in getting rest config", "err", err, "clusterId", req.ClusterId, "externalArgoApplicationName", req.ExternalArgoApplicationName) return nil, nil, err @@ -652,7 +652,7 @@ func (impl *TerminalSessionHandlerImpl) saveEphemeralContainerTerminalAccessAudi var restConfig *rest.Config var err error if len(req.ExternalArgoApplicationName) > 0 { - restConfig, err = impl.argoApplicationService.GetRestConfigForExternalArgo(context.Background(), req.ClusterId, req.ExternalArgoApplicationName) + restConfig, err = impl.argoApplicationReadService.GetRestConfigForExternalArgo(context.Background(), req.ClusterId, req.ExternalArgoApplicationName) if err != nil { impl.logger.Errorw("error in getting rest config", "err", err, "clusterId", req.ClusterId, "externalArgoApplicationName", req.ExternalArgoApplicationName) return err diff --git a/wire_gen.go b/wire_gen.go index a99ee499aaa..9ad1f1575a8 100644 --- a/wire_gen.go +++ b/wire_gen.go @@ -119,6 +119,7 @@ import ( service3 "github.com/devtron-labs/devtron/pkg/appStore/values/service" appWorkflow2 "github.com/devtron-labs/devtron/pkg/appWorkflow" "github.com/devtron-labs/devtron/pkg/argoApplication" + "github.com/devtron-labs/devtron/pkg/argoApplication/read" "github.com/devtron-labs/devtron/pkg/argoRepositoryCreds" "github.com/devtron-labs/devtron/pkg/asyncProvider" "github.com/devtron-labs/devtron/pkg/attributes" @@ -157,7 +158,7 @@ import ( "github.com/devtron-labs/devtron/pkg/deploymentGroup" "github.com/devtron-labs/devtron/pkg/devtronResource" "github.com/devtron-labs/devtron/pkg/devtronResource/history/deployment/cdPipeline" - "github.com/devtron-labs/devtron/pkg/devtronResource/read" + read2 "github.com/devtron-labs/devtron/pkg/devtronResource/read" repository8 "github.com/devtron-labs/devtron/pkg/devtronResource/repository" "github.com/devtron-labs/devtron/pkg/dockerRegistry" "github.com/devtron-labs/devtron/pkg/eventProcessor" @@ -399,8 +400,8 @@ func InitializeApp() (*App, error) { if err != nil { return nil, err } - argoApplicationServiceImpl := argoApplication.NewArgoApplicationServiceImpl(sugaredLogger, clusterRepositoryImpl, k8sServiceImpl, argoUserServiceImpl, helmAppClientImpl, helmAppServiceImpl) - k8sCommonServiceImpl := k8s2.NewK8sCommonServiceImpl(sugaredLogger, k8sServiceImpl, clusterServiceImplExtended, argoApplicationServiceImpl) + argoApplicationReadServiceImpl := read.NewArgoApplicationReadServiceImpl(sugaredLogger, clusterRepositoryImpl, k8sServiceImpl, argoUserServiceImpl, helmAppClientImpl, helmAppServiceImpl) + k8sCommonServiceImpl := k8s2.NewK8sCommonServiceImpl(sugaredLogger, k8sServiceImpl, clusterServiceImplExtended, argoApplicationReadServiceImpl) environmentRestHandlerImpl := cluster3.NewEnvironmentRestHandlerImpl(environmentServiceImpl, sugaredLogger, userServiceImpl, validate, enforcerImpl, deleteServiceExtendedImpl, k8sServiceImpl, k8sCommonServiceImpl) environmentRouterImpl := cluster3.NewEnvironmentRouterImpl(environmentRestHandlerImpl) transactionUtilImpl := sql.NewTransactionUtilImpl(db) @@ -460,7 +461,7 @@ func InitializeApp() (*App, error) { appStatusServiceImpl := appStatus2.NewAppStatusServiceImpl(appStatusRepositoryImpl, sugaredLogger, enforcerImpl, enforcerUtilImpl) scopedVariableRepositoryImpl := repository7.NewScopedVariableRepository(db, sugaredLogger, transactionUtilImpl) devtronResourceSearchableKeyRepositoryImpl := repository8.NewDevtronResourceSearchableKeyRepositoryImpl(sugaredLogger, db) - devtronResourceSearchableKeyServiceImpl, err := read.NewDevtronResourceSearchableKeyServiceImpl(sugaredLogger, devtronResourceSearchableKeyRepositoryImpl) + devtronResourceSearchableKeyServiceImpl, err := read2.NewDevtronResourceSearchableKeyServiceImpl(sugaredLogger, devtronResourceSearchableKeyRepositoryImpl) if err != nil { return nil, err } @@ -713,9 +714,9 @@ func InitializeApp() (*App, error) { k8sResourceHistoryServiceImpl := kubernetesResourceAuditLogs.Newk8sResourceHistoryServiceImpl(k8sResourceHistoryRepositoryImpl, sugaredLogger, appRepositoryImpl, environmentRepositoryImpl) ephemeralContainersRepositoryImpl := repository.NewEphemeralContainersRepositoryImpl(db, transactionUtilImpl) ephemeralContainerServiceImpl := cluster2.NewEphemeralContainerServiceImpl(ephemeralContainersRepositoryImpl, sugaredLogger) - terminalSessionHandlerImpl := terminal.NewTerminalSessionHandlerImpl(environmentServiceImpl, clusterServiceImplExtended, sugaredLogger, k8sServiceImpl, ephemeralContainerServiceImpl, argoApplicationServiceImpl) + terminalSessionHandlerImpl := terminal.NewTerminalSessionHandlerImpl(environmentServiceImpl, clusterServiceImplExtended, sugaredLogger, k8sServiceImpl, ephemeralContainerServiceImpl, argoApplicationReadServiceImpl) fluxApplicationServiceImpl := fluxApplication.NewFluxApplicationServiceImpl(sugaredLogger, helmAppServiceImpl, clusterServiceImplExtended, helmAppClientImpl, pumpImpl) - k8sApplicationServiceImpl, err := application2.NewK8sApplicationServiceImpl(sugaredLogger, clusterServiceImplExtended, pumpImpl, helmAppServiceImpl, k8sServiceImpl, acdAuthConfig, k8sResourceHistoryServiceImpl, k8sCommonServiceImpl, terminalSessionHandlerImpl, ephemeralContainerServiceImpl, ephemeralContainersRepositoryImpl, argoApplicationServiceImpl, fluxApplicationServiceImpl) + k8sApplicationServiceImpl, err := application2.NewK8sApplicationServiceImpl(sugaredLogger, clusterServiceImplExtended, pumpImpl, helmAppServiceImpl, k8sServiceImpl, acdAuthConfig, k8sResourceHistoryServiceImpl, k8sCommonServiceImpl, terminalSessionHandlerImpl, ephemeralContainerServiceImpl, ephemeralContainersRepositoryImpl, fluxApplicationServiceImpl) if err != nil { return nil, err } @@ -868,9 +869,10 @@ func InitializeApp() (*App, error) { appRouterImpl := app3.NewAppRouterImpl(appFilteringRouterImpl, appListingRouterImpl, appInfoRouterImpl, pipelineTriggerRouterImpl, pipelineConfigRouterImpl, pipelineHistoryRouterImpl, pipelineStatusRouterImpl, appWorkflowRouterImpl, devtronAppAutoCompleteRouterImpl, appWorkflowRestHandlerImpl, appListingRestHandlerImpl, appFilteringRestHandlerImpl) 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) + argoApplicationServiceImpl := argoApplication.NewArgoApplicationServiceImpl(sugaredLogger, clusterRepositoryImpl, k8sServiceImpl, argoUserServiceImpl, helmAppClientImpl, helmAppServiceImpl, k8sApplicationServiceImpl, argoApplicationReadServiceImpl) helmAppRestHandlerImpl := client3.NewHelmAppRestHandlerImpl(sugaredLogger, helmAppServiceImpl, enforcerImpl, clusterServiceImplExtended, enforcerUtilHelmImpl, appStoreDeploymentServiceImpl, installedAppDBServiceImpl, userServiceImpl, attributesServiceImpl, serverEnvConfigServerEnvConfig, fluxApplicationServiceImpl, argoApplicationServiceImpl) helmAppRouterImpl := client3.NewHelmAppRouterImpl(helmAppRestHandlerImpl) - k8sApplicationRestHandlerImpl := application3.NewK8sApplicationRestHandlerImpl(sugaredLogger, k8sApplicationServiceImpl, pumpImpl, terminalSessionHandlerImpl, enforcerImpl, enforcerUtilHelmImpl, enforcerUtilImpl, helmAppServiceImpl, userServiceImpl, k8sCommonServiceImpl, validate, environmentVariables, fluxApplicationServiceImpl, argoApplicationServiceImpl) + k8sApplicationRestHandlerImpl := application3.NewK8sApplicationRestHandlerImpl(sugaredLogger, k8sApplicationServiceImpl, pumpImpl, terminalSessionHandlerImpl, enforcerImpl, enforcerUtilHelmImpl, enforcerUtilImpl, helmAppServiceImpl, userServiceImpl, k8sCommonServiceImpl, validate, environmentVariables, fluxApplicationServiceImpl, argoApplicationReadServiceImpl) k8sApplicationRouterImpl := application3.NewK8sApplicationRouterImpl(k8sApplicationRestHandlerImpl) pProfRestHandlerImpl := restHandler.NewPProfRestHandler(userServiceImpl, enforcerImpl) pProfRouterImpl := router.NewPProfRouter(sugaredLogger, pProfRestHandlerImpl) @@ -955,7 +957,7 @@ func InitializeApp() (*App, error) { deploymentConfigurationRouterImpl := router.NewDeploymentConfigurationRouter(deploymentConfigurationRestHandlerImpl) infraConfigRestHandlerImpl := infraConfig2.NewInfraConfigRestHandlerImpl(sugaredLogger, infraConfigServiceImpl, userServiceImpl, enforcerImpl, enforcerUtilImpl, validate) infraConfigRouterImpl := infraConfig2.NewInfraProfileRouterImpl(infraConfigRestHandlerImpl) - argoApplicationRestHandlerImpl := argoApplication2.NewArgoApplicationRestHandlerImpl(argoApplicationServiceImpl, sugaredLogger, enforcerImpl) + argoApplicationRestHandlerImpl := argoApplication2.NewArgoApplicationRestHandlerImpl(argoApplicationServiceImpl, argoApplicationReadServiceImpl, sugaredLogger, enforcerImpl) argoApplicationRouterImpl := argoApplication2.NewArgoApplicationRouterImpl(argoApplicationRestHandlerImpl) deploymentHistoryServiceImpl := cdPipeline.NewDeploymentHistoryServiceImpl(sugaredLogger, cdHandlerImpl, imageTaggingServiceImpl, pipelineRepositoryImpl, deployedConfigurationHistoryServiceImpl) apiReqDecoderServiceImpl := devtronResource.NewAPIReqDecoderServiceImpl(sugaredLogger, pipelineRepositoryImpl)