1/* 2Copyright The Helm Authors. 3 4Licensed under the Apache License, Version 2.0 (the "License"); 5you may not use this file except in compliance with the License. 6You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10Unless required by applicable law or agreed to in writing, software 11distributed under the License is distributed on an "AS IS" BASIS, 12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13See the License for the specific language governing permissions and 14limitations under the License. 15*/ 16 17package getter 18 19import ( 20 "bytes" 21 "time" 22 23 "github.com/pkg/errors" 24 25 "helm.sh/helm/v3/internal/experimental/registry" 26 "helm.sh/helm/v3/pkg/cli" 27) 28 29// options are generic parameters to be provided to the getter during instantiation. 30// 31// Getters may or may not ignore these parameters as they are passed in. 32type options struct { 33 url string 34 certFile string 35 keyFile string 36 caFile string 37 unTar bool 38 insecureSkipVerifyTLS bool 39 username string 40 password string 41 userAgent string 42 version string 43 registryClient *registry.Client 44 timeout time.Duration 45} 46 47// Option allows specifying various settings configurable by the user for overriding the defaults 48// used when performing Get operations with the Getter. 49type Option func(*options) 50 51// WithURL informs the getter the server name that will be used when fetching objects. Used in conjunction with 52// WithTLSClientConfig to set the TLSClientConfig's server name. 53func WithURL(url string) Option { 54 return func(opts *options) { 55 opts.url = url 56 } 57} 58 59// WithBasicAuth sets the request's Authorization header to use the provided credentials 60func WithBasicAuth(username, password string) Option { 61 return func(opts *options) { 62 opts.username = username 63 opts.password = password 64 } 65} 66 67// WithUserAgent sets the request's User-Agent header to use the provided agent name. 68func WithUserAgent(userAgent string) Option { 69 return func(opts *options) { 70 opts.userAgent = userAgent 71 } 72} 73 74// WithInsecureSkipVerifyTLS determines if a TLS Certificate will be checked 75func WithInsecureSkipVerifyTLS(insecureSkipVerifyTLS bool) Option { 76 return func(opts *options) { 77 opts.insecureSkipVerifyTLS = insecureSkipVerifyTLS 78 } 79} 80 81// WithTLSClientConfig sets the client auth with the provided credentials. 82func WithTLSClientConfig(certFile, keyFile, caFile string) Option { 83 return func(opts *options) { 84 opts.certFile = certFile 85 opts.keyFile = keyFile 86 opts.caFile = caFile 87 } 88} 89 90// WithTimeout sets the timeout for requests 91func WithTimeout(timeout time.Duration) Option { 92 return func(opts *options) { 93 opts.timeout = timeout 94 } 95} 96 97func WithTagName(tagname string) Option { 98 return func(opts *options) { 99 opts.version = tagname 100 } 101} 102 103func WithRegistryClient(client *registry.Client) Option { 104 return func(opts *options) { 105 opts.registryClient = client 106 } 107} 108 109func WithUntar() Option { 110 return func(opts *options) { 111 opts.unTar = true 112 } 113} 114 115// Getter is an interface to support GET to the specified URL. 116type Getter interface { 117 // Get file content by url string 118 Get(url string, options ...Option) (*bytes.Buffer, error) 119} 120 121// Constructor is the function for every getter which creates a specific instance 122// according to the configuration 123type Constructor func(options ...Option) (Getter, error) 124 125// Provider represents any getter and the schemes that it supports. 126// 127// For example, an HTTP provider may provide one getter that handles both 128// 'http' and 'https' schemes. 129type Provider struct { 130 Schemes []string 131 New Constructor 132} 133 134// Provides returns true if the given scheme is supported by this Provider. 135func (p Provider) Provides(scheme string) bool { 136 for _, i := range p.Schemes { 137 if i == scheme { 138 return true 139 } 140 } 141 return false 142} 143 144// Providers is a collection of Provider objects. 145type Providers []Provider 146 147// ByScheme returns a Provider that handles the given scheme. 148// 149// If no provider handles this scheme, this will return an error. 150func (p Providers) ByScheme(scheme string) (Getter, error) { 151 for _, pp := range p { 152 if pp.Provides(scheme) { 153 return pp.New() 154 } 155 } 156 return nil, errors.Errorf("scheme %q not supported", scheme) 157} 158 159var httpProvider = Provider{ 160 Schemes: []string{"http", "https"}, 161 New: NewHTTPGetter, 162} 163 164var ociProvider = Provider{ 165 Schemes: []string{"oci"}, 166 New: NewOCIGetter, 167} 168 169// All finds all of the registered getters as a list of Provider instances. 170// Currently, the built-in getters and the discovered plugins with downloader 171// notations are collected. 172func All(settings *cli.EnvSettings) Providers { 173 result := Providers{httpProvider, ociProvider} 174 pluginDownloaders, _ := collectPlugins(settings) 175 result = append(result, pluginDownloaders...) 176 return result 177} 178