|
|
@ -270,7 +270,7 @@ func (m *Manager) downloadAll(deps []*chart.Dependency) error {
|
|
|
|
|
|
|
|
|
|
|
|
fmt.Fprintf(m.Out, "Saving %d charts\n", len(deps))
|
|
|
|
fmt.Fprintf(m.Out, "Saving %d charts\n", len(deps))
|
|
|
|
var saveError error
|
|
|
|
var saveError error
|
|
|
|
churls := make(map[string]struct{})
|
|
|
|
var depsToDownload []*chart.Dependency
|
|
|
|
for _, dep := range deps {
|
|
|
|
for _, dep := range deps {
|
|
|
|
// No repository means the chart is in charts directory
|
|
|
|
// No repository means the chart is in charts directory
|
|
|
|
if dep.Repository == "" {
|
|
|
|
if dep.Repository == "" {
|
|
|
@ -310,22 +310,32 @@ func (m *Manager) downloadAll(deps []*chart.Dependency) error {
|
|
|
|
dep.Version = ver
|
|
|
|
dep.Version = ver
|
|
|
|
continue
|
|
|
|
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)
|
|
|
|
churl, username, password, insecureskiptlsverify, passcredentialsall, caFile, certFile, keyFile, err := m.findChartURL(dep.Name, dep.Version, dep.Repository, repos)
|
|
|
|
if err != nil {
|
|
|
|
if err != nil {
|
|
|
|
saveError = errors.Wrapf(err, "could not find %s", churl)
|
|
|
|
saveError = errors.Wrapf(err, "could not find %s", churl)
|
|
|
|
break
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if _, ok := churls[churl]; ok {
|
|
|
|
|
|
|
|
fmt.Fprintf(m.Out, "Already downloaded %s from repo %s\n", dep.Name, dep.Repository)
|
|
|
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fmt.Fprintf(m.Out, "Downloading %s from repo %s\n", dep.Name, dep.Repository)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
dl := ChartDownloader{
|
|
|
|
dl := ChartDownloader{
|
|
|
|
Out: m.Out,
|
|
|
|
Out: m.Out,
|
|
|
|
Verify: m.Verify,
|
|
|
|
Verify: m.Verify,
|
|
|
@ -346,7 +356,8 @@ func (m *Manager) downloadAll(deps []*chart.Dependency) error {
|
|
|
|
if registry.IsOCI(churl) {
|
|
|
|
if registry.IsOCI(churl) {
|
|
|
|
churl, version, err = parseOCIRef(churl)
|
|
|
|
churl, version, err = parseOCIRef(churl)
|
|
|
|
if err != nil {
|
|
|
|
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,
|
|
|
|
dl.Options = append(dl.Options,
|
|
|
|
getter.WithRegistryClient(m.RegistryClient),
|
|
|
|
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 {
|
|
|
|
if _, _, err = dl.DownloadTo(churl, version, tmpPath); err != nil {
|
|
|
|
saveError = errors.Wrapf(err, "could not download %s", churl)
|
|
|
|
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".
|
|
|
|
// 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 {
|
|
|
|
if saveError == nil {
|
|
|
|
// now we can move all downloaded charts to destPath and delete outdated dependencies
|
|
|
|
// 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
|
|
|
|
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) {
|
|
|
|
func parseOCIRef(chartRef string) (string, string, error) {
|
|
|
|
refTagRegexp := regexp.MustCompile(`^(oci://[^:]+(:[0-9]{1,5})?[^:]+):(.*)$`)
|
|
|
|
refTagRegexp := regexp.MustCompile(`^(oci://[^:]+(:[0-9]{1,5})?[^:]+):(.*)$`)
|
|
|
|
caps := refTagRegexp.FindStringSubmatch(chartRef)
|
|
|
|
caps := refTagRegexp.FindStringSubmatch(chartRef)
|
|
|
|