From f7b010a140671e9711a2a0ca376cf9f70e468695 Mon Sep 17 00:00:00 2001 From: Matt Butcher Date: Thu, 23 Feb 2017 17:22:03 -0700 Subject: [PATCH] feat(helm): add --skip-refresh flag to 'helm dep up' This makes it possible to do a `dep up` without refetching all of the repositories.While it's less safe, it's useful when doing many updates in a short period of time (such as in a CI/CD setting) Closes #2019 --- cmd/helm/dependency_update.go | 21 ++++++++------ cmd/helm/dependency_update_test.go | 44 ++++++++++++++++++++++++++++++ pkg/downloader/manager.go | 20 ++++++++++---- 3 files changed, 70 insertions(+), 15 deletions(-) diff --git a/cmd/helm/dependency_update.go b/cmd/helm/dependency_update.go index c9aaf54de..a9569e385 100644 --- a/cmd/helm/dependency_update.go +++ b/cmd/helm/dependency_update.go @@ -41,11 +41,12 @@ in the requirements.yaml file, but (b) at the wrong version. // dependencyUpdateCmd describes a 'helm dependency update' type dependencyUpdateCmd struct { - out io.Writer - chartpath string - helmhome helmpath.Home - verify bool - keyring string + out io.Writer + chartpath string + helmhome helmpath.Home + verify bool + keyring string + skipRefresh bool } // newDependencyUpdateCmd creates a new dependency update command. @@ -80,6 +81,7 @@ func newDependencyUpdateCmd(out io.Writer) *cobra.Command { f := cmd.Flags() f.BoolVar(&duc.verify, "verify", false, "verify the packages against signatures") f.StringVar(&duc.keyring, "keyring", defaultKeyring(), "keyring containing public keys") + f.BoolVar(&duc.skipRefresh, "skip-refresh", false, "do not refresh the local repository cache") return cmd } @@ -87,10 +89,11 @@ func newDependencyUpdateCmd(out io.Writer) *cobra.Command { // run runs the full dependency update process. func (d *dependencyUpdateCmd) run() error { man := &downloader.Manager{ - Out: d.out, - ChartPath: d.chartpath, - HelmHome: d.helmhome, - Keyring: d.keyring, + Out: d.out, + ChartPath: d.chartpath, + HelmHome: d.helmhome, + Keyring: d.keyring, + SkipUpdate: d.skipRefresh, } if d.verify { man.Verify = downloader.VerifyIfPossible diff --git a/cmd/helm/dependency_update_test.go b/cmd/helm/dependency_update_test.go index b10b61f35..d64601d49 100644 --- a/cmd/helm/dependency_update_test.go +++ b/cmd/helm/dependency_update_test.go @@ -128,6 +128,50 @@ func TestDependencyUpdateCmd(t *testing.T) { } } +func TestDependencyUpdateCmd_SkipRefresh(t *testing.T) { + // Set up a testing helm home + oldhome := helmHome + hh, err := tempHelmHome(t) + if err != nil { + t.Fatal(err) + } + helmHome = hh + defer func() { + os.RemoveAll(hh) + helmHome = oldhome + }() + + srv := repotest.NewServer(hh) + defer srv.Stop() + copied, err := srv.CopyCharts("testdata/testcharts/*.tgz") + if err != nil { + t.Fatal(err) + } + t.Logf("Copied charts:\n%s", strings.Join(copied, "\n")) + t.Logf("Listening on directory %s", srv.Root()) + + chartname := "depup" + if err := createTestingChart(hh, chartname, srv.URL()); err != nil { + t.Fatal(err) + } + + out := bytes.NewBuffer(nil) + duc := &dependencyUpdateCmd{out: out} + duc.helmhome = helmpath.Home(hh) + duc.chartpath = filepath.Join(hh, chartname) + duc.skipRefresh = true + + if err := duc.run(); err == nil { + t.Fatal("Expected failure to find the repo with skipRefresh") + } + + output := out.String() + // This is written directly to stdout, so we have to capture as is. + if strings.Contains(output, `update from the "test" chart repository`) { + t.Errorf("Repo was unexpectedly updated\n%s", output) + } +} + // createTestingChart creates a basic chart that depends on reqtest-0.1.0 // // The baseURL can be used to point to a particular repository server. diff --git a/pkg/downloader/manager.go b/pkg/downloader/manager.go index cc267abd1..b8d277fbb 100644 --- a/pkg/downloader/manager.go +++ b/pkg/downloader/manager.go @@ -53,11 +53,15 @@ type Manager struct { Verify VerificationStrategy // Keyring is the key ring file. Keyring string + // SkipUpdate indicates that the repository should not be updated first. + SkipUpdate bool } // Build rebuilds a local charts directory from a lockfile. // // If the lockfile is not present, this will run a Manager.Update() +// +// If SkipUpdate is set, this will not update the repository. func (m *Manager) Build() error { c, err := m.loadChartDir() if err != nil { @@ -85,9 +89,11 @@ func (m *Manager) Build() error { return err } - // For each repo in the file, update the cached copy of that repo - if err := m.UpdateRepositories(); err != nil { - return err + if !m.SkipUpdate { + // For each repo in the file, update the cached copy of that repo + if err := m.UpdateRepositories(); err != nil { + return err + } } // Now we need to fetch every package here into charts/ @@ -102,7 +108,7 @@ func (m *Manager) Build() error { // // It first reads the requirements.yaml file, and then attempts to // negotiate versions based on that. It will download the versions -// from remote chart repositories. +// from remote chart repositories unless SkipUpdate is true. func (m *Manager) Update() error { c, err := m.loadChartDir() if err != nil { @@ -127,8 +133,10 @@ func (m *Manager) Update() error { } // For each repo in the file, update the cached copy of that repo - if err := m.UpdateRepositories(); err != nil { - return err + if !m.SkipUpdate { + if err := m.UpdateRepositories(); err != nil { + return err + } } // Now we need to find out which version of a chart best satisfies the