Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat: Description for cluster and apps #4154

Merged
merged 28 commits into from
Nov 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
a46a489
wip
kartik-579 Oct 25, 2023
0198f78
updated description provision in app update api used for labels
kartik-579 Oct 25, 2023
d6f9120
added api for getting app meta info for helm app
kartik-579 Oct 25, 2023
4c11b9f
updated app meta info api for helm app chart used data support
kartik-579 Oct 25, 2023
ab42cd6
corrected api method
kartik-579 Oct 25, 2023
6f838e3
fixed validation for cluster description update api
kartik-579 Oct 25, 2023
2f5a88d
added icon
kartik-579 Oct 26, 2023
032b92f
refactored query for better viewing
kartik-579 Oct 26, 2023
c6842ef
enhanced env listing query for app overview to support new required d…
kartik-579 Oct 26, 2023
b905533
Merge branch 'main' into description-and-env-list-api
kartik-579 Oct 27, 2023
1b11737
review comments
kartik-579 Oct 27, 2023
5a6edbc
updated sql script no
kartik-579 Oct 30, 2023
4864e81
Merge branch 'main' into description-and-env-list-api
kartik-579 Oct 30, 2023
239209a
Merge branch 'main' into description-and-env-list-api
kartik-579 Oct 31, 2023
6dc4d44
added code source info
kartik-579 Oct 31, 2023
5ecfa20
fixed ea wiring
kartik-579 Oct 31, 2023
f9e69e7
updated params in other-env api
kartik-579 Nov 1, 2023
0d95220
Merge branch 'main' into description-and-env-list-api
kartik-579 Nov 1, 2023
110a2ec
updated api for fetching other env data
kartik-579 Nov 2, 2023
e1fe325
Merge branch 'main' into description-and-env-list-api
kartik-579 Nov 2, 2023
8a70d0a
fixed import
kartik-579 Nov 2, 2023
e7abd99
fix
kartik-579 Nov 2, 2023
7f315aa
wip
kartik-579 Nov 2, 2023
3f4a3be
wip
kartik-579 Nov 2, 2023
03a391c
wip
kartik-579 Nov 2, 2023
0b8607d
added pipeline deleted condition - fetch other env
kartik-579 Nov 3, 2023
198ff20
Merge branch 'main' into description-and-env-list-api
kartik-579 Nov 3, 2023
cbea326
updated sql script no.
kartik-579 Nov 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion api/appStore/AppStoreRouter.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ func (router AppStoreRouterImpl) Init(configRouter *mux.Router) {
chartProviderSubRouter := configRouter.PathPrefix("/chart-provider").Subrouter()
router.chartProviderRouter.Init(chartProviderSubRouter)
// chart provider router ends

configRouter.Path("/overview").Queries("installedAppId", "{installedAppId}").
HandlerFunc(router.deployRestHandler.FetchAppOverview).Methods("GET")
configRouter.Path("/application/exists").
HandlerFunc(router.deployRestHandler.CheckAppExists).Methods("POST")
configRouter.Path("/group/install").
Expand Down
44 changes: 43 additions & 1 deletion api/appStore/InstalledAppRestHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
"github.com/devtron-labs/devtron/internal/constants"
"github.com/devtron-labs/devtron/internal/middleware"
util2 "github.com/devtron-labs/devtron/internal/util"
app2 "github.com/devtron-labs/devtron/pkg/app"
appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean"
"github.com/devtron-labs/devtron/pkg/appStore/deployment/repository"
"github.com/devtron-labs/devtron/pkg/appStore/deployment/service"
Expand All @@ -53,6 +54,7 @@ import (
)

type InstalledAppRestHandler interface {
FetchAppOverview(w http.ResponseWriter, r *http.Request)
GetAllInstalledApp(w http.ResponseWriter, r *http.Request)
DeployBulk(w http.ResponseWriter, r *http.Request)
CheckAppExists(w http.ResponseWriter, r *http.Request)
Expand Down Expand Up @@ -82,6 +84,7 @@ type InstalledAppRestHandlerImpl struct {
cdApplicationStatusUpdateHandler cron.CdApplicationStatusUpdateHandler
installedAppRepository repository.InstalledAppRepository
K8sApplicationService application2.K8sApplicationService
appCrudOperationService app2.AppCrudOperationService
}

func NewInstalledAppRestHandlerImpl(Logger *zap.SugaredLogger, userAuthService user.UserService,
Expand All @@ -91,7 +94,7 @@ func NewInstalledAppRestHandlerImpl(Logger *zap.SugaredLogger, userAuthService u
argoUserService argo.ArgoUserService,
cdApplicationStatusUpdateHandler cron.CdApplicationStatusUpdateHandler,
installedAppRepository repository.InstalledAppRepository,
) *InstalledAppRestHandlerImpl {
appCrudOperationService app2.AppCrudOperationService) *InstalledAppRestHandlerImpl {
return &InstalledAppRestHandlerImpl{
Logger: Logger,
userAuthService: userAuthService,
Expand All @@ -108,8 +111,47 @@ func NewInstalledAppRestHandlerImpl(Logger *zap.SugaredLogger, userAuthService u
argoUserService: argoUserService,
cdApplicationStatusUpdateHandler: cdApplicationStatusUpdateHandler,
installedAppRepository: installedAppRepository,
appCrudOperationService: appCrudOperationService,
}
}
func (handler *InstalledAppRestHandlerImpl) FetchAppOverview(w http.ResponseWriter, r *http.Request) {
userId, err := handler.userAuthService.GetLoggedInUser(r)
if userId == 0 || err != nil {
common.WriteJsonResp(w, err, nil, http.StatusUnauthorized)
return
}

vars := mux.Vars(r)
installedAppId, err := strconv.Atoi(vars["installedAppId"])
if err != nil {
handler.Logger.Errorw("request err, FetchAppOverview", "err", err, "installedAppId", installedAppId)
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
}
token := r.Header.Get("token")
handler.Logger.Infow("request payload, FindAppOverview", "installedAppId", installedAppId)
installedApp, err := handler.installedAppService.CheckAppExistsByInstalledAppId(installedAppId)
appOverview, err := handler.appCrudOperationService.GetAppMetaInfo(installedApp.AppId, installedAppId, installedApp.EnvironmentId)
if err != nil {
handler.Logger.Errorw("service err, FetchAppOverview", "err", err, "appId", installedApp.AppId, "installedAppId", installedAppId)
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
return
}

//rbac block starts from here
object, object2 := handler.enforcerUtil.GetHelmObject(appOverview.AppId, installedApp.EnvironmentId)
var ok bool
if object2 == "" {
ok = handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionGet, object)
} else {
ok = handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionGet, object) || handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionGet, object2)
}
if !ok {
common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), nil, http.StatusForbidden)
return
}
common.WriteJsonResp(w, nil, appOverview, http.StatusOK)
}

