diff --git a/cmd/helm/repo_add.go b/cmd/helm/repo_add.go index 6a8a70a0f..62510a9bc 100644 --- a/cmd/helm/repo_add.go +++ b/cmd/helm/repo_add.go @@ -51,6 +51,7 @@ type repoAddOptions struct { passCredentialsAll bool forceUpdate bool allowDeprecatedRepos bool + timeout time.Duration certFile string keyFile string @@ -99,6 +100,7 @@ func newRepoAddCmd(out io.Writer) *cobra.Command { f.BoolVar(&o.insecureSkipTLSverify, "insecure-skip-tls-verify", false, "skip tls certificate checks for the repository") f.BoolVar(&o.allowDeprecatedRepos, "allow-deprecated-repos", false, "by default, this command will not allow adding official repos that have been permanently deleted. This disables that behavior") f.BoolVar(&o.passCredentialsAll, "pass-credentials", false, "pass credentials to all domains") + f.DurationVar(&o.timeout, "timeout", getter.DefaultHTTPTimeout*time.Second, "time to wait for the index file download to complete") return cmd } @@ -203,7 +205,7 @@ func (o *repoAddOptions) run(out io.Writer) error { return nil } - r, err := repo.NewChartRepository(&c, getter.All(settings)) + r, err := repo.NewChartRepository(&c, getter.All(settings, getter.WithTimeout(o.timeout))) if err != nil { return err } diff --git a/cmd/helm/repo_update.go b/cmd/helm/repo_update.go index 8d5f532f1..9dcc61d49 100644 --- a/cmd/helm/repo_update.go +++ b/cmd/helm/repo_update.go @@ -20,6 +20,7 @@ import ( "fmt" "io" "sync" + "time" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -45,6 +46,7 @@ type repoUpdateOptions struct { repoFile string repoCache string names []string + timeout time.Duration failOnRepoUpdateFail bool } @@ -69,6 +71,7 @@ func newRepoUpdateCmd(out io.Writer) *cobra.Command { } f := cmd.Flags() + f.DurationVar(&o.timeout, "timeout", getter.DefaultHTTPTimeout*time.Second, "time to wait for the index file download to complete") // Adding this flag for Helm 3 as stop gap functionality for https://github.com/helm/helm/issues/10016. // This should be deprecated in Helm 4 by update to the behaviour of `helm repo update` command. @@ -100,7 +103,7 @@ func (o *repoUpdateOptions) run(out io.Writer) error { for _, cfg := range f.Repositories { if updateAllRepos || isRepoRequested(cfg.Name, o.names) { - r, err := repo.NewChartRepository(cfg, getter.All(settings)) + r, err := repo.NewChartRepository(cfg, getter.All(settings, getter.WithTimeout(o.timeout))) if err != nil { return err } diff --git a/pkg/getter/getter.go b/pkg/getter/getter.go index 1acb2093d..7c73a46a9 100644 --- a/pkg/getter/getter.go +++ b/pkg/getter/getter.go @@ -196,24 +196,32 @@ const ( var defaultOptions = []Option{WithTimeout(time.Second * DefaultHTTPTimeout)} -var httpProvider = Provider{ - Schemes: []string{"http", "https"}, - New: func(options ...Option) (Getter, error) { - options = append(options, defaultOptions...) - return NewHTTPGetter(options...) - }, -} - -var ociProvider = Provider{ - Schemes: []string{registry.OCIScheme}, - New: NewOCIGetter, +func Getters(extraOpts ...Option) Providers { + return Providers{ + Provider{ + Schemes: []string{"http", "https"}, + New: func(options ...Option) (Getter, error) { + options = append(options, defaultOptions...) + options = append(options, extraOpts...) + return NewHTTPGetter(options...) + }, + }, + Provider{ + Schemes: []string{registry.OCIScheme}, + New: func(options ...Option) (Getter, error) { + options = append(options, defaultOptions...) + options = append(options, extraOpts...) + return NewOCIGetter(options...) + }, + }, + } } // All finds all of the registered getters as a list of Provider instances. // Currently, the built-in getters and the discovered plugins with downloader // notations are collected. -func All(settings *cli.EnvSettings) Providers { - result := Providers{httpProvider, ociProvider} +func All(settings *cli.EnvSettings, opts ...Option) Providers { + result := Getters(opts...) pluginDownloaders, _ := collectPlugins(settings) result = append(result, pluginDownloaders...) return result diff --git a/pkg/getter/getter_test.go b/pkg/getter/getter_test.go index ab14784ab..85ef1fbbf 100644 --- a/pkg/getter/getter_test.go +++ b/pkg/getter/getter_test.go @@ -17,6 +17,7 @@ package getter import ( "testing" + "time" "helm.sh/helm/v3/pkg/cli" ) @@ -52,6 +53,23 @@ func TestProviders(t *testing.T) { } } +func TestProvidersWithTimeout(t *testing.T) { + want := time.Hour + getters := Getters(WithTimeout(want)) + getter, err := getters.ByScheme("http") + if err != nil { + t.Error(err) + } + client, err := getter.(*HTTPGetter).httpClient() + if err != nil { + t.Error(err) + } + got := client.Timeout + if got != want { + t.Errorf("Expected %q, got %q", want, got) + } +} + func TestAll(t *testing.T) { env := cli.New() env.PluginsDirectory = pluginDir