Skip to content

Commit da2ac52

Browse files
prakash100198adi6859
authored andcommitted
fix: argocd-cm empty data label nil pointer fix (#3443)
* config map data nil pointer fix * check for nil config map * creating secret for public chart repo * delete chart repo based on it's presence in argocd-cm * code for unique chart name while adding a chart repo * secret creation doesn't support uppercase letters hence adding checks * minor change * minor fix
1 parent 219ded8 commit da2ac52

File tree

1 file changed

+113
-52
lines changed

1 file changed

+113
-52
lines changed

pkg/chartRepo/ChartRepositoryService.go

Lines changed: 113 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ package chartRepo
2020
import (
2121
"bytes"
2222
"encoding/json"
23+
"errors"
2324
"fmt"
2425
"github.com/devtron-labs/devtron/internal/sql/repository"
2526
"github.com/devtron-labs/devtron/internal/util"
@@ -99,22 +100,42 @@ func NewChartRepositoryServiceImpl(logger *zap.SugaredLogger, repoRepository cha
99100
}
100101

101102
// Private helm charts credentials are saved as secrets
102-
func (impl *ChartRepositoryServiceImpl) CreateSecretDataForPrivateHelmChart(request *ChartRepoDto) (secretData map[string]string) {
103+
func (impl *ChartRepositoryServiceImpl) CreateSecretDataForHelmChart(request *ChartRepoDto, isPrivateChart bool) (secretData map[string]string) {
103104
secretData = make(map[string]string)
104-
secretData[NAME] = fmt.Sprintf("%s-%s", request.Name, uuid.New().String()) // making repo name unique so that "helm repp add" command in argo-repo-server doesn't give error
105-
secretData[USERNAME] = request.UserName
106-
secretData[PASSWORD] = request.Password
105+
secretData[NAME] = fmt.Sprintf("%s-%s", request.Name, uuid.New().String()) // making repo name unique so that "helm repo add" command in argo-repo-server doesn't give error
107106
secretData[TYPE] = HELM
108107
secretData[URL] = request.Url
109-
isInsecureConnection := "true"
110-
if !request.AllowInsecureConnection {
111-
isInsecureConnection = "false"
108+
if isPrivateChart {
109+
secretData[USERNAME] = request.UserName
110+
secretData[PASSWORD] = request.Password
111+
isInsecureConnection := "true"
112+
if !request.AllowInsecureConnection {
113+
isInsecureConnection = "false"
114+
}
115+
secretData[INSECRUE] = isInsecureConnection
112116
}
113-
secretData[INSECRUE] = isInsecureConnection
117+
114118
return secretData
115119
}
116120

117121
func (impl *ChartRepositoryServiceImpl) CreateChartRepo(request *ChartRepoDto) (*chartRepoRepository.ChartRepo, error) {
122+
//metadata.name label in Secret doesn't support uppercase hence returning if user enters uppercase letters
123+
if strings.ToLower(request.Name) != request.Name {
124+
return nil, errors.New("invalid repo name: please use lowercase")
125+
}
126+
allChartsRepos, err := impl.repoRepository.FindAll()
127+
if err != nil {
128+
impl.logger.Errorw("error in getting list of all chart repos", "err", err)
129+
return nil, err
130+
}
131+
if len(allChartsRepos) == 0 {
132+
return nil, nil
133+
}
134+
for _, chart := range allChartsRepos {
135+
if chart.Name == request.Name {
136+
return nil, errors.New("repo with chart name already exists")
137+
}
138+
}
118139
dbConnection := impl.repoRepository.GetConnection()
119140
tx, err := dbConnection.Begin()
120141
if err != nil {
@@ -166,24 +187,10 @@ func (impl *ChartRepositoryServiceImpl) CreateChartRepo(request *ChartRepoDto) (
166187
for !updateSuccess && retryCount < 3 {
167188
retryCount = retryCount + 1
168189

169-
if !isPrivateChart {
170-
cm, err := impl.K8sUtil.GetConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, impl.aCDAuthConfig.ACDConfigMapName, client)
171-
if err != nil {
172-
return nil, err
173-
}
174-
data, err := impl.updateRepoData(cm.Data, request)
175-
if err != nil {
176-
impl.logger.Warnw(" config map update failed", "err", err)
177-
continue
178-
}
179-
cm.Data = data
180-
_, err = impl.K8sUtil.UpdateConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, cm, client)
181-
} else {
182-
secretLabel := make(map[string]string)
183-
secretLabel[LABEL] = REPOSITORY
184-
secretData := impl.CreateSecretDataForPrivateHelmChart(request)
185-
_, err = impl.K8sUtil.CreateSecret(impl.aCDAuthConfig.ACDConfigMapNamespace, nil, chartRepo.Name, "", client, secretLabel, secretData)
186-
}
190+
secretLabel := make(map[string]string)
191+
secretLabel[LABEL] = REPOSITORY
192+
secretData := impl.CreateSecretDataForHelmChart(request, isPrivateChart)
193+
_, err = impl.K8sUtil.CreateSecret(impl.aCDAuthConfig.ACDConfigMapNamespace, nil, chartRepo.Name, "", client, secretLabel, secretData)
187194
if err != nil {
188195
continue
189196
}
@@ -215,7 +222,11 @@ func (impl *ChartRepositoryServiceImpl) UpdateData(request *ChartRepoDto) (*char
215222
return nil, err
216223
}
217224
previousName := chartRepo.Name
218-
225+
previousUrl := chartRepo.Url
226+
//metadata.name label in Secret doesn't support uppercase hence returning if user enters uppercase letters in repo name
227+
if request.Name != previousName && strings.ToLower(request.Name) != request.Name {
228+
return nil, errors.New("invalid repo name: please use lowercase")
229+
}
219230
chartRepo.Url = request.Url
220231
chartRepo.Name = request.Name
221232
chartRepo.AuthMode = request.AuthMode
@@ -257,31 +268,55 @@ func (impl *ChartRepositoryServiceImpl) UpdateData(request *ChartRepoDto) (*char
257268
for !updateSuccess && retryCount < 3 {
258269
retryCount = retryCount + 1
259270

260-
if !isPrivateChart {
261-
cm, err := impl.K8sUtil.GetConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, impl.aCDAuthConfig.ACDConfigMapName, client)
271+
var isFoundInArgoCdCm bool
272+
cm, err := impl.K8sUtil.GetConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, impl.aCDAuthConfig.ACDConfigMapName, client)
273+
if err != nil {
274+
return nil, err
275+
}
276+
var repositories []*AcdConfigMapRepositoriesDto
277+
if cm != nil && cm.Data != nil {
278+
repoStr := cm.Data["repositories"]
279+
repoByte, err := yaml.YAMLToJSON([]byte(repoStr))
262280
if err != nil {
281+
impl.logger.Errorw("error in json patch", "err", err)
263282
return nil, err
264283
}
265-
var data map[string]string
266-
// if the repo name has been updated then, create a new repo
267-
data, err = impl.updateRepoData(cm.Data, request)
268-
// if the repo name has been updated then, delete the previous repo
284+
err = json.Unmarshal(repoByte, &repositories)
269285
if err != nil {
270-
impl.logger.Warnw(" config map update failed", "err", err)
271-
continue
272-
}
273-
if previousName != request.Name {
274-
data, err = impl.removeRepoData(cm.Data, previousName)
286+
impl.logger.Errorw("error in unmarshal", "err", err)
287+
return nil, err
275288
}
276-
if err != nil {
277-
impl.logger.Warnw(" config map update failed", "err", err)
278-
continue
289+
for _, repo := range repositories {
290+
if repo.Name == previousName && repo.Url == previousUrl {
291+
//chart repo is present in argocd-cm
292+
isFoundInArgoCdCm = true
293+
break
294+
}
279295
}
296+
}
280297

298+
if isFoundInArgoCdCm {
299+
var data map[string]string
300+
// if the repo name has been updated then, create a new repo
301+
if cm != nil && cm.Data != nil {
302+
data, err = impl.updateRepoData(cm.Data, request)
303+
// if the repo name has been updated then, delete the previous repo
304+
if err != nil {
305+
impl.logger.Warnw(" config map update failed", "err", err)
306+
continue
307+
}
308+
if previousName != request.Name {
309+
data, err = impl.removeRepoData(cm.Data, previousName)
310+
}
311+
if err != nil {
312+
impl.logger.Warnw(" config map update failed", "err", err)
313+
continue
314+
}
315+
}
281316
cm.Data = data
282317
_, err = impl.K8sUtil.UpdateConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, cm, client)
283318
} else {
284-
secretData := impl.CreateSecretDataForPrivateHelmChart(request)
319+
secretData := impl.CreateSecretDataForHelmChart(request, isPrivateChart)
285320
secret, err := impl.K8sUtil.GetSecret(impl.aCDAuthConfig.ACDConfigMapNamespace, previousName, client)
286321
if err != nil {
287322
impl.logger.Errorw("error in fetching secret", "err", err)
@@ -380,23 +415,45 @@ func (impl *ChartRepositoryServiceImpl) DeleteChartRepo(request *ChartRepoDto) e
380415
retryCount := 0
381416
//request.Url = ""
382417

383-
isPrivateChart := false
384-
if len(chartRepo.UserName) > 0 && len(chartRepo.Password) > 0 {
385-
isPrivateChart = true
386-
}
387-
388418
for !updateSuccess && retryCount < 3 {
389419
retryCount = retryCount + 1
390420

391-
if !isPrivateChart {
392-
cm, err := impl.K8sUtil.GetConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, impl.aCDAuthConfig.ACDConfigMapName, client)
421+
var isFoundInArgoCdCm bool
422+
cm, err := impl.K8sUtil.GetConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, impl.aCDAuthConfig.ACDConfigMapName, client)
423+
if err != nil {
424+
return err
425+
}
426+
var repositories []*AcdConfigMapRepositoriesDto
427+
if cm != nil && cm.Data != nil {
428+
repoStr := cm.Data["repositories"]
429+
repoByte, err := yaml.YAMLToJSON([]byte(repoStr))
393430
if err != nil {
431+
impl.logger.Errorw("error in json patch", "err", err)
394432
return err
395433
}
396-
data, err := impl.removeRepoData(cm.Data, request.Name)
434+
err = json.Unmarshal(repoByte, &repositories)
397435
if err != nil {
398-
impl.logger.Warnw(" config map update failed", "err", err)
399-
continue
436+
impl.logger.Errorw("error in unmarshal", "err", err)
437+
return err
438+
}
439+
for _, repo := range repositories {
440+
if repo.Name == request.Name && repo.Url == request.Url {
441+
//chart repo is present in argocd-cm
442+
isFoundInArgoCdCm = true
443+
break
444+
}
445+
}
446+
}
447+
448+
if isFoundInArgoCdCm {
449+
var data map[string]string
450+
451+
if cm != nil && cm.Data != nil {
452+
data, err = impl.removeRepoData(cm.Data, request.Name)
453+
if err != nil {
454+
impl.logger.Warnw(" config map update failed", "err", err)
455+
continue
456+
}
400457
}
401458
cm.Data = data
402459
_, err = impl.K8sUtil.UpdateConfigMap(impl.aCDAuthConfig.ACDConfigMapNamespace, cm, client)
@@ -572,6 +629,10 @@ func (impl *ChartRepositoryServiceImpl) ValidateAndCreateChartRepo(request *Char
572629
if err != nil {
573630
return nil, err, validationResult
574631
}
632+
if chartRepo == nil && err == nil {
633+
//case when no entry for chart in chart_repo table and no need to trigger chart sync
634+
return nil, nil, validationResult
635+
}
575636

576637
// Trigger chart sync job, ignore error
577638
err = impl.TriggerChartSyncManual()

0 commit comments

Comments
 (0)