Skip to content

Commit 8581fbe

Browse files
author
kishan789dev
committed
Merge branch 'main' into rback-related-bug
2 parents 55b0138 + 190ea04 commit 8581fbe

File tree

170 files changed

+5513
-3503
lines changed

Some content is hidden

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

170 files changed

+5513
-3503
lines changed

.gitbook.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,4 +76,4 @@ redirects:
7676
user-guide/use-cases/untitled-3: user-guide/use-cases/connect-django-with-mysql-database.md
7777
global-configurations/api-token: user-guide/global-configurations/authorization/api-tokens.md
7878
user-guide/creating-application/workflow/ci-pipeline2: user-guide/creating-application/workflow/ci-pipeline.md
79-
79+
user-guide/clusters: user-guide/resource-browser.md

Makefile

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,17 +40,13 @@ test-unit:
4040
go test ./pkg/pipeline
4141

4242
test-integration:
43-
export INTEGRATION_TEST_ENV_ID=$(docker run --env TEST_BRANCH=$TEST_BRANCH --env LATEST_HASH=$LATEST_HASH --privileged -d --name dind-test -v $PWD/tests/integrationTesting/:/tmp/ docker:dind)
44-
docker exec ${INTEGRATION_TEST_ENV_ID} sh /tmp/create-test-env.sh
45-
docker exec ${INTEGRATION_TEST_ENV_ID} sh /tests/integrationTesting/run-integration-test.sh
46-
43+
docker run --env-file=wireNilChecker.env --privileged -d --name dind-test -v $(PWD)/:/wirenil/:ro -v $(PWD)/temp/:/tempfile docker:dind
44+
docker exec dind-test sh -c "mkdir test && cp -r wirenil/* test/ && ./test/tests/integrationTesting/exportEnvsExecuteWireNilChecker.sh"
4745
run: build
4846
./devtron
49-
5047
.PHONY: build
5148
docker-build-image: build
5249
docker build -t devtron:$(TAG) .
53-
5450
.PHONY: build, all, wire, clean, run, set-docker-build-env, docker-build-push, devtron,
5551
docker-build-push: docker-build-image
5652
docker tag devtron:${TAG} ${REGISTRY}/devtron:${TAG}

