Skip to content

Commit

Permalink
fix: Intermittent helm apps deployment fail deployed through gitops (#…
Browse files Browse the repository at this point in the history
…3756)

* pushed requirements.yaml file while pushing chart

* pushed values.yaml file while pushing chart

* Order of return parameters

* Order of return parameters

* review comments

* review comments
  • Loading branch information
Shivam-nagar23 committed Aug 14, 2023
1 parent 324beb4 commit 01ff25c
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 42 deletions.
124 changes: 82 additions & 42 deletions pkg/appStore/deployment/common/AppStoreDeploymentCommonService.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
appStoreBean "github.com/devtron-labs/devtron/pkg/appStore/bean"
"github.com/devtron-labs/devtron/pkg/appStore/deployment/repository"
appStoreDiscoverRepository "github.com/devtron-labs/devtron/pkg/appStore/discover/repository"
util2 "github.com/devtron-labs/devtron/pkg/appStore/util"
repository2 "github.com/devtron-labs/devtron/pkg/cluster/repository"
"github.com/go-pg/pg"
"github.com/google/go-github/github"
Expand All @@ -49,7 +50,7 @@ type AppStoreDeploymentCommonService interface {
ParseGitRepoErrorResponse(err error) (bool, error)
GetValuesAndRequirementGitConfig(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*util.ChartConfig, *util.ChartConfig, error)
CreateChartProxyAndGetPath(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*util.ChartCreateResponse, error)
CreateGitOpsRepoAndPushChart(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, builtChartPath string) (*util.ChartGitAttribute, error)
CreateGitOpsRepoAndPushChart(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, builtChartPath string, requirementsConfig *util.ChartConfig, valuesConfig *util.ChartConfig) (*util.ChartGitAttribute, bool, string, error)
CommitConfigToGit(chartConfig *util.ChartConfig) (gitHash string, err error)
GetGitCommitConfig(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, fileString string, filename string) (*util.ChartConfig, error)
GetValuesString(chartName, valuesOverrideYaml string) (string, error)
Expand Down Expand Up @@ -380,7 +381,7 @@ func (impl AppStoreDeploymentCommonServiceImpl) GenerateManifest(installAppVersi
//}

// CreateGitOpsRepo creates a gitOps repo with readme
func (impl AppStoreDeploymentCommonServiceImpl) CreateGitOpsRepo(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (string, error) {
func (impl AppStoreDeploymentCommonServiceImpl) CreateGitOpsRepo(installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (string, bool, error) {

if len(installAppVersionRequest.GitOpsRepoName) == 0 {
//here gitops repo will be the app name, to breaking the mono repo structure
Expand All @@ -393,7 +394,7 @@ func (impl AppStoreDeploymentCommonServiceImpl) CreateGitOpsRepo(installAppVersi
err = nil
gitOpsConfigBitbucket.BitBucketWorkspaceId = ""
} else {
return "", err
return "", false, err
}
}
//getting user name & emailId for commit author data
Expand All @@ -406,18 +407,18 @@ func (impl AppStoreDeploymentCommonServiceImpl) CreateGitOpsRepo(installAppVersi
BitBucketWorkspaceId: gitOpsConfigBitbucket.BitBucketWorkspaceId,
BitBucketProjectKey: gitOpsConfigBitbucket.BitBucketProjectKey,
}
repoUrl, _, detailedError := impl.gitFactory.Client.CreateRepository(gitRepoRequest)
repoUrl, isNew, detailedError := impl.gitFactory.Client.CreateRepository(gitRepoRequest)
for _, err := range detailedError.StageErrorMap {
if err != nil {
impl.logger.Errorw("error in creating git project", "name", installAppVersionRequest.GitOpsRepoName, "err", err)
return "", err
return "", false, err
}
}
return repoUrl, err
return repoUrl, isNew, err
}

// PushChartToGitopsRepo pushes built chart to gitOps repo
func (impl AppStoreDeploymentCommonServiceImpl) PushChartToGitopsRepo(PushChartToGitRequest *appStoreBean.PushChartToGitRequestDTO) (*util.ChartGitAttribute, error) {
func (impl AppStoreDeploymentCommonServiceImpl) PushChartToGitopsRepo(PushChartToGitRequest *appStoreBean.PushChartToGitRequestDTO, requirementsConfig *util.ChartConfig, valuesConfig *util.ChartConfig) (*util.ChartGitAttribute, string, error) {
space := regexp.MustCompile(`\s+`)
appStoreName := space.ReplaceAllString(PushChartToGitRequest.ChartAppStoreName, "-")
chartDir := fmt.Sprintf("%s-%s", PushChartToGitRequest.AppName, impl.chartTemplateService.GetDir())
Expand All @@ -426,25 +427,35 @@ func (impl AppStoreDeploymentCommonServiceImpl) PushChartToGitopsRepo(PushChartT
clonedDir, err = impl.gitFactory.GitService.Clone(PushChartToGitRequest.RepoURL, chartDir)
if err != nil {
impl.logger.Errorw("error in cloning repo", "url", PushChartToGitRequest.RepoURL, "err", err)
return nil, err
return nil, "", err
}
} else {
err = impl.chartTemplateService.GitPull(clonedDir, PushChartToGitRequest.RepoURL, appStoreName)
if err != nil {
return nil, err
return nil, "", err
}
}
acdAppName := fmt.Sprintf("%s-%s", PushChartToGitRequest.AppName, PushChartToGitRequest.EnvName)
dir := filepath.Join(clonedDir, acdAppName)
err := os.MkdirAll(dir, os.ModePerm)
if err != nil {
impl.logger.Errorw("error in making dir", "err", err)
return nil, err
return nil, "", err
}
err = dirCopy.Copy(PushChartToGitRequest.TempChartRefDir, dir)
if err != nil {
impl.logger.Errorw("error copying dir", "err", err)
return nil, err
return nil, "", err
}
err = impl.AddConfigFileToChart(requirementsConfig, dir, clonedDir)
if err != nil {
impl.logger.Errorw("error in adding requirements.yaml to chart", "err", err, "appName", PushChartToGitRequest.AppName)
return nil, "", err
}
err = impl.AddConfigFileToChart(valuesConfig, dir, clonedDir)
if err != nil {
impl.logger.Errorw("error in adding values.yaml to chart", "err", err, "appName", PushChartToGitRequest.AppName)
return nil, "", err
}
userEmailId, userName := impl.chartTemplateService.GetUserEmailIdAndNameForGitOpsCommit(PushChartToGitRequest.UserId)
commit, err := impl.gitFactory.GitService.CommitAndPushAllChanges(clonedDir, "first commit", userName, userEmailId)
Expand All @@ -453,38 +464,62 @@ func (impl AppStoreDeploymentCommonServiceImpl) PushChartToGitopsRepo(PushChartT
impl.logger.Warn("re-trying, taking pull and then push again")
err = impl.chartTemplateService.GitPull(clonedDir, PushChartToGitRequest.RepoURL, acdAppName)
if err != nil {
return nil, err
impl.logger.Errorw("error in git pull", "err", err, "appName", acdAppName)
return nil, "", err
}
err = dirCopy.Copy(PushChartToGitRequest.TempChartRefDir, dir)
if err != nil {
impl.logger.Errorw("error copying dir", "err", err)
return nil, err
return nil, "", err
}
commit, err = impl.gitFactory.GitService.CommitAndPushAllChanges(clonedDir, "first commit", userName, userEmailId)
if err != nil {
impl.logger.Errorw("error in pushing git", "err", err)
return nil, err
return nil, "", err
}
}
impl.logger.Debugw("template committed", "url", PushChartToGitRequest.RepoURL, "commit", commit)
defer impl.chartTemplateService.CleanDir(clonedDir)
return &util.ChartGitAttribute{RepoUrl: PushChartToGitRequest.RepoURL, ChartLocation: filepath.Join("", acdAppName)}, nil
return &util.ChartGitAttribute{RepoUrl: PushChartToGitRequest.RepoURL, ChartLocation: acdAppName}, commit, err
}

// AddConfigFileToChart will override requirements.yaml file in chart
func (impl AppStoreDeploymentCommonServiceImpl) AddConfigFileToChart(config *util.ChartConfig, dir string, clonedDir string) error {
filePath := filepath.Join(clonedDir, config.FileName)
file, err := os.Create(filePath)
if err != nil {
impl.logger.Errorw("error in creating file", "err", err, "fileName", config.FileName)
return err
}
defer file.Close()
_, err = file.Write([]byte(config.FileContent))
if err != nil {
impl.logger.Errorw("error in writing file content", "err", err, "fileName", config.FileName)
return err
}
destinationFilePath := filepath.Join(dir, config.FileName)
err = util2.MoveFileToDestination(filePath, destinationFilePath)
if err != nil {
impl.logger.Errorw("error in moving file from source to destination", "err", err)
return err
}
return nil
}

// CreateGitOpsRepoAndPushChart is a wrapper for creating gitops repo and pushing chart to created repo
func (impl AppStoreDeploymentCommonServiceImpl) CreateGitOpsRepoAndPushChart(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, builtChartPath string) (*util.ChartGitAttribute, error) {
repoURL, err := impl.CreateGitOpsRepo(installAppVersionRequest)
func (impl AppStoreDeploymentCommonServiceImpl) CreateGitOpsRepoAndPushChart(installAppVersionRequest *appStoreBean.InstallAppVersionDTO, builtChartPath string, requirementsConfig *util.ChartConfig, valuesConfig *util.ChartConfig) (*util.ChartGitAttribute, bool, string, error) {
repoURL, isNew, err := impl.CreateGitOpsRepo(installAppVersionRequest)
if err != nil {
impl.logger.Errorw("Error in creating gitops repo for ", "appName", installAppVersionRequest.AppName, "err", err)
return nil, err
return nil, false, "", err
}
pushChartToGitRequest := ParseChartGitPushRequest(installAppVersionRequest, repoURL, builtChartPath)
chartGitAttribute, err := impl.PushChartToGitopsRepo(pushChartToGitRequest)
chartGitAttribute, commitHash, err := impl.PushChartToGitopsRepo(pushChartToGitRequest, requirementsConfig, valuesConfig)
if err != nil {
impl.logger.Errorw("error in pushing chart to git", "err", err)
return nil, err
return nil, false, "", err
}
return chartGitAttribute, err
return chartGitAttribute, isNew, commitHash, err
}

// CommitConfigToGit is used for committing values.yaml and requirements.yaml file config
Expand All @@ -508,34 +543,39 @@ func (impl AppStoreDeploymentCommonServiceImpl) CommitConfigToGit(chartConfig *u

func (impl AppStoreDeploymentCommonServiceImpl) GitOpsOperations(manifestResponse *AppStoreManifestResponse, installAppVersionRequest *appStoreBean.InstallAppVersionDTO) (*AppStoreGitOpsResponse, error) {
appStoreGitOpsResponse := &AppStoreGitOpsResponse{}
chartGitAttribute, err := impl.CreateGitOpsRepoAndPushChart(installAppVersionRequest, manifestResponse.ChartResponse.BuiltChartPath)
chartGitAttribute, isNew, githash, err := impl.CreateGitOpsRepoAndPushChart(installAppVersionRequest, manifestResponse.ChartResponse.BuiltChartPath, manifestResponse.RequirementsConfig, manifestResponse.ValuesConfig)
if err != nil {
impl.logger.Errorw("Error in pushing chart to git", "err", err)
return appStoreGitOpsResponse, err
}
// step-2 commit dependencies and values in git
_, err = impl.CommitConfigToGit(manifestResponse.RequirementsConfig)
if err != nil {
impl.logger.Errorw("error in committing dependency config to git", "err", err)
return appStoreGitOpsResponse, err
}
space := regexp.MustCompile(`\s+`)
appStoreName := space.ReplaceAllString(installAppVersionRequest.AppName, "-")
clonedDir := impl.gitFactory.GitWorkingDir + "" + appStoreName
err = impl.chartTemplateService.GitPull(clonedDir, chartGitAttribute.RepoUrl, appStoreName)
if err != nil {
impl.logger.Errorw("error in git pull", "err", err)
return appStoreGitOpsResponse, err
}
githash, err := impl.CommitConfigToGit(manifestResponse.ValuesConfig)
if err != nil {
impl.logger.Errorw("error in committing values config to git", "err", err)
return appStoreGitOpsResponse, err
}
err = impl.chartTemplateService.GitPull(clonedDir, chartGitAttribute.RepoUrl, appStoreName)
if err != nil {
impl.logger.Errorw("error in git pull", "err", err)
return appStoreGitOpsResponse, err

// Checking this is the first time chart has been pushed , if yes requirements.yaml has been already pushed with chart as there was sync-delay with github api.
// step-2 commit dependencies and values in git
if !isNew {
_, err = impl.CommitConfigToGit(manifestResponse.RequirementsConfig)
if err != nil {
impl.logger.Errorw("error in committing dependency config to git", "err", err)
return appStoreGitOpsResponse, err
}
err = impl.chartTemplateService.GitPull(clonedDir, chartGitAttribute.RepoUrl, appStoreName)
if err != nil {
impl.logger.Errorw("error in git pull", "err", err)
return appStoreGitOpsResponse, err
}

githash, err = impl.CommitConfigToGit(manifestResponse.ValuesConfig)
if err != nil {
impl.logger.Errorw("error in committing values config to git", "err", err)
return appStoreGitOpsResponse, err
}
err = impl.chartTemplateService.GitPull(clonedDir, chartGitAttribute.RepoUrl, appStoreName)
if err != nil {
impl.logger.Errorw("error in git pull", "err", err)
return appStoreGitOpsResponse, err
}
}
appStoreGitOpsResponse.ChartGitAttribute = chartGitAttribute
appStoreGitOpsResponse.GitHash = githash
Expand Down
11 changes: 11 additions & 0 deletions pkg/appStore/util/util.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package util

import "os"

func MoveFileToDestination(filePath, destinationPath string) error {
err := os.Rename(filePath, destinationPath)
if err != nil {
return err
}
return nil
}

0 comments on commit 01ff25c

Please sign in to comment.