Merge pull request #5922 from bacongobbler/pass-parameters-to-chartdownloader

ref(downloader): pass in options to ChartDownloader
pull/6059/head
Matthew Fisher 5 years ago committed by GitHub
commit ec68243dbb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -630,8 +630,9 @@ func (c *ChartPathOptions) LocateChart(name string, settings cli.EnvSettings) (s
Out: os.Stdout, Out: os.Stdout,
Keyring: c.Keyring, Keyring: c.Keyring,
Getters: getter.All(settings), Getters: getter.All(settings),
Username: c.Username, Options: []getter.Option{
Password: c.Password, getter.WithBasicAuth(c.Username, c.Password),
},
} }
if c.Verify { if c.Verify {
dl.Verify = downloader.VerifyAlways dl.Verify = downloader.VerifyAlways

@ -62,8 +62,9 @@ func (p *Pull) Run(chartRef string) (string, error) {
Keyring: p.Keyring, Keyring: p.Keyring,
Verify: downloader.VerifyNever, Verify: downloader.VerifyNever,
Getters: getter.All(p.Settings), Getters: getter.All(p.Settings),
Username: p.Username, Options: []getter.Option{
Password: p.Password, getter.WithBasicAuth(p.Username, p.Password),
},
} }
if p.Verify { if p.Verify {

@ -68,10 +68,8 @@ type ChartDownloader struct {
HelmHome helmpath.Home HelmHome helmpath.Home
// Getter collection for the operation // Getter collection for the operation
Getters getter.Providers Getters getter.Providers
// Chart repository username // Options provide parameters to be passed along to the Getter being initialized.
Username string Options []getter.Option
// Chart repository password
Password string
} }
// DownloadTo retrieves a chart. Depending on the settings, it may also download a provenance file. // DownloadTo retrieves a chart. Depending on the settings, it may also download a provenance file.
@ -86,7 +84,17 @@ type ChartDownloader struct {
// Returns a string path to the location where the file was downloaded and a verification // 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. // (if provenance was verified), or an error if something bad happened.
func (c *ChartDownloader) DownloadTo(ref, version, dest string) (string, *provenance.Verification, error) { func (c *ChartDownloader) DownloadTo(ref, version, dest string) (string, *provenance.Verification, error) {
u, g, err := c.ResolveChartVersion(ref, version) u, err := c.ResolveChartVersion(ref, version)
if err != nil {
return "", nil, err
}
constructor, err := c.Getters.ByScheme(u.Scheme)
if err != nil {
return "", nil, err
}
g, err := constructor(c.Options...)
if err != nil { if err != nil {
return "", nil, err return "", nil, err
} }
@ -132,8 +140,8 @@ func (c *ChartDownloader) DownloadTo(ref, version, dest string) (string, *proven
// ResolveChartVersion resolves a chart reference to a URL. // ResolveChartVersion resolves a chart reference to a URL.
// //
// It returns the URL as well as a preconfigured repo.Getter that can fetch // It returns the URL and sets the ChartDownloader's Options that can fetch
// the URL. // the URL using the appropriate Getter.
// //
// A reference may be an HTTP URL, a 'reponame/chartname' reference, or a local path. // A reference may be an HTTP URL, a 'reponame/chartname' reference, or a local path.
// //
@ -144,21 +152,16 @@ func (c *ChartDownloader) DownloadTo(ref, version, dest string) (string, *proven
// * If version is non-empty, this will return the URL for that version // * If version is non-empty, this will return the URL for that version
// * If version is empty, this will return the URL for the latest version // * If version is empty, this will return the URL for the latest version
// * If no version can be found, an error is returned // * If no version can be found, an error is returned
func (c *ChartDownloader) ResolveChartVersion(ref, version string) (*url.URL, getter.Getter, error) { func (c *ChartDownloader) ResolveChartVersion(ref, version string) (*url.URL, error) {
u, err := url.Parse(ref) u, err := url.Parse(ref)
if err != nil { if err != nil {
return nil, nil, errors.Errorf("invalid chart URL format: %s", ref) return nil, errors.Errorf("invalid chart URL format: %s", ref)
} }
c.Options = append(c.Options, getter.WithURL(ref))
rf, err := repo.LoadFile(c.HelmHome.RepositoryFile()) rf, err := repo.LoadFile(c.HelmHome.RepositoryFile())
if err != nil { if err != nil {
return u, nil, err return u, err
}
// TODO add user-agent
g, err := getter.NewHTTPGetter(getter.WithURL(ref))
if err != nil {
return u, nil, err
} }
if u.IsAbs() && len(u.Host) > 0 && len(u.Path) > 0 { if u.IsAbs() && len(u.Host) > 0 && len(u.Path) > 0 {
@ -173,24 +176,31 @@ func (c *ChartDownloader) ResolveChartVersion(ref, version string) (*url.URL, ge
// If there is no special config, return the default HTTP client and // If there is no special config, return the default HTTP client and
// swallow the error. // swallow the error.
if err == ErrNoOwnerRepo { if err == ErrNoOwnerRepo {
r := &repo.ChartRepository{} return u, nil
r.Client = g
g.SetBasicAuth(c.getRepoCredentials(r))
return u, g, nil
} }
return u, nil, err return u, err
} }
r, err := repo.NewChartRepository(rc, c.Getters)
// If we get here, we don't need to go through the next phase of looking // If we get here, we don't need to go through the next phase of looking
// up the URL. We have it already. So we just return. // up the URL. We have it already. So we just set the parameters and return.
return u, r.Client, err c.Options = append(
c.Options,
getter.WithURL(rc.URL),
getter.WithTLSClientConfig(rc.CertFile, rc.KeyFile, rc.CAFile),
)
if rc.Username != "" && rc.Password != "" {
c.Options = append(
c.Options,
getter.WithBasicAuth(rc.Username, rc.Password),
)
}
return u, nil
} }
// See if it's of the form: repo/path_to_chart // See if it's of the form: repo/path_to_chart
p := strings.SplitN(u.Path, "/", 2) p := strings.SplitN(u.Path, "/", 2)
if len(p) < 2 { if len(p) < 2 {
return u, nil, errors.Errorf("non-absolute URLs should be in form of repo_name/path_to_chart, got: %s", u) return u, errors.Errorf("non-absolute URLs should be in form of repo_name/path_to_chart, got: %s", u)
} }
repoName := p[0] repoName := p[0]
@ -198,41 +208,43 @@ func (c *ChartDownloader) ResolveChartVersion(ref, version string) (*url.URL, ge
rc, err := pickChartRepositoryConfigByName(repoName, rf.Repositories) rc, err := pickChartRepositoryConfigByName(repoName, rf.Repositories)
if err != nil { if err != nil {
return u, nil, err return u, err
} }
r, err := repo.NewChartRepository(rc, c.Getters) r, err := repo.NewChartRepository(rc, c.Getters)
if err != nil { if err != nil {
return u, nil, err return u, err
}
if r != nil && r.Config != nil && r.Config.Username != "" && r.Config.Password != "" {
c.Options = append(c.Options, getter.WithBasicAuth(r.Config.Username, r.Config.Password))
} }
g.SetBasicAuth(c.getRepoCredentials(r))
// Next, we need to load the index, and actually look up the chart. // Next, we need to load the index, and actually look up the chart.
i, err := repo.LoadIndexFile(c.HelmHome.CacheIndex(r.Config.Name)) i, err := repo.LoadIndexFile(c.HelmHome.CacheIndex(r.Config.Name))
if err != nil { if err != nil {
return u, g, errors.Wrap(err, "no cached repo found. (try 'helm repo update')") return u, errors.Wrap(err, "no cached repo found. (try 'helm repo update')")
} }
cv, err := i.Get(chartName, version) cv, err := i.Get(chartName, version)
if err != nil { if err != nil {
return u, g, errors.Wrapf(err, "chart %q matching %s not found in %s index. (try 'helm repo update')", chartName, version, r.Config.Name) return u, errors.Wrapf(err, "chart %q matching %s not found in %s index. (try 'helm repo update')", chartName, version, r.Config.Name)
} }
if len(cv.URLs) == 0 { if len(cv.URLs) == 0 {
return u, g, errors.Errorf("chart %q has no downloadable URLs", ref) return u, errors.Errorf("chart %q has no downloadable URLs", ref)
} }
// TODO: Seems that picking first URL is not fully correct // TODO: Seems that picking first URL is not fully correct
u, err = url.Parse(cv.URLs[0]) u, err = url.Parse(cv.URLs[0])
if err != nil { if err != nil {
return u, g, errors.Errorf("invalid chart URL format: %s", ref) return u, errors.Errorf("invalid chart URL format: %s", ref)
} }
// If the URL is relative (no scheme), prepend the chart repo's base URL // If the URL is relative (no scheme), prepend the chart repo's base URL
if !u.IsAbs() { if !u.IsAbs() {
repoURL, err := url.Parse(rc.URL) repoURL, err := url.Parse(rc.URL)
if err != nil { if err != nil {
return repoURL, nil, err return repoURL, err
} }
q := repoURL.Query() q := repoURL.Query()
// We need a trailing slash for ResolveReference to work, but make sure there isn't already one // We need a trailing slash for ResolveReference to work, but make sure there isn't already one
@ -240,32 +252,17 @@ func (c *ChartDownloader) ResolveChartVersion(ref, version string) (*url.URL, ge
u = repoURL.ResolveReference(u) u = repoURL.ResolveReference(u)
u.RawQuery = q.Encode() u.RawQuery = q.Encode()
// TODO add user-agent // TODO add user-agent
g, err := getter.NewHTTPGetter(getter.WithURL(rc.URL)) if _, err := getter.NewHTTPGetter(getter.WithURL(rc.URL)); err != nil {
if err != nil { return repoURL, err
return repoURL, nil, err
} }
g.SetBasicAuth(c.getRepoCredentials(r)) if r != nil && r.Config != nil && r.Config.Username != "" && r.Config.Password != "" {
return u, g, err c.Options = append(c.Options, getter.WithBasicAuth(r.Config.Username, r.Config.Password))
}
return u, g, nil
}
// If this ChartDownloader is not configured to use credentials, and the chart repository sent as an argument is,
// then the repository's configured credentials are returned.
// Else, this ChartDownloader's credentials are returned.
func (c *ChartDownloader) getRepoCredentials(r *repo.ChartRepository) (username, password string) {
username = c.Username
password = c.Password
if r != nil && r.Config != nil {
if username == "" {
username = r.Config.Username
}
if password == "" {
password = r.Config.Password
} }
return u, err
} }
return
// TODO add user-agent
return u, nil
} }
// VerifyChart takes a path to a chart archive and a keyring, and verifies the chart. // VerifyChart takes a path to a chart archive and a keyring, and verifies the chart.

@ -16,11 +16,8 @@ limitations under the License.
package downloader package downloader
import ( import (
"fmt"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"net/http/httptest"
"net/url"
"os" "os"
"path/filepath" "path/filepath"
"testing" "testing"
@ -61,7 +58,7 @@ func TestResolveChartRef(t *testing.T) {
} }
for _, tt := range tests { for _, tt := range tests {
u, _, err := c.ResolveChartVersion(tt.ref, tt.version) u, err := c.ResolveChartVersion(tt.ref, tt.version)
if err != nil { if err != nil {
if tt.fail { if tt.fail {
continue continue
@ -87,78 +84,88 @@ func TestVerifyChart(t *testing.T) {
} }
} }
func TestDownload(t *testing.T) { func TestIsTar(t *testing.T) {
expect := "Call me Ishmael" tests := map[string]bool{
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { "foo.tgz": true,
fmt.Fprint(w, expect) "foo/bar/baz.tgz": true,
})) "foo-1.2.3.4.5.tgz": true,
defer srv.Close() "foo.tar.gz": false, // for our purposes
"foo.tgz.1": false,
provider, err := getter.ByScheme("http", cli.EnvSettings{}) "footgz": false,
if err != nil {
t.Fatal("No http provider found")
} }
g, err := provider.New(getter.WithURL(srv.URL)) for src, expect := range tests {
if err != nil { if isTar(src) != expect {
t.Fatal(err) t.Errorf("%q should be %t", src, expect)
}
} }
got, err := g.Get(srv.URL) }
func TestDownloadTo(t *testing.T) {
tmp, err := ioutil.TempDir("", "helm-downloadto-")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
defer os.RemoveAll(tmp)
if got.String() != expect { hh := helmpath.Home(tmp)
t.Errorf("Expected %q, got %q", expect, got.String()) dest := filepath.Join(hh.String(), "dest")
configDirectories := []string{
hh.String(),
hh.Repository(),
hh.Cache(),
dest,
} }
for _, p := range configDirectories {
// test with server backed by basic auth if fi, err := os.Stat(p); err != nil {
basicAuthSrv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if err := os.MkdirAll(p, 0755); err != nil {
username, password, ok := r.BasicAuth() t.Fatalf("Could not create %s: %s", p, err)
if !ok || username != "username" || password != "password" { }
t.Errorf("Expected request to use basic auth and for username == 'username' and password == 'password', got '%v', '%s', '%s'", ok, username, password) } else if !fi.IsDir() {
t.Fatalf("%s must be a directory", p)
} }
fmt.Fprint(w, expect) }
}))
defer basicAuthSrv.Close()
u, _ := url.ParseRequestURI(basicAuthSrv.URL) // Set up a fake repo
httpgetter, err := getter.NewHTTPGetter( srv := repotest.NewServer(tmp)
getter.WithURL(u.String()), defer srv.Stop()
getter.WithBasicAuth("username", "password"), if _, err := srv.CopyCharts("testdata/*.tgz*"); err != nil {
) t.Error(err)
if err != nil { return
}
if err := srv.LinkIndices(); err != nil {
t.Fatal(err) t.Fatal(err)
} }
got, err = httpgetter.Get(u.String())
c := ChartDownloader{
HelmHome: hh,
Out: os.Stderr,
Verify: VerifyAlways,
Keyring: "testdata/helm-test-key.pub",
Getters: getter.All(cli.EnvSettings{}),
}
cname := "/signtest-0.1.0.tgz"
where, v, err := c.DownloadTo(srv.URL()+cname, "", dest)
if err != nil { if err != nil {
t.Fatal(err) t.Error(err)
return
} }
if got.String() != expect { if expect := filepath.Join(dest, cname); where != expect {
t.Errorf("Expected %q, got %q", expect, got.String()) t.Errorf("Expected download to %s, got %s", expect, where)
} }
}
func TestIsTar(t *testing.T) { if v.FileHash == "" {
tests := map[string]bool{ t.Error("File hash was empty, but verification is required.")
"foo.tgz": true,
"foo/bar/baz.tgz": true,
"foo-1.2.3.4.5.tgz": true,
"foo.tar.gz": false, // for our purposes
"foo.tgz.1": false,
"footgz": false,
} }
for src, expect := range tests { if _, err := os.Stat(filepath.Join(dest, cname)); err != nil {
if isTar(src) != expect { t.Error(err)
t.Errorf("%q should be %t", src, expect) return
}
} }
} }
func TestDownloadTo(t *testing.T) { func TestDownloadTo_WithOptions(t *testing.T) {
tmp, err := ioutil.TempDir("", "helm-downloadto-") tmp, err := ioutil.TempDir("", "helm-downloadto-")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -183,8 +190,16 @@ func TestDownloadTo(t *testing.T) {
} }
} }
// Set up a fake repo // Set up a fake repo with basic auth enabled
srv := repotest.NewServer(tmp) srv := repotest.NewServer(tmp)
srv.Stop()
srv.WithMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
username, password, ok := r.BasicAuth()
if !ok || username != "username" || password != "password" {
t.Errorf("Expected request to use basic auth and for username == 'username' and password == 'password', got '%v', '%s', '%s'", ok, username, password)
}
}))
srv.Start()
defer srv.Stop() defer srv.Stop()
if _, err := srv.CopyCharts("testdata/*.tgz*"); err != nil { if _, err := srv.CopyCharts("testdata/*.tgz*"); err != nil {
t.Error(err) t.Error(err)
@ -200,6 +215,9 @@ func TestDownloadTo(t *testing.T) {
Verify: VerifyAlways, Verify: VerifyAlways,
Keyring: "testdata/helm-test-key.pub", Keyring: "testdata/helm-test-key.pub",
Getters: getter.All(cli.EnvSettings{}), Getters: getter.All(cli.EnvSettings{}),
Options: []getter.Option{
getter.WithBasicAuth("username", "password"),
},
} }
cname := "/signtest-0.1.0.tgz" cname := "/signtest-0.1.0.tgz"
where, v, err := c.DownloadTo(srv.URL()+cname, "", dest) where, v, err := c.DownloadTo(srv.URL()+cname, "", dest)

@ -236,8 +236,9 @@ func (m *Manager) downloadAll(deps []*chart.Dependency) error {
Keyring: m.Keyring, Keyring: m.Keyring,
HelmHome: m.HelmHome, HelmHome: m.HelmHome,
Getters: m.Getters, Getters: m.Getters,
Username: username, Options: []getter.Option{
Password: password, getter.WithBasicAuth(username, password),
},
} }
if _, _, err := dl.DownloadTo(churl, "", destPath); err != nil { if _, _, err := dl.DownloadTo(churl, "", destPath); err != nil {

@ -124,7 +124,7 @@ func All(settings cli.EnvSettings) Providers {
result := Providers{ result := Providers{
{ {
Schemes: []string{"http", "https"}, Schemes: []string{"http", "https"},
New: newHTTPGetter, New: NewHTTPGetter,
}, },
} }
pluginDownloaders, _ := collectPlugins(settings) pluginDownloaders, _ := collectPlugins(settings)

@ -32,17 +32,6 @@ type HTTPGetter struct {
opts options opts options
} }
// SetBasicAuth sets the request's Authorization header to use the provided credentials.
func (g *HTTPGetter) SetBasicAuth(username, password string) {
g.opts.username = username
g.opts.password = password
}
// SetUserAgent sets the request's User-Agent header to use the provided agent name.
func (g *HTTPGetter) SetUserAgent(userAgent string) {
g.opts.userAgent = userAgent
}
//Get performs a Get from repo.Getter and returns the body. //Get performs a Get from repo.Getter and returns the body.
func (g *HTTPGetter) Get(href string) (*bytes.Buffer, error) { func (g *HTTPGetter) Get(href string) (*bytes.Buffer, error) {
return g.get(href) return g.get(href)
@ -79,13 +68,8 @@ func (g *HTTPGetter) get(href string) (*bytes.Buffer, error) {
return buf, err return buf, err
} }
// newHTTPGetter constructs a valid http/https client as Getter // NewHTTPGetter constructs a valid http/https client as a Getter
func newHTTPGetter(options ...Option) (Getter, error) { func NewHTTPGetter(options ...Option) (Getter, error) {
return NewHTTPGetter(options...)
}
// NewHTTPGetter constructs a valid http/https client as HTTPGetter
func NewHTTPGetter(options ...Option) (*HTTPGetter, error) {
var client HTTPGetter var client HTTPGetter
for _, opt := range options { for _, opt := range options {

@ -16,30 +16,34 @@ limitations under the License.
package getter package getter
import ( import (
"fmt"
"net/http" "net/http"
"net/http/httptest"
"net/url"
"path/filepath" "path/filepath"
"testing" "testing"
"helm.sh/helm/internal/test" "helm.sh/helm/internal/test"
"helm.sh/helm/pkg/cli"
) )
func TestHTTPGetter(t *testing.T) { func TestHTTPGetter(t *testing.T) {
g, err := newHTTPGetter(WithURL("http://example.com")) g, err := NewHTTPGetter(WithURL("http://example.com"))
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if hg, ok := g.(*HTTPGetter); !ok { if hg, ok := g.(*HTTPGetter); !ok {
t.Fatal("Expected newHTTPGetter to produce an httpGetter") t.Fatal("Expected NewHTTPGetter to produce an *HTTPGetter")
} else if hg.client != http.DefaultClient { } else if hg.client != http.DefaultClient {
t.Fatal("Expected newHTTPGetter to return a default HTTP client.") t.Fatal("Expected NewHTTPGetter to return a default HTTP client.")
} }
// Test with SSL: // Test with SSL:
cd := "../../testdata" cd := "../../testdata"
join := filepath.Join join := filepath.Join
ca, pub, priv := join(cd, "ca.pem"), join(cd, "crt.pem"), join(cd, "key.pem") ca, pub, priv := join(cd, "ca.pem"), join(cd, "crt.pem"), join(cd, "key.pem")
g, err = newHTTPGetter( g, err = NewHTTPGetter(
WithURL("http://example.com"), WithURL("http://example.com"),
WithTLSClientConfig(pub, priv, ca), WithTLSClientConfig(pub, priv, ca),
) )
@ -49,18 +53,18 @@ func TestHTTPGetter(t *testing.T) {
hg, ok := g.(*HTTPGetter) hg, ok := g.(*HTTPGetter)
if !ok { if !ok {
t.Fatal("Expected newHTTPGetter to produce an httpGetter") t.Fatal("Expected NewHTTPGetter to produce an *HTTPGetter")
} }
transport, ok := hg.client.Transport.(*http.Transport) transport, ok := hg.client.Transport.(*http.Transport)
if !ok { if !ok {
t.Errorf("Expected newHTTPGetter to set up an HTTP transport") t.Errorf("Expected NewHTTPGetter to set up an HTTP transport")
} }
test.AssertGoldenString(t, transport.TLSClientConfig.ServerName, "output/httpgetter-servername.txt") test.AssertGoldenString(t, transport.TLSClientConfig.ServerName, "output/httpgetter-servername.txt")
// Test other options // Test other options
hg, err = NewHTTPGetter( g, err = NewHTTPGetter(
WithBasicAuth("I", "Am"), WithBasicAuth("I", "Am"),
WithUserAgent("Groot"), WithUserAgent("Groot"),
) )
@ -68,6 +72,11 @@ func TestHTTPGetter(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
hg, ok = g.(*HTTPGetter)
if !ok {
t.Fatal("expected NewHTTPGetter to produce an *HTTPGetter")
}
if hg.opts.username != "I" { if hg.opts.username != "I" {
t.Errorf("Expected NewHTTPGetter to contain %q as the username, got %q", "I", hg.opts.username) t.Errorf("Expected NewHTTPGetter to contain %q as the username, got %q", "I", hg.opts.username)
} }
@ -80,3 +89,57 @@ func TestHTTPGetter(t *testing.T) {
t.Errorf("Expected NewHTTPGetter to contain %q as the user agent, got %q", "Groot", hg.opts.userAgent) t.Errorf("Expected NewHTTPGetter to contain %q as the user agent, got %q", "Groot", hg.opts.userAgent)
} }
} }
func TestDownload(t *testing.T) {
expect := "Call me Ishmael"
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, expect)
}))
defer srv.Close()
provider, err := ByScheme("http", cli.EnvSettings{})
if err != nil {
t.Fatal("No http provider found")
}
g, err := provider.New(WithURL(srv.URL))
if err != nil {
t.Fatal(err)
}
got, err := g.Get(srv.URL)
if err != nil {
t.Fatal(err)
}
if got.String() != expect {
t.Errorf("Expected %q, got %q", expect, got.String())
}
// test with server backed by basic auth
basicAuthSrv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
username, password, ok := r.BasicAuth()
if !ok || username != "username" || password != "password" {
t.Errorf("Expected request to use basic auth and for username == 'username' and password == 'password', got '%v', '%s', '%s'", ok, username, password)
}
fmt.Fprint(w, expect)
}))
defer basicAuthSrv.Close()
u, _ := url.ParseRequestURI(basicAuthSrv.URL)
httpgetter, err := NewHTTPGetter(
WithURL(u.String()),
WithBasicAuth("username", "password"),
)
if err != nil {
t.Fatal(err)
}
got, err = httpgetter.Get(u.String())
if err != nil {
t.Fatal(err)
}
if got.String() != expect {
t.Errorf("Expected %q, got %q", expect, got.String())
}
}

@ -40,7 +40,7 @@ func collectPlugins(settings cli.EnvSettings) (Providers, error) {
for _, downloader := range plugin.Metadata.Downloaders { for _, downloader := range plugin.Metadata.Downloaders {
result = append(result, Provider{ result = append(result, Provider{
Schemes: downloader.Protocols, Schemes: downloader.Protocols,
New: newPluginGetter( New: NewPluginGetter(
downloader.Command, downloader.Command,
settings, settings,
plugin.Metadata.Name, plugin.Metadata.Name,
@ -82,8 +82,8 @@ func (p *pluginGetter) Get(href string) (*bytes.Buffer, error) {
return buf, nil return buf, nil
} }
// newPluginGetter constructs a valid plugin getter // NewPluginGetter constructs a valid plugin getter
func newPluginGetter(command string, settings cli.EnvSettings, name, base string) Constructor { func NewPluginGetter(command string, settings cli.EnvSettings, name, base string) Constructor {
return func(options ...Option) (Getter, error) { return func(options ...Option) (Getter, error) {
result := &pluginGetter{ result := &pluginGetter{
command: command, command: command,

@ -77,7 +77,7 @@ func TestPluginGetter(t *testing.T) {
os.Setenv("HELM_HOME", "") os.Setenv("HELM_HOME", "")
env := hh(false) env := hh(false)
pg := newPluginGetter("echo", env, "test", ".") pg := NewPluginGetter("echo", env, "test", ".")
g, err := pg() g, err := pg()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
@ -105,7 +105,7 @@ func TestPluginSubCommands(t *testing.T) {
os.Setenv("HELM_HOME", "") os.Setenv("HELM_HOME", "")
env := hh(false) env := hh(false)
pg := newPluginGetter("echo -n", env, "test", ".") pg := NewPluginGetter("echo -n", env, "test", ".")
g, err := pg() g, err := pg()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)

@ -69,7 +69,7 @@ func NewServer(docroot string) *Server {
srv := &Server{ srv := &Server{
docroot: root, docroot: root,
} }
srv.start() srv.Start()
// Add the testing repository as the only repo. // Add the testing repository as the only repo.
if err := setTestingRepository(helmpath.Home(docroot), "test", srv.URL()); err != nil { if err := setTestingRepository(helmpath.Home(docroot), "test", srv.URL()); err != nil {
panic(err) panic(err)
@ -79,8 +79,15 @@ func NewServer(docroot string) *Server {
// Server is an implementation of a repository server for testing. // Server is an implementation of a repository server for testing.
type Server struct { type Server struct {
docroot string docroot string
srv *httptest.Server srv *httptest.Server
middleware http.HandlerFunc
}
// WithMiddleware injects middleware in front of the server. This can be used to inject
// additional functionality like layering in an authentication frontend.
func (s *Server) WithMiddleware(middleware http.HandlerFunc) {
s.middleware = middleware
} }
// Root gets the docroot for the server. // Root gets the docroot for the server.
@ -129,8 +136,13 @@ func (s *Server) CreateIndex() error {
return ioutil.WriteFile(ifile, d, 0755) return ioutil.WriteFile(ifile, d, 0755)
} }
func (s *Server) start() { func (s *Server) Start() {
s.srv = httptest.NewServer(http.FileServer(http.Dir(s.docroot))) s.srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if s.middleware != nil {
s.middleware.ServeHTTP(w, r)
}
http.FileServer(http.Dir(s.docroot)).ServeHTTP(w, r)
}))
} }
// Stop stops the server and closes all connections. // Stop stops the server and closes all connections.

Loading…
Cancel
Save