Skip to content

Commit 229e3f9

Browse files
Ash-expiamayushm
andauthored
feat: Integrated OCI registries in global config artifact store. (#3567)
* migration virtual cluster v2 * migration column name changed * migration update * refactoring gitops code * OCI registry integration * added validation for container storage type action * refactoring gitops code * migration update * migration update * manifest_push_config dto update * manifest push config dto correction * wip * db object correction * manifest push config get function * cleaning code * added integration test cases for docker_artifact_store * skipped integration test cases for built and modified logs * updated validation condition * updated docker_artifact_store query condition for OCI config relations * moving save timeline call * handled nil pointer issue of existing registry update * cleaning code- removing unused functions * trigger event refactor for unit test case * wip * migration-update * wip * updated wire_gen.go --------- Co-authored-by: ayushmaheshwari <[email protected]>
1 parent b384ced commit 229e3f9

20 files changed

+1190
-826
lines changed

Wire.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,8 @@ func InitializeApp() (*App, error) {
232232
wire.Bind(new(dockerRegistryRepository.DockerArtifactStoreRepository), new(*dockerRegistryRepository.DockerArtifactStoreRepositoryImpl)),
233233
dockerRegistryRepository.NewDockerRegistryIpsConfigRepositoryImpl,
234234
wire.Bind(new(dockerRegistryRepository.DockerRegistryIpsConfigRepository), new(*dockerRegistryRepository.DockerRegistryIpsConfigRepositoryImpl)),
235+
dockerRegistryRepository.NewOCIRegistryConfigRepositoryImpl,
236+
wire.Bind(new(dockerRegistryRepository.OCIRegistryConfigRepository), new(*dockerRegistryRepository.OCIRegistryConfigRepositoryImpl)),
235237
util.NewChartTemplateServiceImpl,
236238
wire.Bind(new(util.ChartTemplateService), new(*util.ChartTemplateServiceImpl)),
237239
util.NewChartDeploymentServiceImpl,
@@ -855,6 +857,10 @@ func InitializeApp() (*App, error) {
855857
wire.Bind(new(appGroup2.AppGroupMappingRepository), new(*appGroup2.AppGroupMappingRepositoryImpl)),
856858
pipeline.NewArgoWorkflowExecutorImpl,
857859
wire.Bind(new(pipeline.ArgoWorkflowExecutor), new(*pipeline.ArgoWorkflowExecutorImpl)),
860+
repository5.NewManifestPushConfigRepository,
861+
wire.Bind(new(repository5.ManifestPushConfigRepository), new(*repository5.ManifestPushConfigRepositoryImpl)),
862+
app.NewGitOpsManifestPushServiceImpl,
863+
wire.Bind(new(app.GitOpsPushService), new(*app.GitOpsManifestPushServiceImpl)),
858864
)
859865
return &App{}, nil
860866
}

api/bean/ValuesOverrideRequest.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,11 @@ type ReleaseStatusUpdateRequest struct {
7373
}
7474

7575
type TriggerEvent struct {
76-
PerformGitOps bool
76+
PerformChartPush bool
7777
PerformDeploymentOnCluster bool
7878
GetManifestInResponse bool
7979
DeploymentAppType string
80+
ManifestStorageType string
8081
TriggeredBy int32
8182
TriggerdAt time.Time
8283
}

api/restHandler/DockerRegRestHandler.go

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,12 @@ package restHandler
1919

2020
import (
2121
"encoding/json"
22+
"fmt"
2223
"github.com/devtron-labs/devtron/api/restHandler/common"
24+
repository "github.com/devtron-labs/devtron/internal/sql/repository/dockerRegistry"
2325
delete2 "github.com/devtron-labs/devtron/pkg/delete"
2426
"github.com/devtron-labs/devtron/pkg/user/casbin"
27+
"k8s.io/utils/strings/slices"
2528
"net/http"
2629
"strings"
2730

@@ -79,6 +82,27 @@ func NewDockerRegRestHandlerImpl(dockerRegistryConfig pipeline.DockerRegistryCon
7982
}
8083
}
8184

85+
func ValidateDockerArtifactStoreRequestBean(bean pipeline.DockerArtifactStoreBean) bool {
86+
// validating secure connection configs
87+
if (bean.Connection == secureWithCert && bean.Cert == "") ||
88+
(bean.Connection != secureWithCert && bean.Cert != "") {
89+
return false
90+
}
91+
// validating OCI Registry configs
92+
if bean.IsOCICompliantRegistry {
93+
if bean.OCIRegistryConfig == nil {
94+
return false
95+
}
96+
containerStorageActionType, containerStorageActionExists := bean.OCIRegistryConfig[repository.OCI_REGISRTY_REPO_TYPE_CONTAINER]
97+
if containerStorageActionExists && containerStorageActionType != repository.STORAGE_ACTION_TYPE_PULL_AND_PUSH {
98+
return false
99+
}
100+
} else if bean.OCIRegistryConfig != nil {
101+
return false
102+
}
103+
return true
104+
}
105+
82106
func (impl DockerRegRestHandlerImpl) SaveDockerRegistryConfig(w http.ResponseWriter, r *http.Request) {
83107
decoder := json.NewDecoder(r.Body)
84108
userId, err := impl.userAuthService.GetLoggedInUser(r)
@@ -94,7 +118,9 @@ func (impl DockerRegRestHandlerImpl) SaveDockerRegistryConfig(w http.ResponseWri
94118
return
95119
}
96120
bean.User = userId
97-
if (bean.Connection == secureWithCert && bean.Cert == "") || (bean.Connection != secureWithCert && bean.Cert != "") {
121+
if !ValidateDockerArtifactStoreRequestBean(bean) {
122+
err = fmt.Errorf("invalid payload, missing or incorrect values for required fields")
123+
impl.logger.Errorw("validation err, SaveDockerRegistryConfig", "err", err, "payload", bean)
98124
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
99125
return
100126
} else {
@@ -222,7 +248,9 @@ func (impl DockerRegRestHandlerImpl) UpdateDockerRegistryConfig(w http.ResponseW
222248
return
223249
}
224250
bean.User = userId
225-
if (bean.Connection == secureWithCert && bean.Cert == "") || (bean.Connection != secureWithCert && bean.Cert != "") {
251+
if !ValidateDockerArtifactStoreRequestBean(bean) {
252+
err = fmt.Errorf("invalid payload, missing or incorrect values for required fields")
253+
impl.logger.Errorw("validation err, SaveDockerRegistryConfig", "err", err, "payload", bean)
226254
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
227255
return
228256
} else {
@@ -267,15 +295,36 @@ func (impl DockerRegRestHandlerImpl) FetchAllDockerRegistryForAutocomplete(w htt
267295
}
268296

269297
func (impl DockerRegRestHandlerImpl) IsDockerRegConfigured(w http.ResponseWriter, r *http.Request) {
298+
v := r.URL.Query()
299+
storageType := v.Get("storageType")
300+
if storageType == "" {
301+
storageType = repository.OCI_REGISRTY_REPO_TYPE_CONTAINER
302+
}
303+
if !slices.Contains(repository.OCI_REGISRTY_REPO_TYPE_LIST, storageType) {
304+
common.WriteJsonResp(w, fmt.Errorf("invalid query parameters"), nil, http.StatusBadRequest)
305+
return
306+
}
307+
storageAction := v.Get("storageAction")
308+
if storageAction == "" {
309+
storageAction = repository.STORAGE_ACTION_TYPE_PUSH
310+
}
311+
if !(storageAction == repository.STORAGE_ACTION_TYPE_PULL || storageAction == repository.STORAGE_ACTION_TYPE_PUSH) {
312+
common.WriteJsonResp(w, fmt.Errorf("invalid query parameters"), nil, http.StatusBadRequest)
313+
return
314+
}
270315
isConfigured := false
271-
res, err := impl.dockerRegistryConfig.ListAllActive()
316+
registryConfigs, err := impl.dockerRegistryConfig.ListAllActive()
272317
if err != nil && err != pg.ErrNoRows {
273318
impl.logger.Errorw("service err, IsDockerRegConfigured", "err", err)
274319
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
275320
return
276321
}
277-
if len(res) > 0 {
278-
isConfigured = true
322+
if len(registryConfigs) > 0 {
323+
// Filter out all registries with CONTAINER push or pull/push access
324+
res := impl.dockerRegistryConfig.FilterRegistryBeanListBasedOnStorageTypeAndAction(registryConfigs, storageType, storageAction, repository.STORAGE_ACTION_TYPE_PULL_AND_PUSH)
325+
if len(res) > 0 {
326+
isConfigured = true
327+
}
279328
}
280329

281330
common.WriteJsonResp(w, err, isConfigured, http.StatusOK)

api/restHandler/app/AutoCompleteRestHandler.go

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,22 @@ package app
22

33
import (
44
"context"
5+
"fmt"
56
"github.com/devtron-labs/devtron/api/restHandler/common"
7+
repository "github.com/devtron-labs/devtron/internal/sql/repository/dockerRegistry"
68
"github.com/devtron-labs/devtron/internal/sql/repository/helper"
79
"github.com/devtron-labs/devtron/pkg/pipeline"
810
"github.com/devtron-labs/devtron/pkg/user/casbin"
911
"github.com/gorilla/mux"
1012
"go.opentelemetry.io/otel"
13+
"k8s.io/utils/strings/slices"
1114
"net/http"
1215
"strconv"
1316
)
1417

1518
type DevtronAppAutoCompleteRestHandler interface {
1619
GitListAutocomplete(w http.ResponseWriter, r *http.Request)
17-
DockerListAutocomplete(w http.ResponseWriter, r *http.Request)
20+
RegistriesListAutocomplete(w http.ResponseWriter, r *http.Request)
1821
TeamListAutocomplete(w http.ResponseWriter, r *http.Request)
1922
EnvironmentListAutocomplete(w http.ResponseWriter, r *http.Request)
2023
GetAppListForAutocomplete(w http.ResponseWriter, r *http.Request)
@@ -166,14 +169,32 @@ func (handler PipelineConfigRestHandlerImpl) GitListAutocomplete(w http.Response
166169
common.WriteJsonResp(w, err, res, http.StatusOK)
167170
}
168171

169-
func (handler PipelineConfigRestHandlerImpl) DockerListAutocomplete(w http.ResponseWriter, r *http.Request) {
172+
func (handler PipelineConfigRestHandlerImpl) RegistriesListAutocomplete(w http.ResponseWriter, r *http.Request) {
170173
token := r.Header.Get("token")
171174
vars := mux.Vars(r)
172175
appId, err := strconv.Atoi(vars["appId"])
173176
if err != nil {
174177
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
175178
return
176179
}
180+
v := r.URL.Query()
181+
storageType := v.Get("storageType")
182+
if storageType == "" {
183+
storageType = repository.OCI_REGISRTY_REPO_TYPE_CONTAINER
184+
}
185+
if !slices.Contains(repository.OCI_REGISRTY_REPO_TYPE_LIST, storageType) {
186+
common.WriteJsonResp(w, fmt.Errorf("invalid query parameters"), nil, http.StatusBadRequest)
187+
return
188+
}
189+
storageAction := v.Get("storageAction")
190+
if storageAction == "" {
191+
storageAction = repository.STORAGE_ACTION_TYPE_PUSH
192+
}
193+
if !(storageAction == repository.STORAGE_ACTION_TYPE_PULL || storageAction == repository.STORAGE_ACTION_TYPE_PUSH) {
194+
common.WriteJsonResp(w, fmt.Errorf("invalid query parameters"), nil, http.StatusBadRequest)
195+
return
196+
}
197+
177198
handler.Logger.Infow("request payload, DockerListAutocomplete", "appId", appId)
178199
//RBAC
179200
object := handler.enforcerUtil.GetAppRBACNameByAppId(appId)
@@ -182,13 +203,13 @@ func (handler PipelineConfigRestHandlerImpl) DockerListAutocomplete(w http.Respo
182203
return
183204
}
184205
//RBAC
185-
res, err := handler.dockerRegistryConfig.ListAllActive()
206+
registryConfigs, err := handler.dockerRegistryConfig.ListAllActive()
186207
if err != nil {
187208
handler.Logger.Errorw("service err, DockerListAutocomplete", "err", err, "appId", appId)
188209
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
189210
return
190211
}
191-
212+
res := handler.dockerRegistryConfig.FilterRegistryBeanListBasedOnStorageTypeAndAction(registryConfigs, storageType, storageAction, repository.STORAGE_ACTION_TYPE_PULL_AND_PUSH)
192213
common.WriteJsonResp(w, err, res, http.StatusOK)
193214
}
194215

api/restHandler/app/BuildPipelineRestHandler.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/devtron-labs/devtron/api/restHandler/common"
1010
"github.com/devtron-labs/devtron/client/gitSensor"
1111
"github.com/devtron-labs/devtron/internal/sql/repository"
12+
dockerRegistryRepository "github.com/devtron-labs/devtron/internal/sql/repository/dockerRegistry"
1213
"github.com/devtron-labs/devtron/internal/sql/repository/helper"
1314
"github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig"
1415
"github.com/devtron-labs/devtron/internal/util"
@@ -102,6 +103,14 @@ func (handler PipelineConfigRestHandlerImpl) CreateCiConfig(w http.ResponseWrite
102103
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
103104
return
104105
}
106+
// validates if the dockerRegistry can store CONTAINER
107+
isValid := handler.dockerRegistryConfig.ValidateRegistryStorageType(createRequest.DockerRegistry, dockerRegistryRepository.OCI_REGISRTY_REPO_TYPE_CONTAINER, dockerRegistryRepository.STORAGE_ACTION_TYPE_PUSH, dockerRegistryRepository.STORAGE_ACTION_TYPE_PULL_AND_PUSH)
108+
if !isValid {
109+
err = fmt.Errorf("invalid registry type")
110+
handler.Logger.Errorw("validation err, create ci config", "err", err, "create request", createRequest)
111+
common.WriteJsonResp(w, err, nil, http.StatusBadRequest)
112+
return
113+
}
105114
token := r.Header.Get("token")
106115
app, err := handler.pipelineBuilder.GetApp(createRequest.AppId)
107116
if err != nil {

api/router/PipelineConfigRouter.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ func (router PipelineConfigRouterImpl) initPipelineConfigRouter(configRouter *mu
117117

118118
configRouter.Path("/{appId}/autocomplete/environment").HandlerFunc(router.restHandler.EnvironmentListAutocomplete).Methods("GET")
119119
configRouter.Path("/{appId}/autocomplete/git").HandlerFunc(router.restHandler.GitListAutocomplete).Methods("GET")
120-
configRouter.Path("/{appId}/autocomplete/docker").HandlerFunc(router.restHandler.DockerListAutocomplete).Methods("GET")
120+
configRouter.Path("/{appId}/autocomplete/docker").HandlerFunc(router.restHandler.RegistriesListAutocomplete).Methods("GET")
121121
configRouter.Path("/{appId}/autocomplete/team").HandlerFunc(router.restHandler.TeamListAutocomplete).Methods("GET")
122122

123123
configRouter.Path("/cd-pipeline/defaultStrategy/{appId}/{envId}").HandlerFunc(router.restHandler.GetDefaultDeploymentPipelineStrategy).Methods("GET")

cmd/external-app/wire_gen.go

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)