perf: download charts in parallel

Signed-off-by: Felipe Santos <felipecassiors@gmail.com>
pull/11793/head
Felipe Santos 3 years ago
parent 5bf273d81b
commit 4ad501c85a

@ -270,7 +270,7 @@ func (m *Manager) downloadAll(deps []*chart.Dependency) error {
fmt.Fprintf(m.Out, "Saving %d charts\n", len(deps))
var saveError error
churls := make(map[string]struct{})
var depsToDownload []*chart.Dependency
for _, dep := range deps {
// No repository means the chart is in charts directory
if dep.Repository == "" {
@ -310,22 +310,32 @@ func (m *Manager) downloadAll(deps []*chart.Dependency) error {
dep.Version = ver
continue
}
// Add dep to download list
depsToDownload = append(depsToDownload, dep)
}
// De-duplicate depsToDownload
deduplicatedDepsToDownload := deduplicateDeps(depsToDownload)
var wg sync.WaitGroup
sem := make(chan struct{}, 4)
for _, dep := range deduplicatedDepsToDownload {
wg.Add(1)
sem <- struct{}{}
go func(dep *chart.Dependency) {
defer wg.Done()
fmt.Fprintf(m.Out, "Downloading %s from repo %s\n", dep.Name, dep.Repository)
// Any failure to resolve/download a chart should fail:
// https://github.com/helm/helm/issues/1439
churl, username, password, insecureskiptlsverify, passcredentialsall, caFile, certFile, keyFile, err := m.findChartURL(dep.Name, dep.Version, dep.Repository, repos)
if err != nil {
saveError = errors.Wrapf(err, "could not find %s", churl)
break
}
if _, ok := churls[churl]; ok {
fmt.Fprintf(m.Out, "Already downloaded %s from repo %s\n", dep.Name, dep.Repository)
continue
return
}
fmt.Fprintf(m.Out, "Downloading %s from repo %s\n", dep.Name, dep.Repository)
dl := ChartDownloader{
Out: m.Out,
Verify: m.Verify,
@ -346,7 +356,8 @@ func (m *Manager) downloadAll(deps []*chart.Dependency) error {
if registry.IsOCI(churl) {
churl, version, err = parseOCIRef(churl)
if err != nil {
return errors.Wrapf(err, "could not parse OCI reference")
saveError = errors.Wrapf(err, "could not parse OCI reference")
return
}
dl.Options = append(dl.Options,
getter.WithRegistryClient(m.RegistryClient),
@ -355,12 +366,15 @@ func (m *Manager) downloadAll(deps []*chart.Dependency) error {
if _, _, err = dl.DownloadTo(churl, version, tmpPath); err != nil {
saveError = errors.Wrapf(err, "could not download %s", churl)
break
return
}
churls[churl] = struct{}{}
<-sem
}(dep)
}
wg.Wait()
// TODO: this should probably be refactored to be a []error, so we can capture and provide more information rather than "last error wins".
if saveError == nil {
// now we can move all downloaded charts to destPath and delete outdated dependencies
@ -374,6 +388,21 @@ func (m *Manager) downloadAll(deps []*chart.Dependency) error {
return nil
}
func deduplicateDeps(deps []*chart.Dependency) []*chart.Dependency {
depsMap := make(map[string]bool)
var depsResult []*chart.Dependency
for _, dep := range deps {
depKey := fmt.Sprintf("%s/%s/%s", dep.Repository, dep.Name, dep.Version)
if _, ok := depsMap[depKey]; !ok {
depsMap[depKey] = true
depsResult = append(deps, dep)
}
}
return depsResult
}
func parseOCIRef(chartRef string) (string, string, error) {
refTagRegexp := regexp.MustCompile(`^(oci://[^:]+(:[0-9]{1,5})?[^:]+):(.*)$`)
caps := refTagRegexp.FindStringSubmatch(chartRef)

Loading…
Cancel
Save