feat(cmd): Allow to specify which repos to update

This is a port to helm v3 of #5182.
A little more flexible than the v2 version, it allows to specify a list
of repositories that should be updated.

Signed-off-by: Marc Khouzam <marc.khouzam@montreal.ca>
pull/9934/head
Marc Khouzam 3 years ago committed by Marc Khouzam
parent 21251378b4
commit 6951cd5076

@ -32,6 +32,10 @@ import (
const updateDesc = ` const updateDesc = `
Update gets the latest information about charts from the respective chart repositories. Update gets the latest information about charts from the respective chart repositories.
Information is cached locally, where it is used by commands like 'helm search'. Information is cached locally, where it is used by commands like 'helm search'.
You can optionally specify a list of repositories you want to update.
$ helm repo update <repo_name> ...
To update all the repositories, use 'helm repo update'.
` `
var errNoRepositories = errors.New("no repositories found. You must add one before updating") var errNoRepositories = errors.New("no repositories found. You must add one before updating")
@ -40,21 +44,25 @@ type repoUpdateOptions struct {
update func([]*repo.ChartRepository, io.Writer) update func([]*repo.ChartRepository, io.Writer)
repoFile string repoFile string
repoCache string repoCache string
names []string
} }
func newRepoUpdateCmd(out io.Writer) *cobra.Command { func newRepoUpdateCmd(out io.Writer) *cobra.Command {
o := &repoUpdateOptions{update: updateCharts} o := &repoUpdateOptions{update: updateCharts}
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "update", Use: "update [REPO1 [REPO2 ...]]",
Aliases: []string{"up"}, Aliases: []string{"up"},
Short: "update information of available charts locally from chart repositories", Short: "update information of available charts locally from chart repositories",
Long: updateDesc, Long: updateDesc,
Args: require.NoArgs, Args: require.MinimumNArgs(0),
ValidArgsFunction: noCompletions, ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return compListRepos(toComplete, args), cobra.ShellCompDirectiveNoFileComp
},
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
o.repoFile = settings.RepositoryConfig o.repoFile = settings.RepositoryConfig
o.repoCache = settings.RepositoryCache o.repoCache = settings.RepositoryCache
o.names = args
return o.run(out) return o.run(out)
}, },
} }
@ -73,15 +81,26 @@ func (o *repoUpdateOptions) run(out io.Writer) error {
} }
var repos []*repo.ChartRepository var repos []*repo.ChartRepository
for _, cfg := range f.Repositories { updateAllRepos := len(o.names) == 0
r, err := repo.NewChartRepository(cfg, getter.All(settings))
if err != nil { if !updateAllRepos {
// Fail early if the user specified an invalid repo to update
if err := checkRequestedRepos(o.names, f.Repositories); err != nil {
return err return err
} }
if o.repoCache != "" { }
r.CachePath = o.repoCache
for _, cfg := range f.Repositories {
if updateAllRepos || isRepoRequested(cfg.Name, o.names) {
r, err := repo.NewChartRepository(cfg, getter.All(settings))
if err != nil {
return err
}
if o.repoCache != "" {
r.CachePath = o.repoCache
}
repos = append(repos, r)
} }
repos = append(repos, r)
} }
o.update(repos, out) o.update(repos, out)
@ -105,3 +124,28 @@ func updateCharts(repos []*repo.ChartRepository, out io.Writer) {
wg.Wait() wg.Wait()
fmt.Fprintln(out, "Update Complete. ⎈Happy Helming!⎈") fmt.Fprintln(out, "Update Complete. ⎈Happy Helming!⎈")
} }
func checkRequestedRepos(requestedRepos []string, validRepos []*repo.Entry) error {
for _, requestedRepo := range requestedRepos {
found := false
for _, repo := range validRepos {
if requestedRepo == repo.Name {
found = true
break
}
}
if !found {
return errors.Errorf("no repositories found matching '%s'. Nothing will be updated", requestedRepo)
}
}
return nil
}
func isRepoRequested(repoName string, requestedRepos []string) bool {
for _, requestedRepo := range requestedRepos {
if repoName == requestedRepo {
return true
}
}
return false
}

@ -48,8 +48,54 @@ func TestUpdateCmd(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
if got := out.String(); !strings.Contains(got, "charts") { if got := out.String(); !strings.Contains(got, "charts") ||
t.Errorf("Expected 'charts' got %q", got) !strings.Contains(got, "firstexample") ||
!strings.Contains(got, "secondexample") {
t.Errorf("Expected 'charts', 'firstexample' and 'secondexample' but got %q", got)
}
}
func TestUpdateCmdMultiple(t *testing.T) {
var out bytes.Buffer
// Instead of using the HTTP updater, we provide our own for this test.
// The TestUpdateCharts test verifies the HTTP behavior independently.
updater := func(repos []*repo.ChartRepository, out io.Writer) {
for _, re := range repos {
fmt.Fprintln(out, re.Config.Name)
}
}
o := &repoUpdateOptions{
update: updater,
repoFile: "testdata/repositories.yaml",
names: []string{"firstexample", "charts"},
}
if err := o.run(&out); err != nil {
t.Fatal(err)
}
if got := out.String(); !strings.Contains(got, "charts") ||
!strings.Contains(got, "firstexample") ||
strings.Contains(got, "secondexample") {
t.Errorf("Expected 'charts' and 'firstexample' but not 'secondexample' but got %q", got)
}
}
func TestUpdateCmdInvalid(t *testing.T) {
var out bytes.Buffer
// Instead of using the HTTP updater, we provide our own for this test.
// The TestUpdateCharts test verifies the HTTP behavior independently.
updater := func(repos []*repo.ChartRepository, out io.Writer) {
for _, re := range repos {
fmt.Fprintln(out, re.Config.Name)
}
}
o := &repoUpdateOptions{
update: updater,
repoFile: "testdata/repositories.yaml",
names: []string{"firstexample", "invalid"},
}
if err := o.run(&out); err == nil {
t.Fatal("expected error but did not get one")
} }
} }
@ -111,4 +157,5 @@ func TestUpdateCharts(t *testing.T) {
func TestRepoUpdateFileCompletion(t *testing.T) { func TestRepoUpdateFileCompletion(t *testing.T) {
checkFileCompletion(t, "repo update", false) checkFileCompletion(t, "repo update", false)
checkFileCompletion(t, "repo update repo1", false)
} }

@ -2,3 +2,8 @@ apiVersion: v1
repositories: repositories:
- name: charts - name: charts
url: "https://charts.helm.sh/stable" url: "https://charts.helm.sh/stable"
- name: firstexample
url: "http://firstexample.com"
- name: secondexample
url: "http://secondexample.com"

Loading…
Cancel
Save