Skip to content

Commit

Permalink
implement cache for provenance files
Browse files Browse the repository at this point in the history
Signed-off-by: Christian Richter <christian@boltares.de>
  • Loading branch information
Christian authored and dragonchaser committed Apr 20, 2021
1 parent 60813b6 commit cae4857
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 29 deletions.
1 change: 1 addition & 0 deletions cmd/helm/dependency_build.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ func newDependencyBuildCmd(cfg *action.Configuration, out io.Writer) *cobra.Comm
RepositoryConfig: settings.RepositoryConfig,
RepositoryCache: settings.RepositoryCache,
DownloadCache: settings.DownloadCache,
ProvenanceCache: settings.ProvenanceCache,
Debug: settings.Debug,
}
if client.Verify {
Expand Down
1 change: 1 addition & 0 deletions cmd/helm/dependency_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ func newDependencyUpdateCmd(cfg *action.Configuration, out io.Writer) *cobra.Com
RepositoryConfig: settings.RepositoryConfig,
RepositoryCache: settings.RepositoryCache,
DownloadCache: settings.DownloadCache,
ProvenanceCache: settings.ProvenanceCache,
Debug: settings.Debug,
}
if client.Verify {
Expand Down
1 change: 1 addition & 0 deletions cmd/helm/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ func runInstall(args []string, client *action.Install, valueOpts *values.Options
RepositoryConfig: settings.RepositoryConfig,
RepositoryCache: settings.RepositoryCache,
DownloadCache: settings.DownloadCache,
ProvenanceCache: settings.ProvenanceCache,
Debug: settings.Debug,
}
if err := man.Update(); err != nil {
Expand Down
1 change: 1 addition & 0 deletions cmd/helm/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ func newPackageCmd(out io.Writer) *cobra.Command {
RepositoryConfig: settings.RepositoryConfig,
RepositoryCache: settings.RepositoryCache,
DownloadCache: settings.DownloadCache,
ProvenanceCache: settings.ProvenanceCache,
}

if err := downloadManager.Update(); err != nil {
Expand Down
1 change: 1 addition & 0 deletions pkg/action/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,7 @@ func (c *ChartPathOptions) LocateChart(name string, settings *cli.EnvSettings) (
RepositoryConfig: settings.RepositoryConfig,
RepositoryCache: settings.RepositoryCache,
DownloadCache: settings.DownloadCache,
ProvenanceCache: settings.ProvenanceCache,
}
if c.Verify {
dl.Verify = downloader.VerifyAlways
Expand Down
1 change: 1 addition & 0 deletions pkg/action/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ func (p *Pull) Run(chartRef string) (string, error) {
RepositoryConfig: p.Settings.RepositoryConfig,
RepositoryCache: p.Settings.RepositoryCache,
DownloadCache: p.Settings.DownloadCache,
ProvenanceCache: p.Settings.ProvenanceCache,
}

if strings.HasPrefix(chartRef, "oci://") {
Expand Down
3 changes: 3 additions & 0 deletions pkg/cli/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ type EnvSettings struct {
MaxHistory int
// Downloadcache for the chart downloader
DownloadCache gofilecache.Cache
// Provanencecache for downloaded provenance files
ProvenanceCache gofilecache.Cache
}

func New() *EnvSettings {
Expand All @@ -88,6 +90,7 @@ func New() *EnvSettings {
RepositoryConfig: envOr("HELM_REPOSITORY_CONFIG", helmpath.ConfigPath("repositories.yaml")),
RepositoryCache: envOr("HELM_REPOSITORY_CACHE", helmpath.CachePath("repository")),
DownloadCache: *gofilecache.InitCache(envOr("HELM_DOWNLOAD_CACHE", helmpath.CachePath("downloads"))),
ProvenanceCache: *gofilecache.InitCache(envOr("HELM_PROVENANCE_CACHE", helmpath.CachePath("provenance"))),
}
env.Debug, _ = strconv.ParseBool(os.Getenv("HELM_DEBUG"))

Expand Down
94 changes: 65 additions & 29 deletions pkg/downloader/chart_downloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ limitations under the License.
package downloader

import (
"bytes"
"fmt"
"io"
"io/ioutil"
"net/url"
"os"
"path/filepath"
Expand Down Expand Up @@ -75,6 +77,8 @@ type ChartDownloader struct {
RepositoryCache string
// DownloadCache
DownloadCache gofilecache.Cache
// ProvenanceCache
ProvenanceCache gofilecache.Cache
}

// DownloadTo retrieves a chart. Depending on the settings, it may also download a provenance file.
Expand All @@ -89,6 +93,7 @@ type ChartDownloader struct {
// 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) {
destfile := ""
u, digest, err := c.ResolveChartVersionWithDigest(ref, version)
if err != nil {
return "", nil, err
Expand All @@ -108,47 +113,78 @@ func (c *ChartDownloader) DownloadTo(ref, version, dest string) (string, *proven
fileName, _, _ := c.DownloadCache.GetFile(aID)
if fileName != "" {
fmt.Fprintf(os.Stdout, "cache hit for %s using %s\n", ref, fileName)
return fileName, nil, nil
destfile = fileName
}
}
if destfile != "" {
data, err := g.Get(u.String(), c.Options...)
if err != nil {
return "", nil, err
}

data, err := g.Get(u.String(), c.Options...)
if err != nil {
return "", nil, err
}

name := filepath.Base(u.Path)
if u.Scheme == "oci" {
name = fmt.Sprintf("%s-%s.tgz", name, version)
}
name := filepath.Base(u.Path)
if u.Scheme == "oci" {
name = fmt.Sprintf("%s-%s.tgz", name, version)
}

destfile := filepath.Join(dest, name)
destfile := filepath.Join(dest, name)

f, err := os.Open(destfile)
if err != nil {
fmt.Fprintf(os.Stderr, "Could not access the cache %e", err)
}
defer f.Close()
c.DownloadCache.Put(aID, f)
f, err := os.Open(destfile)
if err != nil {
fmt.Fprintf(os.Stderr, "Could not access the destination chart file %e", err)
}
defer f.Close()
c.DownloadCache.Put(aID, f)

if err := fileutil.AtomicWriteFile(destfile, data, 0644); err != nil {
return destfile, nil, err
if err := fileutil.AtomicWriteFile(destfile, data, 0644); err != nil {
return destfile, nil, err
}
}

// If provenance is requested, verify it.
ver := &provenance.Verification{}
cacheHit := false
if c.Verify > VerifyNever {
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")
var body *bytes.Buffer
if digest != "" {
// try to fetch the provenance file from cache
provCacheFile, _, err := c.ProvenanceCache.GetFile(aID)
if err == nil {
data, err := ioutil.ReadFile(provCacheFile)
if err == nil {
body = bytes.NewBuffer(data)
cacheHit = true
fmt.Fprintf(c.Out, "file has been read from cache")
} else {
fmt.Fprintf(c.Out, "File in cache found but could not be read, trying to get it from remote.")
}
} else {
fmt.Fprintf(c.Out, "File not found in provenance cache.")
}
fmt.Fprintf(c.Out, "WARNING: Verification not found for %s: %s\n", ref, err)
return destfile, ver, nil
}
provfile := destfile + ".prov"
if err := fileutil.AtomicWriteFile(provfile, body, 0644); err != nil {
return destfile, nil, err
if !cacheHit {
// fetch the provenance file from remote
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")
}
fmt.Fprintf(c.Out, "WARNING: Verification not found for %s: %s\n", ref, err)
return destfile, ver, nil
}
}

if !cacheHit {
// write the provenance file to the provenance cache
tmp, err := ioutil.TempFile(os.TempDir(), "prov-")
if err != nil {
fmt.Fprintf(c.Out, "Could not store temporary provenance file")
}
defer tmp.Close()
c.ProvenanceCache.Put(aID, tmp)
provfile := destfile + ".prov"
if err := fileutil.AtomicWriteFile(provfile, body, 0644); err != nil {
return destfile, nil, err
}
}

if c.Verify != VerifyLater {
Expand Down
2 changes: 2 additions & 0 deletions pkg/downloader/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ type Manager struct {
RepositoryConfig string
RepositoryCache string
DownloadCache gofilecache.Cache
ProvenanceCache gofilecache.Cache
}

// Build rebuilds a local charts directory from a lockfile.
Expand Down Expand Up @@ -333,6 +334,7 @@ func (m *Manager) downloadAll(deps []*chart.Dependency) error {
RepositoryCache: m.RepositoryCache,
Getters: m.Getters,
DownloadCache: m.DownloadCache,
ProvenanceCache: m.ProvenanceCache,
Options: []getter.Option{
getter.WithBasicAuth(username, password),
},
Expand Down

0 comments on commit cae4857

Please sign in to comment.