From 89ab7555dbf1e1f2817aeb1b4f65ca7a52aaf86d Mon Sep 17 00:00:00 2001 From: Anton Galitsyn Date: Tue, 27 Dec 2016 23:47:27 +0700 Subject: [PATCH] Get http.Client from referenced repository --- cmd/helm/downloader/chart_downloader.go | 118 +++++++++++------- cmd/helm/downloader/chart_downloader_test.go | 68 +++++++--- cmd/helm/downloader/manager.go | 8 +- .../cache/testing-basicauth-index.yaml | 15 +++ .../repository/cache/testing-https-index.yaml | 15 +++ .../repository/cache/testing-index.yaml | 13 ++ .../helmhome/repository/repositories.yaml | 4 + cmd/helm/helm_test.go | 2 +- cmd/helm/init.go | 4 +- cmd/helm/repo_add.go | 2 +- cmd/helm/repo_add_test.go | 2 +- cmd/helm/repo_list.go | 2 +- cmd/helm/repo_remove.go | 2 +- cmd/helm/repo_remove_test.go | 2 +- cmd/helm/repo_update.go | 2 +- cmd/helm/search.go | 2 +- pkg/repo/chartrepo.go | 8 ++ pkg/repo/repo.go | 4 +- pkg/repo/repo_test.go | 4 +- pkg/urlutil/urlutil.go | 15 +++ 20 files changed, 215 insertions(+), 77 deletions(-) create mode 100644 cmd/helm/downloader/testdata/helmhome/repository/cache/testing-basicauth-index.yaml create mode 100644 cmd/helm/downloader/testdata/helmhome/repository/cache/testing-https-index.yaml diff --git a/cmd/helm/downloader/chart_downloader.go b/cmd/helm/downloader/chart_downloader.go index bb64ff7fc..57e79e9c8 100644 --- a/cmd/helm/downloader/chart_downloader.go +++ b/cmd/helm/downloader/chart_downloader.go @@ -76,12 +76,12 @@ type ChartDownloader struct { // 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. func (c *ChartDownloader) DownloadTo(ref, version, dest string) (string, *provenance.Verification, error) { - // resolve URL - u, err := c.ResolveChartVersion(ref, version) + u, client, err := c.ResolveChartVersion(ref, version) if err != nil { return "", nil, err } - data, err := download(u.String()) + + data, err := download(u.String(), client) if err != nil { return "", nil, err } @@ -95,8 +95,7 @@ func (c *ChartDownloader) DownloadTo(ref, version, dest string) (string, *proven // If provenance is requested, verify it. ver := &provenance.Verification{} if c.Verify > VerifyNever { - - body, err := download(u.String() + ".prov") + body, err := download(u.String()+".prov", client) if err != nil { if c.Verify == VerifyAlways { return destfile, ver, fmt.Errorf("Failed to fetch provenance %q", u.String()+".prov") @@ -132,63 +131,75 @@ 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 empty, this will return the URL for the latest version // * If no version can be found, an error is returned -func (c *ChartDownloader) ResolveChartVersion(ref, version string) (*url.URL, error) { - // See if it's already a full URL. - // FIXME: Why do we use url.ParseRequestURI instead of url.Parse? - u, err := url.ParseRequestURI(ref) - if err == nil { - // If it has a scheme and host and path, it's a full URL - if u.IsAbs() && len(u.Host) > 0 && len(u.Path) > 0 { - return u, nil - } - return u, fmt.Errorf("invalid chart url format: %s", ref) +func (c *ChartDownloader) ResolveChartVersion(ref, version string) (*url.URL, *http.Client, error) { + u, err := url.Parse(ref) + if err != nil { + return nil, nil, fmt.Errorf("invalid chart URL format: %s", ref) } - r, err := repo.LoadRepositoriesFile(c.HelmHome.RepositoryFile()) + rf, err := repo.LoadRepositoryFile(c.HelmHome.RepositoryFile()) if err != nil { - return u, err + return nil, nil, err } - // See if it's of the form: repo/path_to_chart - p := strings.SplitN(ref, "/", 2) - if len(p) < 2 { - return u, fmt.Errorf("invalid chart url format: %s", ref) + var ( + chartName string + rc *repo.ChartRepositoryConfig + ) + if u.IsAbs() && len(u.Host) > 0 && len(u.Path) > 0 { + // If it has a scheme and host and path, it's a full URL + p := strings.SplitN(strings.TrimLeft(u.Path, "/"), "-", 2) + if len(p) < 2 { + return nil, nil, fmt.Errorf("Seems that chart path is not in form of repo_url/path_to_chart, got: %s", u) + } + chartName = p[0] + u.Path = "" + rc, err = pickChartRepositoryConfigByURL(u.String(), rf.Repositories) + if err != nil { + return nil, nil, err + } + } else { + // See if it's of the form: repo/path_to_chart + p := strings.SplitN(u.Path, "/", 2) + if len(p) < 2 { + return nil, nil, fmt.Errorf("Non-absolute URLs should be in form of repo_name/path_to_chart, got: %s", u) + } + + repoName := p[0] + chartName = p[1] + rc, err = pickChartRepositoryConfigByName(repoName, rf.Repositories) + if err != nil { + return nil, nil, err + } } - repoName := p[0] - chartName := p[1] - rf, err := findRepoEntry(repoName, r.Repositories) + r, err := repo.NewChartRepository(rc) if err != nil { - return u, err - } - if rf.URL == "" { - return u, fmt.Errorf("no URL found for repository %q", repoName) + return nil, nil, err } // Next, we need to load the index, and actually look up the chart. - i, err := repo.NewChartRepositoryIndexFromFile(c.HelmHome.CacheIndex(repoName)) + i, err := repo.NewChartRepositoryIndexFromFile(c.HelmHome.CacheIndex(r.Config.Name)) if err != nil { - return u, fmt.Errorf("no cached repo found. (try 'helm repo update'). %s", err) + return nil, nil, fmt.Errorf("no cached repo found. (try 'helm repo update'). %s", err) } cv, err := i.Get(chartName, version) if err != nil { - return u, fmt.Errorf("chart %q not found in %s index. (try 'helm repo update'). %s", chartName, repoName, err) + return nil, nil, fmt.Errorf("chart %q not found in %s index. (try 'helm repo update'). %s", chartName, r.Config.Name, err) } if len(cv.URLs) == 0 { - return u, fmt.Errorf("chart %q has no downloadable URLs", ref) + return nil, nil, fmt.Errorf("chart %q has no downloadable URLs", ref) } - return url.Parse(cv.URLs[0]) -} -func findRepoEntry(name string, repos []*repo.ChartRepositoryConfig) (*repo.ChartRepositoryConfig, error) { - for _, re := range repos { - if re.Name == name { - return re, nil - } + // TODO: Seems that picking first URL is not fully correct + u, err = url.Parse(cv.URLs[0]) + if err != nil { + return nil, nil, fmt.Errorf("invalid chart URL format: %s", ref) } - return nil, fmt.Errorf("no repo named %q", name) + + return u, r.Client, nil } // VerifyChart takes a path to a chart archive and a keyring, and verifies the chart. @@ -217,11 +228,11 @@ func VerifyChart(path string, keyring string) (*provenance.Verification, error) return sig.Verify(path, provfile) } -// download performs a simple HTTP Get and returns the body. -func download(href string) (*bytes.Buffer, error) { +// download performs a HTTP Get using specified client and returns the body. +func download(href string, client *http.Client) (*bytes.Buffer, error) { buf := bytes.NewBuffer(nil) - resp, err := http.Get(href) + resp, err := client.Get(href) if err != nil { return buf, err } @@ -241,3 +252,24 @@ func download(href string) (*bytes.Buffer, error) { func isTar(filename string) bool { return strings.ToLower(filepath.Ext(filename)) == ".tgz" } + +func pickChartRepositoryConfigByName(name string, cfgs []*repo.ChartRepositoryConfig) (*repo.ChartRepositoryConfig, error) { + for _, rc := range cfgs { + if rc.Name == name { + if rc.URL == "" { + return nil, fmt.Errorf("no URL found for repository %s", name) + } + return rc, nil + } + } + return nil, fmt.Errorf("repo %s not found", name) +} + +func pickChartRepositoryConfigByURL(u string, cfgs []*repo.ChartRepositoryConfig) (*repo.ChartRepositoryConfig, error) { + for _, rc := range cfgs { + if rc.URL == u { + return rc, nil + } + } + return nil, fmt.Errorf("repo with URL %s not found", u) +} diff --git a/cmd/helm/downloader/chart_downloader_test.go b/cmd/helm/downloader/chart_downloader_test.go index c3d06f1d6..7a7fbe76f 100644 --- a/cmd/helm/downloader/chart_downloader_test.go +++ b/cmd/helm/downloader/chart_downloader_test.go @@ -37,9 +37,9 @@ func TestResolveChartRef(t *testing.T) { {name: "full URL", ref: "http://example.com/foo-1.2.3.tgz", expect: "http://example.com/foo-1.2.3.tgz"}, {name: "full URL, HTTPS", ref: "https://example.com/foo-1.2.3.tgz", expect: "https://example.com/foo-1.2.3.tgz"}, {name: "full URL, with authentication", ref: "http://username:password@example.com/foo-1.2.3.tgz", expect: "http://username:password@example.com/foo-1.2.3.tgz"}, - {name: "full URL, HTTPS, irrelevant version", ref: "https://example.com/foo-1.2.3.tgz", version: "0.1.0", expect: "https://example.com/foo-1.2.3.tgz"}, {name: "reference, testing repo", ref: "testing/alpine", expect: "http://example.com/alpine-1.2.3.tgz"}, {name: "reference, version, testing repo", ref: "testing/alpine", version: "0.2.0", expect: "http://example.com/alpine-0.2.0.tgz"}, + {name: "full URL, HTTPS, irrelevant version", ref: "https://example.com/foo-1.2.3.tgz", version: "0.1.0", expect: "https://example.com/foo-1.2.3.tgz", fail: true}, {name: "full URL, file", ref: "file:///foo-1.2.3.tgz", fail: true}, {name: "invalid", ref: "invalid-1.2.3", fail: true}, {name: "not found", ref: "nosuchthing/invalid-1.2.3", fail: true}, @@ -51,7 +51,7 @@ func TestResolveChartRef(t *testing.T) { } for _, tt := range tests { - u, err := c.ResolveChartVersion(tt.ref, tt.version) + u, _, err := c.ResolveChartVersion(tt.ref, tt.version) if err != nil { if tt.fail { continue @@ -84,7 +84,7 @@ func TestDownload(t *testing.T) { })) defer srv.Close() - got, err := download(srv.URL) + got, err := download(srv.URL, http.DefaultClient) if err != nil { t.Fatal(err) } @@ -105,7 +105,7 @@ func TestDownload(t *testing.T) { u, _ := url.ParseRequestURI(basicAuthSrv.URL) u.User = url.UserPassword("username", "password") - got, err = download(u.String()) + got, err = download(u.String(), http.DefaultClient) if err != nil { t.Fatal(err) } @@ -133,25 +133,43 @@ func TestIsTar(t *testing.T) { } func TestDownloadTo(t *testing.T) { - hh, err := ioutil.TempDir("", "helm-downloadto-") + tmp, err := ioutil.TempDir("", "helm-downloadto-") if err != nil { t.Fatal(err) } - defer os.RemoveAll(hh) + defer os.RemoveAll(tmp) - dest := filepath.Join(hh, "dest") - os.MkdirAll(dest, 0755) + hh := helmpath.Home(tmp) + dest := filepath.Join(hh.String(), "dest") + configDirectories := []string{ + hh.String(), + hh.Repository(), + hh.Cache(), + dest, + } + for _, p := range configDirectories { + if fi, err := os.Stat(p); err != nil { + if err := os.MkdirAll(p, 0755); err != nil { + t.Fatalf("Could not create %s: %s", p, err) + } + } else if !fi.IsDir() { + t.Fatalf("%s must be a directory", p) + } + } // Set up a fake repo - srv := repotest.NewServer(hh) + srv := repotest.NewServer(tmp) defer srv.Stop() if _, err := srv.CopyCharts("testdata/*.tgz*"); err != nil { t.Error(err) return } + if err := srv.LinkIndices(); err != nil { + t.Fatal(err) + } c := ChartDownloader{ - HelmHome: helmpath.Home("testdata/helmhome"), + HelmHome: hh, Out: os.Stderr, Verify: VerifyAlways, Keyring: "testdata/helm-test-key.pub", @@ -178,25 +196,43 @@ func TestDownloadTo(t *testing.T) { } func TestDownloadTo_VerifyLater(t *testing.T) { - hh, err := ioutil.TempDir("", "helm-downloadto-") + tmp, err := ioutil.TempDir("", "helm-downloadto-") if err != nil { t.Fatal(err) } - defer os.RemoveAll(hh) + defer os.RemoveAll(tmp) - dest := filepath.Join(hh, "dest") - os.MkdirAll(dest, 0755) + hh := helmpath.Home(tmp) + dest := filepath.Join(hh.String(), "dest") + configDirectories := []string{ + hh.String(), + hh.Repository(), + hh.Cache(), + dest, + } + for _, p := range configDirectories { + if fi, err := os.Stat(p); err != nil { + if err := os.MkdirAll(p, 0755); err != nil { + t.Fatalf("Could not create %s: %s", p, err) + } + } else if !fi.IsDir() { + t.Fatalf("%s must be a directory", p) + } + } // Set up a fake repo - srv := repotest.NewServer(hh) + srv := repotest.NewServer(tmp) defer srv.Stop() if _, err := srv.CopyCharts("testdata/*.tgz*"); err != nil { t.Error(err) return } + if err := srv.LinkIndices(); err != nil { + t.Fatal(err) + } c := ChartDownloader{ - HelmHome: helmpath.Home("testdata/helmhome"), + HelmHome: hh, Out: os.Stderr, Verify: VerifyLater, } diff --git a/cmd/helm/downloader/manager.go b/cmd/helm/downloader/manager.go index a64ed3bf3..daa65ef97 100644 --- a/cmd/helm/downloader/manager.go +++ b/cmd/helm/downloader/manager.go @@ -213,7 +213,7 @@ func (m *Manager) downloadAll(deps []*chartutil.Dependency) error { // hasAllRepos ensures that all of the referenced deps are in the local repo cache. func (m *Manager) hasAllRepos(deps []*chartutil.Dependency) error { - rf, err := repo.LoadRepositoriesFile(m.HelmHome.RepositoryFile()) + rf, err := repo.LoadRepositoryFile(m.HelmHome.RepositoryFile()) if err != nil { return err } @@ -244,7 +244,7 @@ func (m *Manager) hasAllRepos(deps []*chartutil.Dependency) error { // getRepoNames returns the repo names of the referenced deps which can be used to fetch the cahced index file. func (m *Manager) getRepoNames(deps []*chartutil.Dependency) (map[string]string, error) { - rf, err := repo.LoadRepositoriesFile(m.HelmHome.RepositoryFile()) + rf, err := repo.LoadRepositoryFile(m.HelmHome.RepositoryFile()) if err != nil { return nil, err } @@ -277,7 +277,7 @@ func (m *Manager) getRepoNames(deps []*chartutil.Dependency) (map[string]string, // UpdateRepositories updates all of the local repos to the latest. func (m *Manager) UpdateRepositories() error { - rf, err := repo.LoadRepositoriesFile(m.HelmHome.RepositoryFile()) + rf, err := repo.LoadRepositoryFile(m.HelmHome.RepositoryFile()) if err != nil { return err } @@ -409,7 +409,7 @@ func (m *Manager) loadChartRepositories() (map[string]*repo.ChartRepository, err repoyaml := m.HelmHome.RepositoryFile() // Load repositories.yaml file - rf, err := repo.LoadRepositoriesFile(repoyaml) + rf, err := repo.LoadRepositoryFile(repoyaml) if err != nil { return indices, fmt.Errorf("failed to load %s: %s", repoyaml, err) } diff --git a/cmd/helm/downloader/testdata/helmhome/repository/cache/testing-basicauth-index.yaml b/cmd/helm/downloader/testdata/helmhome/repository/cache/testing-basicauth-index.yaml new file mode 100644 index 000000000..47bb1b77c --- /dev/null +++ b/cmd/helm/downloader/testdata/helmhome/repository/cache/testing-basicauth-index.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +entries: + foo: + - name: foo + description: Foo Chart + engine: gotpl + home: https://k8s.io/helm + keywords: [] + maintainers: [] + sources: + - https://github.com/kubernetes/charts + urls: + - http://username:password@example.com/foo-1.2.3.tgz + version: 1.2.3 + checksum: 0e6661f193211d7a5206918d42f5c2a9470b737d diff --git a/cmd/helm/downloader/testdata/helmhome/repository/cache/testing-https-index.yaml b/cmd/helm/downloader/testdata/helmhome/repository/cache/testing-https-index.yaml new file mode 100644 index 000000000..872478c3f --- /dev/null +++ b/cmd/helm/downloader/testdata/helmhome/repository/cache/testing-https-index.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +entries: + foo: + - name: foo + description: Foo Chart + engine: gotpl + home: https://k8s.io/helm + keywords: [] + maintainers: [] + sources: + - https://github.com/kubernetes/charts + urls: + - https://example.com/foo-1.2.3.tgz + version: 1.2.3 + checksum: 0e6661f193211d7a5206918d42f5c2a9470b737d diff --git a/cmd/helm/downloader/testdata/helmhome/repository/cache/testing-index.yaml b/cmd/helm/downloader/testdata/helmhome/repository/cache/testing-index.yaml index cec18b069..14cdffece 100644 --- a/cmd/helm/downloader/testdata/helmhome/repository/cache/testing-index.yaml +++ b/cmd/helm/downloader/testdata/helmhome/repository/cache/testing-index.yaml @@ -28,3 +28,16 @@ entries: maintainers: [] engine: "" icon: "" + foo: + - name: foo + description: Foo Chart + engine: gotpl + home: https://k8s.io/helm + keywords: [] + maintainers: [] + sources: + - https://github.com/kubernetes/charts + urls: + - http://example.com/foo-1.2.3.tgz + version: 1.2.3 + checksum: 0e6661f193211d7a5206918d42f5c2a9470b737d diff --git a/cmd/helm/downloader/testdata/helmhome/repository/repositories.yaml b/cmd/helm/downloader/testdata/helmhome/repository/repositories.yaml index c7ddf316a..200f370bd 100644 --- a/cmd/helm/downloader/testdata/helmhome/repository/repositories.yaml +++ b/cmd/helm/downloader/testdata/helmhome/repository/repositories.yaml @@ -2,5 +2,9 @@ apiVersion: v1 repositories: - name: testing url: "http://example.com" + - name: testing-https + url: "https://example.com" + - name: testing-basicauth + url: "http://username:password@example.com" - name: kubernetes-charts url: "http://example.com/charts" diff --git a/cmd/helm/helm_test.go b/cmd/helm/helm_test.go index 83a086875..7dfc34dae 100644 --- a/cmd/helm/helm_test.go +++ b/cmd/helm/helm_test.go @@ -270,7 +270,7 @@ func ensureTestHome(home helmpath.Home, t *testing.T) error { } else if fi.IsDir() { return fmt.Errorf("%s must be a file, not a directory", repoFile) } - if r, err := repo.LoadRepositoriesFile(repoFile); err == repo.ErrRepoOutOfDate { + if r, err := repo.LoadRepositoryFile(repoFile); err == repo.ErrRepoOutOfDate { t.Log("Updating repository file format...") if err := r.WriteFile(repoFile, 0644); err != nil { return err diff --git a/cmd/helm/init.go b/cmd/helm/init.go index b46c32550..43a0ece81 100644 --- a/cmd/helm/init.go +++ b/cmd/helm/init.go @@ -55,7 +55,7 @@ To dump a manifest containing the Tiller deployment YAML, combine the const ( stableRepository = "stable" localRepository = "local" - stableRepositoryURL = "https://kubernetes-charts.storage.googleapis.com/" + stableRepositoryURL = "https://kubernetes-charts.storage.googleapis.com" // This is the IPv4 loopback, not localhost, because we have to force IPv4 // for Dockerized Helm: https://github.com/kubernetes/helm/issues/1410 localRepositoryURL = "http://127.0.0.1:8879/charts" @@ -236,7 +236,7 @@ func initLocalRepo(indexFile, cacheFile string) (*repo.ChartRepositoryConfig, er } func ensureRepoFileFormat(file string, out io.Writer) error { - r, err := repo.LoadRepositoriesFile(file) + r, err := repo.LoadRepositoryFile(file) if err == repo.ErrRepoOutOfDate { fmt.Fprintln(out, "Updating repository file format...") if err := r.WriteFile(file, 0644); err != nil { diff --git a/cmd/helm/repo_add.go b/cmd/helm/repo_add.go index 0abaa9740..2d9a62d1e 100644 --- a/cmd/helm/repo_add.go +++ b/cmd/helm/repo_add.go @@ -78,7 +78,7 @@ func (a *repoAddCmd) run() error { } func addRepository(name, url string, home helmpath.Home, certFile, keyFile, caFile string, noUpdate bool) error { - f, err := repo.LoadRepositoriesFile(home.RepositoryFile()) + f, err := repo.LoadRepositoryFile(home.RepositoryFile()) if err != nil { return err } diff --git a/cmd/helm/repo_add_test.go b/cmd/helm/repo_add_test.go index 7c5342177..b823777f7 100644 --- a/cmd/helm/repo_add_test.go +++ b/cmd/helm/repo_add_test.go @@ -84,7 +84,7 @@ func TestRepoAdd(t *testing.T) { t.Error(err) } - f, err := repo.LoadRepositoriesFile(hh.RepositoryFile()) + f, err := repo.LoadRepositoryFile(hh.RepositoryFile()) if err != nil { t.Error(err) } diff --git a/cmd/helm/repo_list.go b/cmd/helm/repo_list.go index a3816facd..a4f7edec5 100644 --- a/cmd/helm/repo_list.go +++ b/cmd/helm/repo_list.go @@ -51,7 +51,7 @@ func newRepoListCmd(out io.Writer) *cobra.Command { } func (a *repoListCmd) run() error { - f, err := repo.LoadRepositoriesFile(a.home.RepositoryFile()) + f, err := repo.LoadRepositoryFile(a.home.RepositoryFile()) if err != nil { return err } diff --git a/cmd/helm/repo_remove.go b/cmd/helm/repo_remove.go index f7671cab0..ad2a9c188 100644 --- a/cmd/helm/repo_remove.go +++ b/cmd/helm/repo_remove.go @@ -62,7 +62,7 @@ func (r *repoRemoveCmd) run() error { func removeRepoLine(out io.Writer, name string, home helmpath.Home) error { repoFile := home.RepositoryFile() - r, err := repo.LoadRepositoriesFile(repoFile) + r, err := repo.LoadRepositoryFile(repoFile) if err != nil { return err } diff --git a/cmd/helm/repo_remove_test.go b/cmd/helm/repo_remove_test.go index 12f534972..1e0a4c382 100644 --- a/cmd/helm/repo_remove_test.go +++ b/cmd/helm/repo_remove_test.go @@ -69,7 +69,7 @@ func TestRepoRemove(t *testing.T) { t.Errorf("Error cache file was not removed for repository %s", testName) } - f, err := repo.LoadRepositoriesFile(hh.RepositoryFile()) + f, err := repo.LoadRepositoryFile(hh.RepositoryFile()) if err != nil { t.Error(err) } diff --git a/cmd/helm/repo_update.go b/cmd/helm/repo_update.go index 8dfab9a5d..c08d840fb 100644 --- a/cmd/helm/repo_update.go +++ b/cmd/helm/repo_update.go @@ -65,7 +65,7 @@ func newRepoUpdateCmd(out io.Writer) *cobra.Command { } func (u *repoUpdateCmd) run() error { - f, err := repo.LoadRepositoriesFile(u.home.RepositoryFile()) + f, err := repo.LoadRepositoryFile(u.home.RepositoryFile()) if err != nil { return err } diff --git a/cmd/helm/search.go b/cmd/helm/search.go index 62d13e3b3..4804f6b92 100644 --- a/cmd/helm/search.go +++ b/cmd/helm/search.go @@ -110,7 +110,7 @@ func (s *searchCmd) formatSearchResults(res []*search.Result) string { func (s *searchCmd) buildIndex() (*search.Index, error) { // Load the repositories.yaml - rf, err := repo.LoadRepositoriesFile(s.helmhome.RepositoryFile()) + rf, err := repo.LoadRepositoryFile(s.helmhome.RepositoryFile()) if err != nil { return nil, err } diff --git a/pkg/repo/chartrepo.go b/pkg/repo/chartrepo.go index c83592678..523e5e1e4 100644 --- a/pkg/repo/chartrepo.go +++ b/pkg/repo/chartrepo.go @@ -29,6 +29,7 @@ import ( "k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/provenance" "k8s.io/helm/pkg/tlsutil" + "k8s.io/helm/pkg/urlutil" ) // ChartRepositoryConfig represents a collection of parameters for chart repository @@ -58,6 +59,13 @@ func NewChartRepository(cfg *ChartRepositoryConfig) (*ChartRepository, error) { return nil, fmt.Errorf("can't create TLS config for client: %s", err.Error()) } tlsConf.BuildNameToCertificate() + + sni, err := urlutil.ExtractHostname(cfg.URL) + if err != nil { + return nil, err + } + tlsConf.ServerName = sni + client = &http.Client{ Transport: &http.Transport{ TLSClientConfig: tlsConf, diff --git a/pkg/repo/repo.go b/pkg/repo/repo.go index 7d4a91387..bfc7d4c1d 100644 --- a/pkg/repo/repo.go +++ b/pkg/repo/repo.go @@ -48,11 +48,11 @@ func NewRepositoryFile() *RepositoryFile { } } -// LoadRepositoriesFile takes a file at the given path and returns a RepositoryFile object +// LoadRepositoryFile takes a file at the given path and returns a RepositoryFile object // // If this returns ErrRepoOutOfDate, it also returns a recovered RepositoryFile that // can be saved as a replacement to the out of date file. -func LoadRepositoriesFile(path string) (*RepositoryFile, error) { +func LoadRepositoryFile(path string) (*RepositoryFile, error) { b, err := ioutil.ReadFile(path) if err != nil { return nil, err diff --git a/pkg/repo/repo_test.go b/pkg/repo/repo_test.go index 6ee733fcc..451e035aa 100644 --- a/pkg/repo/repo_test.go +++ b/pkg/repo/repo_test.go @@ -73,7 +73,7 @@ func TestNewRepositoriesFile(t *testing.T) { }, ) - repofile, err := LoadRepositoriesFile(testRepositoriesFile) + repofile, err := LoadRepositoryFile(testRepositoriesFile) if err != nil { t.Errorf("%q could not be loaded: %s", testRepositoriesFile, err) } @@ -97,7 +97,7 @@ func TestNewRepositoriesFile(t *testing.T) { } func TestNewPreV1RepositoriesFile(t *testing.T) { - r, err := LoadRepositoriesFile("testdata/old-repositories.yaml") + r, err := LoadRepositoryFile("testdata/old-repositories.yaml") if err != nil && err != ErrRepoOutOfDate { t.Fatal(err) } diff --git a/pkg/urlutil/urlutil.go b/pkg/urlutil/urlutil.go index 8026fd245..f99294938 100644 --- a/pkg/urlutil/urlutil.go +++ b/pkg/urlutil/urlutil.go @@ -17,6 +17,7 @@ limitations under the License. package urlutil import ( + "net" "net/url" "path" "path/filepath" @@ -64,3 +65,17 @@ func URLAreEqual(a, b string) bool { } return au.String() == bu.String() } + +// ExtractHostname returns hostname from URL +func ExtractHostname(addr string) (string, error) { + u, err := url.Parse(addr) + if err != nil { + return "", err + } + + host, _, err := net.SplitHostPort(u.Host) + if err != nil { + return "", err + } + return host, nil +}