Skip to content

Commit e084b22

Browse files
Badal Kumar PrustyBadal Kumar Prusty
authored andcommitted
2 parents 9fc2637 + 1546c20 commit e084b22

File tree

211 files changed

+24164
-793
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

211 files changed

+24164
-793
lines changed

.github/workflows/helm-chart-lint.yaml

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,24 +20,47 @@ jobs:
2020
charts:
2121
- added|modified: 'scripts/devtron-reference-helm-charts/**/templates/**'
2222
- added|modified: 'charts/devtron/**/templates/**'
23+
files:
24+
- added|modified: 'charts/devtron/*'
25+
ref_chart:
26+
- added|modified: 'scripts/devtron-reference-helm-charts/*/*'
2327
- run: echo ${{ steps.filter.outputs.charts }}
28+
- run: echo ${{ steps.filter.outputs.files }}
2429
- uses: actions/setup-python@v2
2530
- uses: jannekem/run-python-script-action@v1
2631
id: python
2732
with:
2833
script: |
2934
string='${{ steps.filter.outputs.charts_files }}'
30-
location=string.split("templates",1)[0]
31-
print(location)
32-
set_output("chart_path",location)
35+
devtron_chart='${{ steps.filter.outputs.files_files }}'
36+
ref_chart='${{ steps.filter.outputs.ref_chart_files }}'
37+
print(string)
38+
print(devtron_chart)
39+
print(ref_chart)
40+
split_ref_chart=ref_chart.split("/")
41+
print(split_ref_chart)
42+
if (string) :
43+
location=string.split("templates",1)[0]
44+
print(location)
45+
set_output("chart_path",location)
46+
elif (devtron_chart):
47+
set_output("chart_path","charts/devtron/")
48+
else :
49+
split_ref_chart=split_ref_chart[:-1]
50+
print("/".join(split_ref_chart))
51+
split_ref_chart="/".join(split_ref_chart)
52+
split_ref_chart+="/"
53+
set_output("chart_path",split_ref_chart)
3354
- run: echo ${{ steps.python.outputs.chart_path }}
3455
- name: Print errors
3556
if: steps.script.outputs.error == 'true'
3657
run: |
3758
printenv "SCRIPT_STDOUT"
3859
printenv "SCRIPT_STDERR"
60+
- name: helm build
61+
run: cd ./${{ steps.python.outputs.chart_path }} && helm dependency build
3962
- name: helm-check
4063
uses: igabaydulin/[email protected]
4164
env:
4265
CHART_LOCATION: ./${{ steps.python.outputs.chart_path }}
43-
CHART_VALUES: ./${{ steps.python.outputs.chart_path }}values.yaml
66+
CHART_VALUES: ./${{ steps.python.outputs.chart_path }}values.yaml

Makefile

100644100755
File mode changed.