WiringNilCheck.go

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"os"
7+
"reflect"
8+
"strings"
9+
"unsafe"
10+
)
11+
12+
func CheckIfNilInWire() {
13+
app, err := InitializeApp()
14+
if err != nil {
15+
log.Panic(err)
16+
}
17+
nilFieldsMap := make(map[string]bool)
18+
checkNilFields(app, nilFieldsMap)
19+
fmt.Println("NIL Fields present in impls are: ", nilFieldsMap)
20+
//Writes the length of nilFieldsMap to a file (e.g., output.env) so that we can export this file's data in a pre-CI pipeline bash script and fail the pre-CI pipeline if the length of nilFieldsMap is greater than zero.
21+
err = writeResultToFile(len(nilFieldsMap))
22+
if err != nil {
23+
return
24+
}
25+
}
26+
27+
func checkNilFields(obj interface{}, nilObjMap map[string]bool) {
28+
val := reflect.ValueOf(obj)
29+
if val.Kind() == reflect.Ptr {
30+
val = val.Elem()
31+
}
32+
if val.Kind() != reflect.Struct {
33+
return
34+
}
35+
valName := val.Type().Name()
36+
for i := 0; i < val.NumField(); i++ {
37+
field := val.Field(i)
38+
fieldName := val.Type().Field(i).Name
39+
pkgPath := val.Type().PkgPath()
40+
if pkgPath != "main" && !strings.Contains(pkgPath, "devtron-labs/devtron") {
41+
//package not from this repo, ignoring
42+
continue
43+
}
44+
if skipUnnecessaryFieldsForCheck(fieldName, valName) { // skip unnecessary fileds and values
45+
continue
46+
}
47+
if !canFieldTypeBeNil(field) { // field can not be nil, skip
48+
continue
49+
} else if field.IsNil() { // check if the field is nil
50+
mapEntry := fmt.Sprintf("%s.%s", valName, fieldName)
51+
nilObjMap[mapEntry] = true
52+
continue
53+
}
54+
if canSkipFieldStructCheck(fieldName, valName) {
55+
continue
56+
}
57+
if !isExported(fieldName) && !field.CanInterface() {
58+
unexportedField := GetUnexportedField(field)
59+
checkNilFields(unexportedField, nilObjMap)
60+
} else {
61+
// Recurse
62+
checkNilFields(field.Interface(), nilObjMap)
63+
}
64+
}
65+
}
66+
67+
func canFieldTypeBeNil(field reflect.Value) bool {
68+
kind := field.Kind()
69+
switch kind {
70+
case reflect.Chan, reflect.Func, reflect.Map, reflect.Pointer, reflect.UnsafePointer,
71+
reflect.Interface, reflect.Slice:
72+
return true
73+
default: //other types can not be nil
74+
return false
75+
}
76+
}
77+
78+
func canSkipFieldStructCheck(fieldName, valName string) bool {
79+
fieldName = strings.ToLower(fieldName)
80+
valName = strings.ToLower(valName)
81+
if valName == "githubclient" && (fieldName == "client" || fieldName == "gitopshelper") {
82+
return true
83+
}
84+
for _, str := range []string{"logger", "dbconnection", "syncedenforcer"} {
85+
if fieldName == str {
86+
return true
87+
}
88+
}
89+
return false
90+
}
91+
92+
func skipUnnecessaryFieldsForCheck(fieldName, valName string) bool {
93+
fieldName = strings.ToLower(fieldName)
94+
valName = strings.ToLower(valName)
95+
if valName == "cicdconfig" {
96+
return true
97+
}
98+
fieldAndValName := map[string][]string{
99+
"app": {"enforcerv2", "server"},
100+
"gitfactory": {"client"},
101+
"argocdconnectionmanagerimpl": {"argocdsettings"},
102+
"enforcerimpl": {"cache", "enforcerv2"},
103+
"helmappclientimpl": {"applicationserviceclient"},
104+
"modulecronserviceimpl": {"cron"},
105+
"oteltracingserviceimpl": {"traceprovider"},
106+
"terminalaccessrepositoryimpl": {"templatescache"},
107+
}
108+
if _, ok := fieldAndValName[valName]; ok {
109+
for _, ignoreFieldName := range fieldAndValName[valName] {
110+
if ignoreFieldName == fieldName {
111+
return true
112+
}
113+
}
114+
}
115+
return false
116+
}
117+
func GetUnexportedField(field reflect.Value) interface{} {
118+
return reflect.NewAt(field.Type(), unsafe.Pointer(field.UnsafeAddr())).Elem().Interface()
119+
}
120+
121+
func isExported(fieldName string) bool {
122+
return strings.ToUpper(fieldName[0:1]) == fieldName[0:1]
123+
}
124+
125+
func writeResultToFile(data int) error {
126+
file, err := os.Create("/test/output.env")
127+
if err != nil {
128+
log.Println("Failed to create file:", err)
129+
return err
130+
}
131+
defer file.Close()
132+
_, err = file.WriteString(fmt.Sprintf("OUTPUT=%d", data))
133+
if err != nil {
134+
log.Println("Failed to write to file:", err)
135+
return err
136+
}
137+
return nil
138+
}

api/appStore/InstalledAppRestHandler.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/devtron-labs/devtron/pkg/appStore/installedApp/service/FullMode"
2727
"github.com/devtron-labs/devtron/pkg/appStore/installedApp/service/FullMode/deploymentTypeChange"
2828
"github.com/devtron-labs/devtron/pkg/appStore/installedApp/service/FullMode/resource"
29+
util3 "github.com/devtron-labs/devtron/pkg/appStore/util"
2930
"github.com/devtron-labs/devtron/pkg/bean"
3031
"net/http"
3132
"strconv"
@@ -603,6 +604,10 @@ func (handler *InstalledAppRestHandlerImpl) FetchAppDetailsForInstalledApp(w htt
603604
common.WriteJsonResp(w, err, "App not found in database", http.StatusBadRequest)
604605
return
605606
}
607+
if util3.IsExternalChartStoreApp(installedApp.App.DisplayName) {
608+
//this is external app case where app_name is a unique identifier, and we want to fetch resource based on display_name
609+
handler.installedAppService.ChangeAppNameToDisplayNameForInstalledApp(installedApp)
610+
}
606611

