Skip to content
This repository has been archived by the owner on Feb 15, 2022. It is now read-only.

Commit

Permalink
Leverage Existing Helm Repo (#260)
Browse files Browse the repository at this point in the history
* If helm repo URL is already locally installed, it uses that repo instead of creating a temp one.

* Fixed build errors

* Updates based on comments from PR
  • Loading branch information
runyontr authored and evanlouie committed Oct 30, 2019
1 parent 41cb60f commit 5d081a3
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 23 deletions.
86 changes: 63 additions & 23 deletions generators/helm.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ import (
"github.com/microsoft/fabrikate/logger"
"github.com/otiai10/copy"
"github.com/timfpark/yaml"

"k8s.io/helm/pkg/helm/environment"
"k8s.io/helm/pkg/helm/helmpath"
"k8s.io/helm/pkg/repo"
)

// HelmGenerator provides 'helm generate' generator functionality to Fabrikate
Expand Down Expand Up @@ -267,28 +271,43 @@ var hd = helmDownloader{}
// downloadChart downloads a target `chart` at version `version` from `repo` and
// places it in `into`. If `version` is blank, latest is automatically fetched.
// -- `into` will be the dir containing Chart.yaml
// The function will add a temporary helm repo, fetch from it, and then remove
// The function will first look to leverage an existing Helm repo from the
// repository file at $HELM_HOME/repositories.yaml. If it fails to find
// a repo there, it will add a temporary helm repo, fetch from it, and then remove
// the temporary repo. This is a to get around a limitation in Helm 2.
// see: https://github.com/helm/helm/issues/4527
func (hd *helmDownloader) downloadChart(repo, chart, version, into string) (err error) {
// generate random name to store repo in helm in temporarily
randomUUID, err := uuid.NewRandom()
repoName, err := getRepoName(repo)
if err != nil {
return err
}
randomName := randomUUID.String()
logger.Info(emoji.Sprintf(":pencil: Adding temporary helm repo %s => %s", repo, randomName))
hd.mu.Lock()
if output, err := exec.Command("helm", "repo", "add", randomName, repo).CombinedOutput(); err != nil {
logger.Info(emoji.Sprintf(":no_bell: %v", repo, err))
// generate random name to store repo in helm in temporarily
randomUUID, err := uuid.NewRandom()
if err != nil {
return err
}
repoName = randomUUID.String()
logger.Info(emoji.Sprintf(":pencil: Adding temporary helm repo %s => %s", repo, repoName))
hd.mu.Lock()
if output, err := exec.Command("helm", "repo", "add", repoName, repo).CombinedOutput(); err != nil {
hd.mu.Unlock()
logger.Error(emoji.Sprintf(":no_entry_sign: Failed adding helm repository '%s'\n%s: %s", repo, err, output))
return err
}
hd.mu.Unlock()
logger.Error(emoji.Sprintf(":no_entry_sign: Failed adding helm repository '%s'\n%s: %s", repo, err, output))
return err
defer func() {
// Remove repository once completed
logger.Info(emoji.Sprintf(":bomb: Removing temporary helm repo %s", repoName))
hd.mu.Lock()
if output, err := exec.Command("helm", "repo", "remove", repoName).CombinedOutput(); err != nil {
logger.Error(emoji.Sprintf(":no_entry_sign: Failed to `helm repo remove %s`\n%s: %s", repoName, err, output))
}
hd.mu.Unlock()
}()
}
hd.mu.Unlock()

// Fetch chart to random temp dir
chartName := fmt.Sprintf("%s/%s", randomName, chart)
randomDir := path.Join(os.TempDir(), randomName)
chartName := fmt.Sprintf("%s/%s", repoName, chart)
randomDir := path.Join(os.TempDir(), repoName)
downloadVersion := "latest"
if version != "" {
downloadVersion = version
Expand All @@ -305,15 +324,6 @@ func (hd *helmDownloader) downloadChart(repo, chart, version, into string) (err
return err
}

// Remove repository once completed
logger.Info(emoji.Sprintf(":bomb: Removing temporary helm repo %s", randomName))
hd.mu.Lock()
if output, err := exec.Command("helm", "repo", "remove", randomName).CombinedOutput(); err != nil {
hd.mu.Unlock()
logger.Error(emoji.Sprintf(":no_entry_sign: Failed to `helm repo remove %s`\n%s: %s", randomName, err, output))
}
hd.mu.Unlock()

// Remove the into directory if it already exists
if err = os.RemoveAll(into); err != nil {
return err
Expand Down Expand Up @@ -369,6 +379,11 @@ func updateHelmChartDep(chartPath string) (err error) {

// Add each dependency repo with a temp name
for _, dep := range requirementsYaml.Dependencies {
currentRepo, err := getRepoName(dep.Repository)
if err == nil {
logger.Info(emoji.Sprintf(":pencil: Helm dependency repo already present: %v", currentRepo))
continue
}
logger.Info(emoji.Sprintf(":pencil: Adding helm dependency repository '%s'", dep.Repository))
randomUUID, err := uuid.NewRandom()
if err != nil {
Expand Down Expand Up @@ -412,3 +427,28 @@ func updateHelmChartDep(chartPath string) (err error) {

return err
}

// getRepoName returns the repo name for the provided url
func getRepoName(url string) (string, error) {
logger.Info(emoji.Sprintf(":eyes: Looking for repo %v", url))
helmHome := os.Getenv(environment.HomeEnvVar)
if helmHome == "" {
helmHome = environment.DefaultHelmHome
}
a := helmpath.Home(helmHome)
f, err := repo.LoadRepositoriesFile(a.RepositoryFile())
if err != nil {
return "", err
}
if len(f.Repositories) == 0 {
return "", fmt.Errorf("no repositories to show")
}

for _, re := range f.Repositories {
if strings.EqualFold(re.URL, url) {
logger.Info(emoji.Sprintf(":green_heart: %v matches repo %v", url, re.Name))
return re.Name, nil
}
}
return "", fmt.Errorf("No repository found for %v", url)
}
6 changes: 6 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ module github.com/microsoft/fabrikate
go 1.12

require (
github.com/Masterminds/semver v1.4.2 // indirect
github.com/cyphar/filepath-securejoin v0.2.2 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/google/go-github/v28 v28.0.1
github.com/google/uuid v1.1.1
github.com/kyokomi/emoji v2.1.0+incompatible
Expand All @@ -16,4 +19,7 @@ require (
github.com/stretchr/testify v1.4.0
github.com/timfpark/conjungo v1.0.1
github.com/timfpark/yaml v0.0.0-20190612232118-2e9e29c9df01
k8s.io/apimachinery v0.0.0-20190831074630-461753078381 // indirect
k8s.io/client-go v11.0.0+incompatible // indirect
k8s.io/helm v2.14.3+incompatible
)
Loading

0 comments on commit 5d081a3

Please sign in to comment.