Wire.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,10 @@ func InitializeApp() (*App, error) {
374374
wire.Bind(new(notifier.SlackNotificationService), new(*notifier.SlackNotificationServiceImpl)),
375375
repository.NewSlackNotificationRepositoryImpl,
376376
wire.Bind(new(repository.SlackNotificationRepository), new(*repository.SlackNotificationRepositoryImpl)),
377+
notifier.NewWebhookNotificationServiceImpl,
378+
wire.Bind(new(notifier.WebhookNotificationService), new(*notifier.WebhookNotificationServiceImpl)),
379+
repository.NewWebhookNotificationRepositoryImpl,
380+
wire.Bind(new(repository.WebhookNotificationRepository), new(*repository.WebhookNotificationRepositoryImpl)),
377381

378382
notifier.NewNotificationConfigServiceImpl,
379383
wire.Bind(new(notifier.NotificationConfigService), new(*notifier.NotificationConfigServiceImpl)),

api/appStore/AppStoreRouter.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ func (router AppStoreRouterImpl) Init(configRouter *mux.Router) {
7676
configRouter.Path("/installed-app/detail").Queries("installed-app-id", "{installed-app-id}").Queries("env-id", "{env-id}").
7777
HandlerFunc(router.deployRestHandler.FetchAppDetailsForInstalledApp).
7878
Methods("GET")
79+
configRouter.Path("/installed-app/delete/{installedAppId}/non-cascade").
80+
HandlerFunc(router.deployRestHandler.DeleteArgoInstalledAppWithNonCascade).
81+
Methods("DELETE")
7982
configRouter.Path("/installed-app/detail/v2").Queries("installed-app-id", "{installed-app-id}").Queries("env-id", "{env-id}").
8083
HandlerFunc(router.deployRestHandler.FetchAppDetailsForInstalledAppV2).
8184
Methods("GET")

api/appStore/InstalledAppRestHandler.go

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

2020
import (
21+
"context"
2122
"encoding/json"
2223
"errors"
2324
"fmt"
@@ -36,6 +37,7 @@ import (
3637
"github.com/devtron-labs/devtron/pkg/cluster"
3738
"github.com/devtron-labs/devtron/pkg/user"
3839
"github.com/devtron-labs/devtron/pkg/user/casbin"
40+
"github.com/devtron-labs/devtron/util"
3941
"github.com/devtron-labs/devtron/util/argo"
4042
"github.com/devtron-labs/devtron/util/rbac"
4143
"github.com/devtron-labs/devtron/util/response"
@@ -55,6 +57,7 @@ type InstalledAppRestHandler interface {
5557
CheckAppExists(w http.ResponseWriter, r *http.Request)
5658
DefaultComponentInstallation(w http.ResponseWriter, r *http.Request)
5759
FetchAppDetailsForInstalledApp(w http.ResponseWriter, r *http.Request)
60+
DeleteArgoInstalledAppWithNonCascade(w http.ResponseWriter, r *http.Request)
5861
FetchAppDetailsForInstalledAppV2(w http.ResponseWriter, r *http.Request)
5962
FetchResourceTree(w http.ResponseWriter, r *http.Request)
6063
FetchResourceTreeForACDApp(w http.ResponseWriter, r *http.Request)
@@ -66,6 +69,7 @@ type InstalledAppRestHandlerImpl struct {
6669
userAuthService user.UserService
6770
enforcer casbin.Enforcer
6871
enforcerUtil rbac.EnforcerUtil
72+
enforcerUtilHelm rbac.EnforcerUtilHelm
6973
installedAppService service.InstalledAppService
7074
validator *validator.Validate
7175
clusterService cluster.ClusterService
@@ -79,7 +83,7 @@ type InstalledAppRestHandlerImpl struct {
7983
}
8084

8185
func NewInstalledAppRestHandlerImpl(Logger *zap.SugaredLogger, userAuthService user.UserService,
82-
enforcer casbin.Enforcer, enforcerUtil rbac.EnforcerUtil, installedAppService service.InstalledAppService,
86+
enforcer casbin.Enforcer, enforcerUtil rbac.EnforcerUtil, enforcerUtilHelm rbac.EnforcerUtilHelm, installedAppService service.InstalledAppService,
8387
validator *validator.Validate, clusterService cluster.ClusterService, acdServiceClient application.ServiceClient,
8488
appStoreDeploymentService service.AppStoreDeploymentService, helmAppClient client.HelmAppClient, helmAppService client.HelmAppService,
8589
argoUserService argo.ArgoUserService,
@@ -91,6 +95,7 @@ func NewInstalledAppRestHandlerImpl(Logger *zap.SugaredLogger, userAuthService u
9195
userAuthService: userAuthService,
9296
enforcer: enforcer,
9397
enforcerUtil: enforcerUtil,
98+
enforcerUtilHelm: enforcerUtilHelm,
9499
installedAppService: installedAppService,
95100
validator: validator,
96101
clusterService: clusterService,
@@ -429,6 +434,82 @@ func (handler *InstalledAppRestHandlerImpl) FetchNotesForArgoInstalledApp(w http
429434
common.WriteJsonResp(w, err, &bean2.Notes{Notes: notes}, http.StatusOK)
430435

431436
}
437+
438+
func (handler *InstalledAppRestHandlerImpl) DeleteArgoInstalledAppWithNonCascade(w http.ResponseWriter, r *http.Request) {
439+
token := r.Header.Get("token")
440+
userId, err := handler.userAuthService.GetLoggedInUser(r)
441+
if userId == 0 || err != nil {
442+
common.WriteJsonResp(w, err, nil, http.StatusUnauthorized)
443+
return
444+
}
445+
vars := mux.Vars(r)
446+
installedAppId, err := strconv.Atoi(vars["installedAppId"])
447+
if err != nil {
448+
handler.Logger.Errorw("request err, DeleteArgoInstalledAppWithNonCascade", "err", err, "installedAppId", installedAppId)
449+
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
450+
return
451+
}
452+
handler.Logger.Infow("request payload, delete app", "appId", installedAppId)
453+
v := r.URL.Query()
454+
forceDelete := false
455+
force := v.Get("force")
456+
if len(force) > 0 {
457+
forceDelete, err = strconv.ParseBool(force)
458+
if err != nil {
459+
handler.Logger.Errorw("request err, NonCascadeDeleteCdPipeline", "err", err)
460+
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
461+
return
462+
}
463+
}
464+
installedApp, err := handler.appStoreDeploymentService.GetInstalledApp(installedAppId)
465+
if err != nil {
466+
handler.Logger.Error("request err, NonCascadeDeleteCdPipeline", "err", err)
467+
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
468+
return
469+
}
470+
if util.IsBaseStack() || util.IsHelmApp(installedApp.AppOfferingMode) || util2.IsHelmApp(installedApp.DeploymentAppType) {
471+
handler.Logger.Errorw("request err, NonCascadeDeleteCdPipeline", "err", fmt.Errorf("nocascade delete is not supported for %s", installedApp.AppName))
472+
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
473+
return
474+
}
475+
//rbac block starts from here
476+
rbacObject, rbacObject2 := handler.enforcerUtil.GetHelmObjectByAppNameAndEnvId(installedApp.AppName, installedApp.EnvironmentId)
477+
ok := handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionDelete, rbacObject) || handler.enforcer.Enforce(token, casbin.ResourceHelmApp, casbin.ActionDelete, rbacObject2)
478+
if !ok {
479+
common.WriteJsonResp(w, fmt.Errorf("unauthorized user"), nil, http.StatusForbidden)
480+
return
481+
}
482+
//rback block ends here
483+
acdToken, err := handler.argoUserService.GetLatestDevtronArgoCdUserToken()
484+
if err != nil {
485+
handler.Logger.Errorw("error in getting acd token", "err", err)
486+
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
487+
return
488+
}
489+
ctx := context.WithValue(r.Context(), "token", acdToken)
490+
request := &appStoreBean.InstallAppVersionDTO{}
491+
request.InstalledAppId = installedAppId
492+
request.AppName = installedApp.AppName
493+
request.AppId = installedApp.AppId
494+
request.EnvironmentId = installedApp.EnvironmentId
495+
request.UserId = userId
496+
request.ForceDelete = forceDelete
497+
request.NonCascadeDelete = true
498+
request.AppOfferingMode = installedApp.AppOfferingMode
499+
request.ClusterId = installedApp.ClusterId
500+
request.Namespace = installedApp.Namespace
501+
request.AcdPartialDelete = true
502+
503+
request, err = handler.appStoreDeploymentService.DeleteInstalledApp(ctx, request)
504+
if err != nil {
505+
handler.Logger.Errorw("service err, DeleteInstalledApp", "err", err, "installAppId", installedAppId)
506+
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
507+
return
508+
}
509+
common.WriteJsonResp(w, nil, nil, http.StatusOK)
510+
511+
}
512+
432513
func (handler *InstalledAppRestHandlerImpl) checkNotesAuth(token string, appName string, envId int) bool {
433514

434515
object, object2 := handler.enforcerUtil.GetHelmObjectByAppNameAndEnvId(appName, envId)

api/appStore/deployment/AppStoreDeploymentRestHandler.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,12 +256,25 @@ func (handler AppStoreDeploymentRestHandlerImpl) DeleteInstalledApp(w http.Respo
256256
v := r.URL.Query()
257257
forceDelete := false
258258
force := v.Get("force")
259+
cascadeDelete := true
260+
cascade := v.Get("cascade")
261+
if len(force) > 0 && len(cascade) > 0 {
262+
handler.Logger.Errorw("request err, PatchCdPipeline", "err", fmt.Errorf("cannot perform both cascade and force delete"), "installAppId", installAppId)
263+
common.WriteJsonResp(w, fmt.Errorf("invalid query params! cannot perform both force and cascade together"), nil, http.StatusBadRequest)
264+
return
265+
}
259266
if len(force) > 0 {
260267
forceDelete, err = strconv.ParseBool(force)
261268
if err != nil {
262269
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
263270
return
264271
}
272+
} else if len(cascade) > 0 {
273+
cascadeDelete, err = strconv.ParseBool(cascade)
274+
if err != nil {
275+
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
276+
return
277+
}
265278
}
266279
partialDelete := false
267280
partialDeleteStr := v.Get("partialDelete")
@@ -311,6 +324,7 @@ func (handler AppStoreDeploymentRestHandlerImpl) DeleteInstalledApp(w http.Respo
311324
request.EnvironmentId = installedApp.EnvironmentId
312325
request.UserId = userId
313326
request.ForceDelete = forceDelete
327+
request.NonCascadeDelete = !cascadeDelete
314328
request.AppOfferingMode = installedApp.AppOfferingMode
315329
request.ClusterId = installedApp.ClusterId
316330
request.Namespace = installedApp.Namespace

api/cluster/EnvironmentRestHandler.go

Lines changed: 89 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,11 @@
1818
package cluster
1919

2020
import (
21+
"context"
2122
"encoding/json"
23+
"github.com/devtron-labs/devtron/internal/util"
24+
"github.com/devtron-labs/devtron/util/k8s"
25+
"k8s.io/client-go/kubernetes"
2226
"net/http"
2327
"strconv"
2428
"strings"
@@ -49,12 +53,14 @@ type EnvironmentRestHandler interface {
4953
FindById(w http.ResponseWriter, r *http.Request)
5054
GetEnvironmentListForAutocomplete(w http.ResponseWriter, r *http.Request)
5155
GetCombinedEnvironmentListForDropDown(w http.ResponseWriter, r *http.Request)
56+
GetEnvironmentConnection(w http.ResponseWriter, r *http.Request)
5257
DeleteEnvironment(w http.ResponseWriter, r *http.Request)
5358
GetCombinedEnvironmentListForDropDownByClusterIds(w http.ResponseWriter, r *http.Request)
5459
}
5560

5661
type EnvironmentRestHandlerImpl struct {
5762
environmentClusterMappingsService request.EnvironmentService
63+
k8sApplicationService k8s.K8sApplicationService
5864
logger *zap.SugaredLogger
5965
userService user.UserService
6066
validator *validator.Validate
@@ -63,7 +69,12 @@ type EnvironmentRestHandlerImpl struct {
6369
cfg *bean.Config
6470
}
6571

66-
func NewEnvironmentRestHandlerImpl(svc request.EnvironmentService, logger *zap.SugaredLogger, userService user.UserService,
72+
type ClusterReachableResponse struct {
73+
ClusterReachable bool `json:"clusterReachable"`
74+
ClusterName string `json:"clusterName"`
75+
}
76+
77+
func NewEnvironmentRestHandlerImpl(svc request.EnvironmentService, k8sApplicationService k8s.K8sApplicationService, logger *zap.SugaredLogger, userService user.UserService,
6778
validator *validator.Validate, enforcer casbin.Enforcer,
6879
deleteService delete2.DeleteService,
6980
) *EnvironmentRestHandlerImpl {
@@ -76,6 +87,7 @@ func NewEnvironmentRestHandlerImpl(svc request.EnvironmentService, logger *zap.S
7687
logger.Infow("evironment rest handler initialized", "ignoreAuthCheckValue", cfg.IgnoreAuthCheck)
7788
return &EnvironmentRestHandlerImpl{
7889
environmentClusterMappingsService: svc,
90+
k8sApplicationService: k8sApplicationService,
7991
logger: logger,
8092
userService: userService,
8193
validator: validator,
@@ -298,7 +310,12 @@ func (impl EnvironmentRestHandlerImpl) GetEnvironmentListForAutocomplete(w http.
298310
return
299311
}
300312
start := time.Now()
301-
environments, err := impl.environmentClusterMappingsService.GetEnvironmentListForAutocomplete()
313+
showDeploymentOptionsParam := false
314+
param := r.URL.Query().Get("showDeploymentOptions")
315+
if param != "" {
316+
showDeploymentOptionsParam, _ = strconv.ParseBool(param)
317+
}
318+
environments, err := impl.environmentClusterMappingsService.GetEnvironmentListForAutocomplete(showDeploymentOptionsParam)
302319
if err != nil {
303320
impl.logger.Errorw("service err, GetEnvironmentListForAutocomplete", "err", err)
304321
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
@@ -460,3 +477,73 @@ func (impl EnvironmentRestHandlerImpl) GetCombinedEnvironmentListForDropDownByCl
460477
}
461478
common.WriteJsonResp(w, err, clusters, http.StatusOK)
462479
}
480+
481+
func (impl EnvironmentRestHandlerImpl) GetEnvironmentConnection(w http.ResponseWriter, r *http.Request) {
482+
//token := r.Header.Get("token")
483+
vars := mux.Vars(r)
484+
envIdString := vars["envId"]
485+
envId, err := strconv.Atoi(envIdString)
486+
if err != nil {
487+
impl.logger.Errorw("failed to extract clusterId from param", "error", err, "clusterId", envIdString)
488+
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
489+
return
490+
}
491+
userId, err := impl.userService.GetLoggedInUser(r)
492+
if userId == 0 || err != nil {
493+
impl.logger.Errorw("user not authorized", "error", err, "userId", userId)
494+
common.WriteJsonResp(w, err, "Unauthorized User", http.StatusUnauthorized)
495+
return
496+
}
497+
bean, err := impl.environmentClusterMappingsService.FindById(envId)
498+
if err != nil {
499+
impl.logger.Errorw("request err, FindById", "err", err, "envId", envId)
500+
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
501+
return
502+
}
503+
clusterBean, err := impl.environmentClusterMappingsService.FindClusterByEnvId(bean.ClusterId)
504+
if err != nil {
505+
impl.logger.Errorw("request err, FindById", "err", err, "envId", envId)
506+
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
507+
return
508+
}
509+
// RBAC enforcer applying
510+
token := r.Header.Get("token")
511+
if ok := impl.enforcer.Enforce(token, casbin.ResourceGlobalEnvironment, casbin.ActionGet, strings.ToLower(bean.EnvironmentIdentifier)); !ok {
512+
common.WriteJsonResp(w, errors.New("unauthorized"), nil, http.StatusForbidden)
513+
return
514+
}
515+
//RBAC enforcer Ends
516+
// getting restConfig and clientSet outside the goroutine because we don't want to call goroutine func with receiver function
517+
restConfig, err := impl.k8sApplicationService.GetRestConfigByClusterId(context.Background(), clusterBean.Id)
518+
if err != nil {
519+
impl.logger.Errorw("error in getting restConfig by cluster", "err", err, "clusterId", clusterBean.Id)
520+
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
521+
return
522+
}
523+
k8sHttpClient, err := util.OverrideK8sHttpClientWithTracer(restConfig)
524+
if err != nil {
525+
impl.logger.Errorw("service err, OverrideK8sHttpClientWithTracer", "err", err, "restConfig", restConfig)
526+
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
527+
return
528+
}
529+
k8sClientSet, err := kubernetes.NewForConfigAndClient(restConfig, k8sHttpClient)
530+
if err != nil {
531+
impl.logger.Errorw("error in getting client set by rest config", "err", err, "restConfig", restConfig)
532+
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
533+
return
534+
}
535+
responseObj := &ClusterReachableResponse{
536+
ClusterReachable: true,
537+
ClusterName: clusterBean.ClusterName,
538+
}
539+
err = impl.k8sApplicationService.FetchConnectionStatusForCluster(k8sClientSet, clusterBean.Id)
540+
if err != nil {
541+
responseObj.ClusterReachable = false
542+
}
543+
//updating the cluster connection error to db
544+
mapObj := map[int]error{
545+
clusterBean.Id: err,
546+
}
547+
impl.environmentClusterMappingsService.HandleErrorInClusterConnections([]*request.ClusterBean{clusterBean}, mapObj, true)
548+
common.WriteJsonResp(w, nil, responseObj, http.StatusOK)
549+
}

api/cluster/EnvironmentRouter.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,5 +71,7 @@ func (impl EnvironmentRouterImpl) InitEnvironmentClusterMappingsRouter(environme
7171
environmentClusterMappingsRouter.Path("/namespace/autocomplete").
7272
Methods("GET").
7373
HandlerFunc(impl.environmentClusterMappingsRestHandler.GetCombinedEnvironmentListForDropDownByClusterIds)
74-
74+
environmentClusterMappingsRouter.Path("/{envId}/connection").
75+
Methods("GET").
76+
HandlerFunc(impl.environmentClusterMappingsRestHandler.GetEnvironmentConnection)
7577
}

0 commit comments

Comments
 (0)