607612
appDetail, err := handler.installedAppService.FindAppDetailsForAppstoreApplication(installedAppId, envId)
608613
if err != nil {
@@ -724,6 +729,10 @@ func (handler *InstalledAppRestHandlerImpl) FetchResourceTree(w http.ResponseWri
724729
common.WriteJsonResp(w, err, "App not found in database", http.StatusBadRequest)
725730
return
726731
}
732+
if util3.IsExternalChartStoreApp(installedApp.App.DisplayName) {
733+
//this is external app case where app_name is a unique identifier, and we want to fetch resource based on display_name
734+
handler.installedAppService.ChangeAppNameToDisplayNameForInstalledApp(installedApp)
735+
}
727736
if installedApp.Environment.IsVirtualEnvironment {
728737
common.WriteJsonResp(w, nil, nil, http.StatusOK)
729738
return

api/appStore/deployment/CommonDeploymentRestHandler.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ func (handler *CommonDeploymentRestHandlerImpl) getAppOfferingMode(installedAppI
9393
err = &util.ApiError{HttpStatusCode: http.StatusBadRequest, UserMessage: "invalid app id"}
9494
return appOfferingMode, installedAppDto, err
9595
}
96-
installedAppDto, err = handler.installedAppService.GetInstalledAppByClusterNamespaceAndName(appIdentifier.ClusterId, appIdentifier.Namespace, appIdentifier.ReleaseName)
96+
uniqueAppName := appIdentifier.GetUniqueAppNameIdentifier()
97+
installedAppDto, err = handler.installedAppService.GetInstalledAppByClusterNamespaceAndName(appIdentifier.ClusterId, appIdentifier.Namespace, uniqueAppName)
9798
if err != nil {
9899
err = &util.ApiError{HttpStatusCode: http.StatusBadRequest, UserMessage: "unable to find app in database"}
99100
return appOfferingMode, installedAppDto, err

api/auth/user/UserRestHandler.go

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ func (handler UserRestHandlerImpl) CreateUser(w http.ResponseWriter, r *http.Req
191191
}
192192
//RBAC enforcer Ends
193193

194-
res, err := handler.userService.CreateUser(&userInfo, token, handler.CheckManagerAuth)
194+
res, restrictedGroups, err := handler.userService.CreateUser(&userInfo, token, handler.CheckManagerAuth)
195195
if err != nil {
196196
handler.logger.Errorw("service err, CreateUser", "err", err, "payload", userInfo)
197197
if _, ok := err.(*util.ApiError); ok {
@@ -203,7 +203,22 @@ func (handler UserRestHandlerImpl) CreateUser(w http.ResponseWriter, r *http.Req
203203
return
204204
}
205205

206-
common.WriteJsonResp(w, err, res, http.StatusOK)
206+
if len(restrictedGroups) == 0 {
207+
common.WriteJsonResp(w, err, res, http.StatusOK)
208+
} else {
209+
errorMessageForGroupsWithoutSuperAdmin, errorMessageForGroupsWithSuperAdmin := helper.CreateErrorMessageForUserRoleGroups(restrictedGroups)
210+
211+
if len(restrictedGroups) != len(userInfo.UserRoleGroup) {
212+
// warning
213+
message := fmt.Errorf("User permissions added partially. %s%s", errorMessageForGroupsWithoutSuperAdmin, errorMessageForGroupsWithSuperAdmin)
214+
common.WriteJsonResp(w, message, nil, http.StatusExpectationFailed)
215+
216+
} else {
217+
//error
218+
message := fmt.Errorf("Permission could not be added. %s%s", errorMessageForGroupsWithoutSuperAdmin, errorMessageForGroupsWithSuperAdmin)
219+
common.WriteJsonResp(w, message, nil, http.StatusBadRequest)
220+
}
221+
}
207222
}
208223

209224
func (handler UserRestHandlerImpl) UpdateUser(w http.ResponseWriter, r *http.Request) {
@@ -252,16 +267,16 @@ func (handler UserRestHandlerImpl) UpdateUser(w http.ResponseWriter, r *http.Req
252267
if len(restrictedGroups) == 0 {
253268
common.WriteJsonResp(w, err, res, http.StatusOK)
254269
} else {
255-
groups := strings.Join(restrictedGroups, ", ")
270+
errorMessageForGroupsWithoutSuperAdmin, errorMessageForGroupsWithSuperAdmin := helper.CreateErrorMessageForUserRoleGroups(restrictedGroups)
256271

257272
if rolesChanged || groupsModified {
258273
// warning
259-
message := fmt.Errorf("User permissions updated partially. Group(s): " + groups + " could not be added/removed. You do not have manager permission for some or all projects in these groups.")
274+
message := fmt.Errorf("User permissions updated partially. %s%s", errorMessageForGroupsWithoutSuperAdmin, errorMessageForGroupsWithSuperAdmin)
260275
common.WriteJsonResp(w, message, nil, http.StatusExpectationFailed)
261276

262277
} else {
263278
//error
264-
message := fmt.Errorf("Permission could not be added/removed: You do not have manager permission for some or all projects in group(s): " + groups + ".")
279+
message := fmt.Errorf("Permission could not be added/removed. %s%s", errorMessageForGroupsWithoutSuperAdmin, errorMessageForGroupsWithSuperAdmin)
265280
common.WriteJsonResp(w, message, nil, http.StatusBadRequest)
266281
}
267282
}

api/bean/UserRequest.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,11 @@ type RoleGroupListingResponse struct {
131131
TotalCount int `json:"totalCount"`
132132
}
133133

134+
type RestrictedGroup struct {
135+
Group string
136+
HasSuperAdminPermission bool
137+
}
138+
134139
type ListingRequest struct {
135140
SearchKey string `json:"searchKey"`
136141
SortOrder bean.SortOrder `json:"sortOrder"`

api/helm-app/HelmAppRestHandler.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,15 +224,15 @@ func (handler *HelmAppRestHandlerImpl) GetReleaseInfo(w http.ResponseWriter, r *
224224
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
225225
return
226226
}
227-
installedApp, err := handler.installedAppService.GetInstalledAppByClusterNamespaceAndName(appIdentifier.ClusterId, appIdentifier.Namespace, appIdentifier.ReleaseName)
227+
installedAppVersionDto, err := handler.installedAppService.GetReleaseInfo(appIdentifier)
228228
if err != nil {
229229
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
230230
return
231231
}
232232

233233
res := &bean.ReleaseAndInstalledAppInfo{
234234
ReleaseInfo: releaseInfo,
235-
InstalledAppInfo: bean.ConvertToInstalledAppInfo(installedApp),
235+
InstalledAppInfo: bean.ConvertToInstalledAppInfo(installedAppVersionDto),
236236
}
237237

238238
common.WriteJsonResp(w, err, res, http.StatusOK)

api/helm-app/HelmAppRouter.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ func (impl *HelmAppRouterImpl) InitAppListRouter(helmRouter *mux.Router) {
2929
helmRouter.Path("/hibernate").HandlerFunc(impl.helmAppRestHandler.Hibernate).Methods("POST")
3030
helmRouter.Path("/unhibernate").HandlerFunc(impl.helmAppRestHandler.UnHibernate).Methods("POST")
3131

32+
// GetReleaseInfo used only for external apps
3233
helmRouter.Path("/release-info").Queries("appId", "{appId}").
3334
HandlerFunc(impl.helmAppRestHandler.GetReleaseInfo).Methods("GET")
3435

0 commit comments

Comments
 (0)