func (handler InstalledAppRestHandlerImpl) GetAllInstalledApp(w http.ResponseWriter, r *http.Request) {
userId, err := handler.userAuthService.GetLoggedInUser(r)
Expand Down
4 changes: 4 additions & 0 deletions api/bean/AppView.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,10 +198,14 @@ type Environment struct {
Prod bool `json:"prod"`
ChartRefId int `json:"chartRefId"`
LastDeployed string `json:"lastDeployed"`
LastDeployedBy string `json:"lastDeployedBy"`
LastDeployedImage string `json:"lastDeployedImage"`
DeploymentAppDeleteRequest bool `json:"deploymentAppDeleteRequest"`
Description string `json:"description" validate:"max=40"`
IsVirtualEnvironment bool `json:"isVirtualEnvironment"`
ClusterId int `json:"clusterId"`
PipelineId int `json:"pipelineId"`
LatestCdWorkflowRunnerId int `json:"latestCdWorkflowRunnerId,omitempty"`
}

type InstanceDetail struct {
Expand Down
40 changes: 40 additions & 0 deletions api/cluster/ClusterRestHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ type ClusterRestHandler interface {
FindById(w http.ResponseWriter, r *http.Request)
FindNoteByClusterId(w http.ResponseWriter, r *http.Request)
Update(w http.ResponseWriter, r *http.Request)
UpdateClusterDescription(w http.ResponseWriter, r *http.Request)
UpdateClusterNote(w http.ResponseWriter, r *http.Request)
FindAllForAutoComplete(w http.ResponseWriter, r *http.Request)
DeleteCluster(w http.ResponseWriter, r *http.Request)
Expand Down Expand Up @@ -453,6 +454,45 @@ func (impl ClusterRestHandlerImpl) Update(w http.ResponseWriter, r *http.Request
common.WriteJsonResp(w, err, bean, http.StatusOK)
}

func (impl ClusterRestHandlerImpl) UpdateClusterDescription(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("token")
decoder := json.NewDecoder(r.Body)
userId, err := impl.userService.GetLoggedInUser(r)
if userId == 0 || err != nil {
impl.logger.Errorw("service err, Update", "error", err, "userId", userId)
common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized)
return
}
var bean cluster.ClusterBean
err = decoder.Decode(&bean)
if err != nil {
impl.logger.Errorw("request err, UpdateClusterDescription", "error", err, "payload", bean)
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
}
impl.logger.Infow("request payload, UpdateClusterDescription", "payload", bean)
//TODO: add apt validation
clusterDescription, err := impl.clusterDescriptionService.FindByClusterIdWithClusterDetails(bean.Id)
if err != nil {
impl.logger.Errorw("service err, FindById", "err", err, "clusterId", bean.Id)
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
return
}
// RBAC enforcer applying
if ok := impl.enforcer.Enforce(token, casbin.ResourceCluster, casbin.ActionUpdate, strings.ToLower(clusterDescription.ClusterName)); !ok {
common.WriteJsonResp(w, errors.New("unauthorized"), nil, http.StatusForbidden)
return
}
// RBAC enforcer ends
err = impl.clusterService.UpdateClusterDescription(&bean, userId)
if err != nil {
impl.logger.Errorw("service err, UpdateClusterDescription", "error", err, "payload", bean)
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
return
}
common.WriteJsonResp(w, err, "Cluster description updated successfully", http.StatusOK)
}

func (impl ClusterRestHandlerImpl) UpdateClusterNote(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("token")
decoder := json.NewDecoder(r.Body)
Expand Down
6 changes: 5 additions & 1 deletion api/cluster/ClusterRouter.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func (impl ClusterRouterImpl) InitClusterRouter(clusterRouter *mux.Router) {
Methods("PUT").
HandlerFunc(impl.clusterRestHandler.Update)

clusterRouter.Path("/description").
clusterRouter.Path("/note").
Methods("PUT").
HandlerFunc(impl.clusterRestHandler.UpdateClusterNote)

Expand All @@ -89,4 +89,8 @@ func (impl ClusterRouterImpl) InitClusterRouter(clusterRouter *mux.Router) {
clusterRouter.Path("/auth-list").
Methods("GET").
HandlerFunc(impl.clusterRestHandler.FindAllForClusterPermission)

clusterRouter.Path("/description").
Methods("PUT").
HandlerFunc(impl.clusterRestHandler.UpdateClusterDescription)
}
6 changes: 3 additions & 3 deletions api/restHandler/AppRestHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ type AppRestHandler interface {
UpdateApp(w http.ResponseWriter, r *http.Request)
UpdateProjectForApps(w http.ResponseWriter, r *http.Request)
GetAppListByTeamIds(w http.ResponseWriter, r *http.Request)
UpdateAppDescription(w http.ResponseWriter, r *http.Request)
UpdateAppNote(w http.ResponseWriter, r *http.Request)
}

type AppRestHandlerImpl struct {
Expand Down Expand Up @@ -123,7 +123,7 @@ func (handler AppRestHandlerImpl) GetAppMetaInfo(w http.ResponseWriter, r *http.
}
//rback implementation ends here

res, err := handler.appService.GetAppMetaInfo(appId)
res, err := handler.appService.GetAppMetaInfo(appId, app.ZERO_INSTALLED_APP_ID, app.ZERO_ENVIRONMENT_ID)
if err != nil {
handler.logger.Errorw("service err, GetAppMetaInfo", "err", err)
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
Expand Down Expand Up @@ -343,7 +343,7 @@ func (handler AppRestHandlerImpl) GetAppListByTeamIds(w http.ResponseWriter, r *
common.WriteJsonResp(w, err, projectWiseApps, http.StatusOK)
}

func (handler AppRestHandlerImpl) UpdateAppDescription(w http.ResponseWriter, r *http.Request) {
func (handler AppRestHandlerImpl) UpdateAppNote(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("token")
decoder := json.NewDecoder(r.Body)
userId, err := handler.userAuthService.GetLoggedInUser(r)
Expand Down
6 changes: 3 additions & 3 deletions api/restHandler/CoreAppRestHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ func (handler CoreAppRestHandlerImpl) CreateApp(w http.ResponseWriter, r *http.R
func (handler CoreAppRestHandlerImpl) buildAppMetadata(appId int) (*appBean.AppMetadata, error, int) {
handler.logger.Debugw("Getting app detail - meta data", "appId", appId)

appMetaInfo, err := handler.appCrudOperationService.GetAppMetaInfo(appId)
appMetaInfo, err := handler.appCrudOperationService.GetAppMetaInfo(appId, app.ZERO_INSTALLED_APP_ID, app.ZERO_ENVIRONMENT_ID)
if err != nil {
handler.logger.Errorw("service err, GetAppMetaInfo in GetAppAllDetail", "err", err, "appId", appId)
return nil, err, http.StatusInternalServerError
Expand Down Expand Up @@ -2328,7 +2328,7 @@ func (handler CoreAppRestHandlerImpl) GetAppWorkflow(w http.ResponseWriter, r *h
token := r.Header.Get("token")

// get app metadata for appId
appMetaInfo, err := handler.appCrudOperationService.GetAppMetaInfo(appId)
appMetaInfo, err := handler.appCrudOperationService.GetAppMetaInfo(appId, app.ZERO_INSTALLED_APP_ID, app.ZERO_ENVIRONMENT_ID)
if err != nil {
handler.logger.Errorw("service err, GetAppMetaInfo in GetAppWorkflow", "appId", appId, "err", err)
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
Expand Down Expand Up @@ -2379,7 +2379,7 @@ func (handler CoreAppRestHandlerImpl) GetAppWorkflowAndOverridesSample(w http.Re
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
return
}
app, err := handler.appCrudOperationService.GetAppMetaInfo(appId)
app, err := handler.appCrudOperationService.GetAppMetaInfo(appId, app.ZERO_INSTALLED_APP_ID, app.ZERO_ENVIRONMENT_ID)
if err != nil {
handler.logger.Errorw("service err, GetAppMetaInfo in GetAppAllDetail", "err", err)
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
Expand Down
4 changes: 2 additions & 2 deletions api/router/AppRouter.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func (router AppRouterImpl) InitAppRouter(appRouter *mux.Router) {

appRouter.Path("/min").HandlerFunc(router.handler.GetAppListByTeamIds).Methods("GET")

appRouter.Path("/description").
appRouter.Path("/note").
Methods("PUT").
HandlerFunc(router.handler.UpdateAppDescription)
HandlerFunc(router.handler.UpdateAppNote)
}
2 changes: 2 additions & 0 deletions cmd/external-app/wire.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ func InitializeApp() (*App, error) {
telemetry.NewPosthogClient,
delete2.NewDeleteServiceImpl,

pipelineConfig.NewMaterialRepositoryImpl,
wire.Bind(new(pipelineConfig.MaterialRepository), new(*pipelineConfig.MaterialRepositoryImpl)),
//appStatus
appStatus.NewAppStatusRepositoryImpl,
wire.Bind(new(appStatus.AppStatusRepository), new(*appStatus.AppStatusRepositoryImpl)),
Expand Down
3 changes: 2 additions & 1 deletion cmd/external-app/wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 19 additions & 9 deletions internal/sql/repository/AppListingRepository.go
Original file line number Diff line number Diff line change
Expand Up @@ -632,19 +632,29 @@ func (impl AppListingRepositoryImpl) makeAppStageStatus(stage int, stageName str
}

func (impl AppListingRepositoryImpl) FetchOtherEnvironment(appId int) ([]*bean.Environment, error) {
impl.Logger.Debug("reached at FetchOtherEnvironment:")

// other environment tab
//TODO : create new optimised query and need to use explain analyse for both queries
var otherEnvironments []*bean.Environment
query := "select OE.*,B.status as app_status " +
"FROM " +
"(SELECT p.environment_id,env.environment_name,env.description, p.last_deployed, env_app_m.app_metrics, env.default as prod, env_app_m.infra_metrics, p.deployment_app_delete_request from ( SELECT pl.id,pl.app_id,pl.environment_id,pl.deleted, pl.deployment_app_delete_request,MAX(pco.created_on) as last_deployed from pipeline pl LEFT JOIN pipeline_config_override pco on pco.pipeline_id = pl.id WHERE pl.app_id = ? and pl.deleted = FALSE GROUP BY pl.id) p INNER JOIN environment env on env.id=p.environment_id LEFT JOIN env_level_app_metrics env_app_m on env.id=env_app_m.env_id and p.app_id = env_app_m.app_id where p.app_id=? and p.deleted = FALSE AND env.active = TRUE GROUP BY 1,2,3,4,5,6,7,8) OE " +
" LEFT JOIN app_status B ON OE.environment_id = B.env_id AND B.app_id = ? ;"
impl.Logger.Debugw("other env query:", query)
_, err := impl.dbConnection.Query(&otherEnvironments, query, appId, appId, appId)
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
from (select *
from (select p.id as pipeline_id, p.app_id, cwr.started_on as last_deployed, cwr.triggered_by, cwr.id as latest_cd_workflow_runner_id,
cw.ci_artifact_id, p.environment_id, p.deployment_app_delete_request,
row_number() over (partition by p.id order by cwr.started_on desc) as max_started_on_rank
from (select * from pipeline where app_id = ? and deleted=?) as p
left join cd_workflow cw on cw.pipeline_id = p.id
left join cd_workflow_runner cwr on cwr.cd_workflow_id = cw.id
where cwr.workflow_type = ? or cwr.workflow_type is null) pcwrraw
where max_started_on_rank = 1) pcwr
INNER JOIN environment e on e.id = pcwr.environment_id
LEFT JOIN ci_artifact ca on ca.id = pcwr.ci_artifact_id
LEFT JOIN users u on u.id = pcwr.triggered_by
LEFT JOIN env_level_app_metrics elam on pcwr.environment_id = elam.env_id and pcwr.app_id = elam.app_id
LEFT JOIN app_status ap ON pcwr.environment_id = ap.env_id and pcwr.app_id=ap.app_id;`
_, err := impl.dbConnection.Query(&otherEnvironments, query, appId, false, "DEPLOY")
if err != nil {
impl.Logger.Error("error in fetching other environment", "error", err)
return nil, err
}
return otherEnvironments, nil
}
Expand Down
9 changes: 9 additions & 0 deletions internal/sql/repository/app/AppRepository.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/devtron-labs/devtron/pkg/team"
"github.com/go-pg/pg"
"go.uber.org/zap"
"time"
)

type App struct {
Expand All @@ -45,6 +46,7 @@ type AppRepository interface {
SaveWithTxn(pipelineGroup *App, tx *pg.Tx) error
Update(app *App) error
UpdateWithTxn(app *App, tx *pg.Tx) error
SetDescription(id int, description string, userId int32) error
FindActiveByName(appName string) (pipelineGroup *App, err error)
FindJobByDisplayName(appName string) (pipelineGroup *App, err error)
FindActiveListByName(appName string) ([]*App, error)
Expand Down Expand Up @@ -116,6 +118,13 @@ func (repo AppRepositoryImpl) UpdateWithTxn(app *App, tx *pg.Tx) error {
return err
}

func (repo AppRepositoryImpl) SetDescription(id int, description string, userId int32) error {
_, err := repo.dbConnection.Model((*App)(nil)).
Set("description = ?", description).Set("updated_by = ?", userId).Set("updated_on = ?", time.Now()).
Where("id = ?", id).Update()
return err
}

func (repo AppRepositoryImpl) FindActiveByName(appName string) (*App, error) {
pipelineGroup := &App{}
err := repo.dbConnection.
Expand Down
2 changes: 1 addition & 1 deletion internal/util/ArgoUtil/ArgoClient.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func (session *ArgoSession) DoRequest(clientRequest *ClientRequest) (resBody []b

func NewArgoSession(config *ArgoConfig, logger *zap.SugaredLogger) (session *ArgoSession, err error) {
/*location := "/api/v1/session"
baseUrl, err := url.Parse(config.Url)
baseUrl, err := url.Parse(config.RedirectionUrl)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion internal/util/GitService.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import (

const (
GIT_WORKING_DIR = "/tmp/gitops/"
GetRepoUrlStage = "Get Repo Url"
GetRepoUrlStage = "Get Repo RedirectionUrl"
CreateRepoStage = "Create Repo"
CloneHttpStage = "Clone Http"
CreateReadmeStage = "Create Readme"
Expand Down