diff --git a/cmd/helm/install.go b/cmd/helm/install.go index e930b6589..0f4f3d4c8 100644 --- a/cmd/helm/install.go +++ b/cmd/helm/install.go @@ -210,6 +210,10 @@ func runInstall(args []string, client *action.Install, valueOpts *values.Options return nil, err } + if client.ChartPathOptions.RepoURL != "" { + chartRequested.Metadata.RepoURL = client.ChartPathOptions.RepoURL + } + if err := checkIfInstallable(chartRequested); err != nil { return nil, err } diff --git a/cmd/helm/upgrade.go b/cmd/helm/upgrade.go index 6fc6eb9a1..2e9a496f4 100644 --- a/cmd/helm/upgrade.go +++ b/cmd/helm/upgrade.go @@ -152,6 +152,9 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { if err != nil { return err } + if client.ChartPathOptions.RepoURL != "" && ch.Metadata.RepoURL == "" { + ch.Metadata.RepoURL = client.ChartPathOptions.RepoURL + } if req := ch.Metadata.Dependencies; req != nil { if err := action.CheckDependencies(ch, req); err != nil { if client.DependencyUpdate { diff --git a/pkg/action/install.go b/pkg/action/install.go index b84a57271..215b43f10 100644 --- a/pkg/action/install.go +++ b/pkg/action/install.go @@ -750,7 +750,8 @@ func (c *ChartPathOptions) LocateChart(name string, settings *cli.EnvSettings) ( return "", err } - filename, _, err := dl.DownloadTo(name, version, settings.RepositoryCache) + filename, rURL, _, err := dl.DownloadTo(name, version, settings.RepositoryCache) + c.RepoURL = rURL if err == nil { lname, err := filepath.Abs(filename) if err != nil { diff --git a/pkg/action/pull.go b/pkg/action/pull.go index 2f5127ea9..ee7f756b4 100644 --- a/pkg/action/pull.go +++ b/pkg/action/pull.go @@ -127,7 +127,7 @@ func (p *Pull) Run(chartRef string) (string, error) { chartRef = chartURL } - saved, v, err := c.DownloadTo(chartRef, p.Version, dest) + saved, _, v, err := c.DownloadTo(chartRef, p.Version, dest) if err != nil { return out.String(), err } diff --git a/pkg/chart/metadata.go b/pkg/chart/metadata.go index 1925e45ac..7ff26ee9c 100644 --- a/pkg/chart/metadata.go +++ b/pkg/chart/metadata.go @@ -77,6 +77,8 @@ type Metadata struct { Dependencies []*Dependency `json:"dependencies,omitempty"` // Specifies the chart type: application or library Type string `json:"type,omitempty"` + // Specifies the chart URL that was used to initially install a chart. + RepoURL string `json:"repoURL,omitempty"` } // Validate checks the metadata for known issues and sanitizes string @@ -94,6 +96,7 @@ func (md *Metadata) Validate() error { md.Tags = sanitizeString(md.Tags) md.AppVersion = sanitizeString(md.AppVersion) md.KubeVersion = sanitizeString(md.KubeVersion) + md.RepoURL = sanitizeString(md.RepoURL) for i := range md.Sources { md.Sources[i] = sanitizeString(md.Sources[i]) } diff --git a/pkg/downloader/chart_downloader.go b/pkg/downloader/chart_downloader.go index 93afb1461..56bd90afc 100644 --- a/pkg/downloader/chart_downloader.go +++ b/pkg/downloader/chart_downloader.go @@ -72,6 +72,7 @@ type ChartDownloader struct { RegistryClient *registry.Client RepositoryConfig string RepositoryCache string + RepositoryURL string } // DownloadTo retrieves a chart. Depending on the settings, it may also download a provenance file. @@ -83,22 +84,22 @@ type ChartDownloader struct { // // For VerifyNever and VerifyIfPossible, the Verification may be empty. // -// Returns a string path to the location where the file was downloaded and a verification -// (if provenance was verified), or an error if something bad happened. -func (c *ChartDownloader) DownloadTo(ref, version, dest string) (string, *provenance.Verification, error) { +// Returns two strings, the first of which is a path to the location where the file was downloaded, the second being the repository URL. +// Also returned is a verification (if provenance was verified), or an error if something bad happened. +func (c *ChartDownloader) DownloadTo(ref, version, dest string) (string, string, *provenance.Verification, error) { u, err := c.ResolveChartVersion(ref, version) if err != nil { - return "", nil, err + return "", "", nil, err } g, err := c.Getters.ByScheme(u.Scheme) if err != nil { - return "", nil, err + return "", "", nil, err } data, err := g.Get(u.String(), c.Options...) if err != nil { - return "", nil, err + return "", "", nil, err } name := filepath.Base(u.Path) @@ -108,7 +109,7 @@ func (c *ChartDownloader) DownloadTo(ref, version, dest string) (string, *proven destfile := filepath.Join(dest, name) if err := fileutil.AtomicWriteFile(destfile, data, 0644); err != nil { - return destfile, nil, err + return destfile, c.RepositoryURL, nil, err } // If provenance is requested, verify it. @@ -117,14 +118,14 @@ func (c *ChartDownloader) DownloadTo(ref, version, dest string) (string, *proven body, err := g.Get(u.String() + ".prov") if err != nil { if c.Verify == VerifyAlways { - return destfile, ver, errors.Errorf("failed to fetch provenance %q", u.String()+".prov") + return destfile, c.RepositoryURL, ver, errors.Errorf("failed to fetch provenance %q", u.String()+".prov") } fmt.Fprintf(c.Out, "WARNING: Verification not found for %s: %s\n", ref, err) - return destfile, ver, nil + return destfile, c.RepositoryURL, ver, nil } provfile := destfile + ".prov" if err := fileutil.AtomicWriteFile(provfile, body, 0644); err != nil { - return destfile, nil, err + return destfile, c.RepositoryURL, nil, err } if c.Verify != VerifyLater { @@ -132,11 +133,11 @@ func (c *ChartDownloader) DownloadTo(ref, version, dest string) (string, *proven if err != nil { // Fail always in this case, since it means the verification step // failed. - return destfile, ver, err + return destfile, c.RepositoryURL, ver, err } } } - return destfile, ver, nil + return destfile, c.RepositoryURL, ver, nil } // ResolveChartVersion resolves a chart reference to a URL. @@ -226,6 +227,9 @@ func (c *ChartDownloader) ResolveChartVersion(ref, version string) (*url.URL, er } if r != nil && r.Config != nil { + if r.Config.URL != "" && c.RepositoryURL == "" { + c.RepositoryURL = r.Config.URL + } if r.Config.CertFile != "" || r.Config.KeyFile != "" || r.Config.CAFile != "" { c.Options = append(c.Options, getter.WithTLSClientConfig(r.Config.CertFile, r.Config.KeyFile, r.Config.CAFile)) } diff --git a/pkg/downloader/chart_downloader_test.go b/pkg/downloader/chart_downloader_test.go index f70a56422..fe8a64e6b 100644 --- a/pkg/downloader/chart_downloader_test.go +++ b/pkg/downloader/chart_downloader_test.go @@ -197,7 +197,7 @@ func TestDownloadTo(t *testing.T) { } cname := "/signtest-0.1.0.tgz" dest := srv.Root() - where, v, err := c.DownloadTo(srv.URL()+cname, "", dest) + where, _, v, err := c.DownloadTo(srv.URL()+cname, "", dest) if err != nil { t.Fatal(err) } @@ -248,7 +248,7 @@ func TestDownloadTo_TLS(t *testing.T) { } cname := "test/signtest" dest := srv.Root() - where, v, err := c.DownloadTo(cname, "", dest) + where, _, v, err := c.DownloadTo(cname, "", dest) if err != nil { t.Fatal(err) } @@ -294,7 +294,7 @@ func TestDownloadTo_VerifyLater(t *testing.T) { }), } cname := "/signtest-0.1.0.tgz" - where, _, err := c.DownloadTo(srv.URL()+cname, "", dest) + where, _, _, err := c.DownloadTo(srv.URL()+cname, "", dest) if err != nil { t.Fatal(err) } diff --git a/pkg/downloader/manager.go b/pkg/downloader/manager.go index 52f1a1312..4a59889b8 100644 --- a/pkg/downloader/manager.go +++ b/pkg/downloader/manager.go @@ -357,7 +357,7 @@ func (m *Manager) downloadAll(deps []*chart.Dependency) error { getter.WithTagName(version)) } - 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) break }