Skip to content

Commit be53fe5

Browse files
Merge branch 'main' into feature-release-v2
2 parents 75aaff3 + 190ea04 commit be53fe5

28 files changed

+620
-64
lines changed

.gitbook.yaml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,5 +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-
usage/clusters: usage/resource-browser
80-
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+
}

client/proxy/ProxyRouter.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ type ProxyConnection struct {
2222
}
2323

2424
type Config struct {
25-
ProxyServiceConfig string `env:"PROXY_SERVICE_CONFIG" envDefault:""`
25+
ProxyServiceConfig string `env:"PROXY_SERVICE_CONFIG" envDefault:"{}"`
2626
}
2727

2828
func GetProxyConfig() (*Config, error) {
@@ -57,9 +57,9 @@ func NewProxyRouterImpl(logger *zap.SugaredLogger, proxyCfg *Config, enforcer ca
5757
proxy := make(map[string]func(writer http.ResponseWriter, request *http.Request))
5858
for s, connection := range proxyConnection {
5959
proxy[s], err = NewHTTPReverseProxy(fmt.Sprintf("http://%s:%s", connection.Host, connection.Port), client.Transport, enforcer)
60-
}
61-
if err != nil {
62-
return nil, err
60+
if err != nil {
61+
return nil, err
62+
}
6363
}
6464

6565
router := &ProxyRouterImpl{

docs/SUMMARY.md

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -114,23 +114,22 @@
114114
* [Security](user-guide/security-features.md)
115115
* [Security Scans](user-guide/security-features/security-scans.md)
116116
* [Security Policies](user-guide/security-features/security-policies.md)
117-
* [Clusters](user-guide/clusters.md)
118117
* [Bulk Edit](user-guide/bulk-update.md)
119118
* [Integrations](user-guide/integrations/README.md)
120119
* [Build and Deploy (CI/CD)](user-guide/integrations/build-and-deploy-ci-cd.md)
121120
* [GitOps (Argo CD)](user-guide/integrations/argocd.md)
122121
* [Vulnerability Scanning (Clair)](user-guide/integrations/clair.md)
123122
* [Notifications](user-guide/integrations/notifications.md)
124123
* [Monitoring (Grafana)](user-guide/integrations/grafana.md)
125-
* [Preset Plugins](user-guide/plugins/README.md)
126-
* [K6 Load Testing](user-guide/plugins/k6-load-testing.md)
127-
* [SonarQube](user-guide/plugins/sonarqube.md)
128-
* [Dependency track - Python](user-guide/plugins/dependency-track-python.md)
129-
* [Dependency track - NodeJS](user-guide/plugins/dependency-track-nodejs.md)
130-
* [Dependency track - Maven & Gradle](user-guide/plugins/dependency-track-maven-gradle.md)
131-
* [Semgrep](user-guide/plugins/semgrep.md)
124+
* [Pipeline Plugins](user-guide/plugins/README.md)
132125
* [Codacy](user-guide/plugins/codacy.md)
133126
* [Copy Container Image](user-guide/plugins/copy-container-image.md)
127+
* [Dependency track - Maven & Gradle](user-guide/plugins/dependency-track-maven-gradle.md)
128+
* [Dependency track - NodeJS](user-guide/plugins/dependency-track-nodejs.md)
129+
* [Dependency track - Python](user-guide/plugins/dependency-track-python.md)
130+
* [K6 Load Testing](user-guide/plugins/k6-load-testing.md)
131+
* [Semgrep](user-guide/plugins/semgrep.md)
132+
* [SonarQube](user-guide/plugins/sonarqube.md)
134133
* [SonarQube v1.1.0](user-guide/plugins/sonarqube-v1.1.0.md)
135134

136135

docs/reference/glossary.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ A place where all Helm charts are centrally listed for users to deploy applicati
3838

3939
A cluster in Kubernetes refers to a set of connected computers (nodes) that collectively manage containerized applications using Kubernetes. It provides resources and services to run, manage, and scale applications.
4040

41-
In Devtron, you can view the list of clusters in Global Configurations’ available in the left sidebar. [Read More...](../user-guide/clusters.md)
41+
In Devtron, you can view the list of clusters in 'Global Configurations' as well as 'Resource Browser'. [Read More...](../user-guide/resource-browser.md)
4242

4343
### Commit Hash
4444

@@ -180,7 +180,7 @@ In Devtron, you can view nodes by going to Resource Browser → (choose a cluste
180180

181181
Kubernetes objects are the building blocks that define and manage your applications running on the platform. They are also known as 'Resources' or 'Kinds'. This includes nodes, pods, deployment, cronjob, configmap, and many more.
182182

183-
Devtron's [Resource Browser](../user-guide/resource-browser/README.md) helps you manage all such objects present in your clusters.
183+
Devtron's [Resource Browser](../user-guide/resource-browser.md) helps you manage all such objects present in your clusters.
184184

185185
### Pod
186186

docs/setup/getting-started/getting-started.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Devtron is installed over a Kubernetes cluster. Once you create a Kubernetes clu
1010
In this section, we will cover the basic details on how you can quickly get started with **Devtron**.
1111
First, lets see what are the prerequisite requirements before you install Devtron.
1212

13-
## Pre-requisite Requirements
13+
## Prerequisites
1414
* Create a [Kubernetes cluster, preferably K8s version 1.16 or higher](#create-a-kubernetes-cluster)
1515
* [Helm Installation](https://helm.sh/docs/intro/install/)
1616
* [Recommended Resources](#recommended-resources)

docs/setup/install/install-devtron-with-cicd.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ In this section, we describe the steps in detail on how you can install Devtron
44

55
---
66

7-
## Pre-requisites
7+
## Prerequisites
88

99
Install [Helm](https://helm.sh/docs/intro/install/), if you have not installed it already.
1010

docs/user-guide/application-groups.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ Users need to have [Build and deploy permission](../user-guide/global-configurat
139139

140140
{% hint style="warning" %}
141141
### Who Can Perform This Action?
142-
Users need to have [Build & deploy permission](../global-configurations/authorization/user-access.md#role-based-access-levels) or above (along with access to the environment and application) to hibernate or unhibernate applications.
142+
Users need to have [Build & deploy permission](./global-configurations/authorization/user-access.md#role-based-access-levels) or above (along with access to the environment and application) to hibernate or unhibernate applications.
143143
{% endhint %}
144144

145145
Since every application comes with an option to hibernate, the same is true for application groups. Using application group, you can hibernate one or more applications belonging to the same environment if you do not want them to consume resources (replica count will be set to 0).

docs/user-guide/global-configurations/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ Before you start creating an application, we recommend to provide basic informat
3434

3535
[Tags Policy](tags-policy.md)
3636

37-
[Filter Condition](filter-condition.md)
37+
[Lock Deployment Configuration](lock-deployment-config.md)
3838

39-
[Image Promotion](image-promotion-policy.md)
39+
[Image Promotion Policy](image-promotion-policy.md)
4040

41-
[Lock Deployment Configuration](lock-deployment-config.md)
41+
[Filter Condition](filter-condition.md)
4242

4343
[Build Infra](build-infra.md)
4444

0 commit comments

Comments
 (0)