Merge pull request #2352 from technosophos/ref/getter

ref(getter): flatten the getter package tree
pull/2370/head
Matt Butcher 8 years ago committed by GitHub
commit e66cdcd1f3

@ -21,7 +21,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/pkg/downloader" "k8s.io/helm/pkg/downloader"
"k8s.io/helm/pkg/getter/defaultgetters" "k8s.io/helm/pkg/getter"
"k8s.io/helm/pkg/helm/helmpath" "k8s.io/helm/pkg/helm/helmpath"
) )
@ -77,7 +77,7 @@ func (d *dependencyBuildCmd) run() error {
ChartPath: d.chartpath, ChartPath: d.chartpath,
HelmHome: d.helmhome, HelmHome: d.helmhome,
Keyring: d.keyring, Keyring: d.keyring,
Getters: defaultgetters.Get(settings), Getters: getter.All(settings),
} }
if d.verify { if d.verify {
man.Verify = downloader.VerifyIfPossible man.Verify = downloader.VerifyIfPossible

@ -21,7 +21,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/pkg/downloader" "k8s.io/helm/pkg/downloader"
"k8s.io/helm/pkg/getter/defaultgetters" "k8s.io/helm/pkg/getter"
"k8s.io/helm/pkg/helm/helmpath" "k8s.io/helm/pkg/helm/helmpath"
) )
@ -95,7 +95,7 @@ func (d *dependencyUpdateCmd) run() error {
HelmHome: d.helmhome, HelmHome: d.helmhome,
Keyring: d.keyring, Keyring: d.keyring,
SkipUpdate: d.skipRefresh, SkipUpdate: d.skipRefresh,
Getters: defaultgetters.Get(settings), Getters: getter.All(settings),
} }
if d.verify { if d.verify {
man.Verify = downloader.VerifyIfPossible man.Verify = downloader.VerifyIfPossible

@ -26,7 +26,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/downloader" "k8s.io/helm/pkg/downloader"
"k8s.io/helm/pkg/getter/defaultgetters" "k8s.io/helm/pkg/getter"
) )
const fetchDesc = ` const fetchDesc = `
@ -97,7 +97,7 @@ func (f *fetchCmd) run() error {
Out: f.out, Out: f.out,
Keyring: f.keyring, Keyring: f.keyring,
Verify: downloader.VerifyNever, Verify: downloader.VerifyNever,
Getters: defaultgetters.Get(settings), Getters: getter.All(settings),
} }
if f.verify { if f.verify {

@ -27,7 +27,7 @@ import (
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/helm/cmd/helm/installer" "k8s.io/helm/cmd/helm/installer"
"k8s.io/helm/pkg/getter/defaultgetters" "k8s.io/helm/pkg/getter"
"k8s.io/helm/pkg/helm/helmpath" "k8s.io/helm/pkg/helm/helmpath"
"k8s.io/helm/pkg/repo" "k8s.io/helm/pkg/repo"
) )
@ -317,7 +317,7 @@ func initStableRepo(cacheFile string, skipRefresh bool) (*repo.Entry, error) {
URL: stableRepositoryURL, URL: stableRepositoryURL,
Cache: cacheFile, Cache: cacheFile,
} }
r, err := repo.NewChartRepository(&c, defaultgetters.Get(settings)) r, err := repo.NewChartRepository(&c, getter.All(settings))
if err != nil { if err != nil {
return nil, err return nil, err
} }

@ -34,7 +34,7 @@ import (
"k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/downloader" "k8s.io/helm/pkg/downloader"
"k8s.io/helm/pkg/getter/defaultgetters" "k8s.io/helm/pkg/getter"
"k8s.io/helm/pkg/helm" "k8s.io/helm/pkg/helm"
"k8s.io/helm/pkg/kube" "k8s.io/helm/pkg/kube"
"k8s.io/helm/pkg/proto/hapi/chart" "k8s.io/helm/pkg/proto/hapi/chart"
@ -362,7 +362,7 @@ func locateChartPath(name, version string, verify bool, keyring string) (string,
HelmHome: settings.Home, HelmHome: settings.Home,
Out: os.Stdout, Out: os.Stdout,
Keyring: keyring, Keyring: keyring,
Getters: defaultgetters.Get(settings), Getters: getter.All(settings),
} }
if verify { if verify {
dl.Verify = downloader.VerifyAlways dl.Verify = downloader.VerifyAlways

@ -22,7 +22,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/pkg/getter/defaultgetters" "k8s.io/helm/pkg/getter"
"k8s.io/helm/pkg/helm/helmpath" "k8s.io/helm/pkg/helm/helmpath"
"k8s.io/helm/pkg/repo" "k8s.io/helm/pkg/repo"
) )
@ -98,7 +98,7 @@ func addRepository(name, url string, home helmpath.Home, certFile, keyFile, caFi
CAFile: caFile, CAFile: caFile,
} }
r, err := repo.NewChartRepository(&c, defaultgetters.Get(settings)) r, err := repo.NewChartRepository(&c, getter.All(settings))
if err != nil { if err != nil {
return err return err
} }

@ -24,7 +24,7 @@ import (
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/pkg/getter/defaultgetters" "k8s.io/helm/pkg/getter"
"k8s.io/helm/pkg/helm/helmpath" "k8s.io/helm/pkg/helm/helmpath"
"k8s.io/helm/pkg/repo" "k8s.io/helm/pkg/repo"
) )
@ -76,7 +76,7 @@ func (u *repoUpdateCmd) run() error {
} }
var repos []*repo.ChartRepository var repos []*repo.ChartRepository
for _, cfg := range f.Repositories { for _, cfg := range f.Repositories {
r, err := repo.NewChartRepository(cfg, defaultgetters.Get(settings)) r, err := repo.NewChartRepository(cfg, getter.All(settings))
if err != nil { if err != nil {
return err return err
} }

@ -23,7 +23,7 @@ import (
"strings" "strings"
"testing" "testing"
"k8s.io/helm/pkg/getter/defaultgetters" "k8s.io/helm/pkg/getter"
"k8s.io/helm/pkg/helm/helmpath" "k8s.io/helm/pkg/helm/helmpath"
"k8s.io/helm/pkg/repo" "k8s.io/helm/pkg/repo"
"k8s.io/helm/pkg/repo/repotest" "k8s.io/helm/pkg/repo/repotest"
@ -85,7 +85,7 @@ func TestUpdateCharts(t *testing.T) {
Name: "charts", Name: "charts",
URL: ts.URL(), URL: ts.URL(),
Cache: hh.CacheIndex("charts"), Cache: hh.CacheIndex("charts"),
}, defaultgetters.Get(settings)) }, getter.All(settings))
if err != nil { if err != nil {
t.Error(err) t.Error(err)
} }

@ -66,7 +66,7 @@ type ChartDownloader struct {
// HelmHome is the $HELM_HOME. // HelmHome is the $HELM_HOME.
HelmHome helmpath.Home HelmHome helmpath.Home
// Getter collection for the operation // Getter collection for the operation
Getters []getter.Prop Getters getter.Providers
} }
// 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.
@ -161,7 +161,7 @@ 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 {
getterConstructor, err := getter.ConstructorByScheme(c.Getters, u.Scheme) getterConstructor, err := c.Getters.ByScheme(u.Scheme)
if err != nil { if err != nil {
return u, nil, err return u, nil, err
} }

@ -25,8 +25,7 @@ import (
"path/filepath" "path/filepath"
"testing" "testing"
"k8s.io/helm/pkg/getter/defaultgetters" "k8s.io/helm/pkg/getter"
"k8s.io/helm/pkg/getter/http"
"k8s.io/helm/pkg/helm/environment" "k8s.io/helm/pkg/helm/environment"
"k8s.io/helm/pkg/helm/helmpath" "k8s.io/helm/pkg/helm/helmpath"
"k8s.io/helm/pkg/repo" "k8s.io/helm/pkg/repo"
@ -52,7 +51,7 @@ func TestResolveChartRef(t *testing.T) {
c := ChartDownloader{ c := ChartDownloader{
HelmHome: helmpath.Home("testdata/helmhome"), HelmHome: helmpath.Home("testdata/helmhome"),
Out: os.Stderr, Out: os.Stderr,
Getters: defaultgetters.Get(environment.EnvSettings{}), Getters: getter.All(environment.EnvSettings{}),
} }
for _, tt := range tests { for _, tt := range tests {
@ -89,7 +88,12 @@ func TestDownload(t *testing.T) {
})) }))
defer srv.Close() defer srv.Close()
getter, err := httpgetter.New(srv.URL, "", "", "") provider, err := getter.ByScheme("http", environment.EnvSettings{})
if err != nil {
t.Fatal("No http provider found")
}
getter, err := provider.New(srv.URL, "", "", "")
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -182,7 +186,7 @@ func TestDownloadTo(t *testing.T) {
Out: os.Stderr, Out: os.Stderr,
Verify: VerifyAlways, Verify: VerifyAlways,
Keyring: "testdata/helm-test-key.pub", Keyring: "testdata/helm-test-key.pub",
Getters: defaultgetters.Get(environment.EnvSettings{}), Getters: getter.All(environment.EnvSettings{}),
} }
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)
@ -245,7 +249,7 @@ func TestDownloadTo_VerifyLater(t *testing.T) {
HelmHome: hh, HelmHome: hh,
Out: os.Stderr, Out: os.Stderr,
Verify: VerifyLater, Verify: VerifyLater,
Getters: defaultgetters.Get(environment.EnvSettings{}), Getters: getter.All(environment.EnvSettings{}),
} }
cname := "/signtest-0.1.0.tgz" cname := "/signtest-0.1.0.tgz"
where, _, err := c.DownloadTo(srv.URL()+cname, "", dest) where, _, err := c.DownloadTo(srv.URL()+cname, "", dest)
@ -274,7 +278,7 @@ func TestScanReposForURL(t *testing.T) {
HelmHome: hh, HelmHome: hh,
Out: os.Stderr, Out: os.Stderr,
Verify: VerifyLater, Verify: VerifyLater,
Getters: defaultgetters.Get(environment.EnvSettings{}), Getters: getter.All(environment.EnvSettings{}),
} }
u := "http://example.com/alpine-0.2.0.tgz" u := "http://example.com/alpine-0.2.0.tgz"

@ -56,7 +56,7 @@ type Manager struct {
// SkipUpdate indicates that the repository should not be updated first. // SkipUpdate indicates that the repository should not be updated first.
SkipUpdate bool SkipUpdate bool
// Getter collection for the operation // Getter collection for the operation
Getters []getter.Prop Getters []getter.Provider
} }
// Build rebuilds a local charts directory from a lockfile. // Build rebuilds a local charts directory from a lockfile.

@ -1,71 +0,0 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package defaultgetters
import (
"os"
"k8s.io/helm/pkg/getter"
"k8s.io/helm/pkg/getter/http"
"k8s.io/helm/pkg/getter/plugin"
"k8s.io/helm/pkg/helm/environment"
"k8s.io/helm/pkg/helm/helmpath"
"k8s.io/helm/pkg/plugin"
)
// Get gathers the getter constructors for the downloaders.
// Currently the build-in http getter and the discovered
// plugins with downloader notations are collected.
func Get(settings environment.EnvSettings) []getter.Prop {
result := []getter.Prop{
{
Schemes: getter.Schemes{"http", "https"},
Constructor: httpgetter.New,
},
}
pluginDownloaders, _ := collectPlugins(settings)
result = append(result, pluginDownloaders...)
return result
}
func collectPlugins(settings environment.EnvSettings) ([]getter.Prop, error) {
plugdirs := os.Getenv(environment.PluginEnvVar)
if plugdirs == "" {
home := helmpath.Home(os.Getenv(environment.HomeEnvVar))
plugdirs = home.Plugins()
}
plugins, err := plugin.FindPlugins(plugdirs)
if err != nil {
return nil, err
}
var result []getter.Prop
for _, plugin := range plugins {
for _, downloader := range plugin.Metadata.Downloaders {
result = append(result, getter.Prop{
Schemes: downloader.Protocols,
Constructor: plugingetter.ConstructNew(
downloader.Command,
settings,
plugin.Metadata.Name,
plugin.Dir,
),
})
}
}
return result, nil
}

@ -0,0 +1,21 @@
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*Package getter provides a generalize tool for fetching data by scheme.
This provides a method by which the plugin system can load arbitrary protocol
handlers based upon a URL scheme.
*/
package getter

@ -19,6 +19,8 @@ package getter
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"k8s.io/helm/pkg/helm/environment"
) )
// Getter is an interface to support GET to the specified URL. // Getter is an interface to support GET to the specified URL.
@ -27,27 +29,70 @@ type Getter interface {
Get(url string) (*bytes.Buffer, error) Get(url string) (*bytes.Buffer, error)
} }
//Schemes is the list to represent a specific Getter's protocol capabilities // Constructor is the function for every getter which creates a specific instance
type Schemes []string // according to the configuration
//Constructor is the function for every getter which creates a specific instance
//according to the configuration
type Constructor func(URL, CertFile, KeyFile, CAFile string) (Getter, error) type Constructor func(URL, CertFile, KeyFile, CAFile string) (Getter, error)
//Prop represents any getter and its capability // Provider represents any getter and the schemes that it supports.
type Prop struct { //
Schemes Schemes // For example, an HTTP provider may provide one getter that handles both
Constructor Constructor // 'http' and 'https' schemes.
type Provider struct {
Schemes []string
New Constructor
}
// Provides returns true if the given scheme is supported by this Provider.
func (p Provider) Provides(scheme string) bool {
for _, i := range p.Schemes {
if i == scheme {
return true
}
}
return false
}
// Providers is a collection of Provider objects.
type Providers []Provider
// ByScheme returns a Provider that handles the given scheme.
//
// If no provider handles this scheme, this will return an error.
func (p Providers) ByScheme(scheme string) (Constructor, error) {
for _, pp := range p {
if pp.Provides(scheme) {
return pp.New, nil
}
}
return nil, fmt.Errorf("scheme %q not supported", scheme)
}
// All finds all of the registered getters as a list of Provider instances.
// Currently the build-in http/https getter and the discovered
// plugins with downloader notations are collected.
func All(settings environment.EnvSettings) Providers {
result := Providers{
{
Schemes: []string{"http", "https"},
New: newHTTPGetter,
},
}
pluginDownloaders, _ := collectPlugins(settings)
result = append(result, pluginDownloaders...)
return result
} }
//ConstructorByScheme returns a contstructor based on the required scheme // ByScheme returns a getter for the given scheme.
func ConstructorByScheme(props []Prop, requiredScheme string) (Constructor, error) { //
for _, item := range props { // If the scheme is not supported, this will return an error.
for _, itemScheme := range item.Schemes { func ByScheme(scheme string, settings environment.EnvSettings) (Provider, error) {
if itemScheme == requiredScheme { // Q: What do you call a scheme string who's the boss?
return item.Constructor, nil // A: Bruce Schemestring, of course.
} a := All(settings)
for _, p := range a {
if p.Provides(scheme) {
return p, nil
} }
} }
return nil, fmt.Errorf("Getter not found") return Provider{}, fmt.Errorf("scheme %q not supported", scheme)
} }

@ -0,0 +1,81 @@
/*
Copyright 2017 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package getter
import (
"os"
"testing"
)
func TestProvider(t *testing.T) {
p := Provider{
[]string{"one", "three"},
func(h, e, l, m string) (Getter, error) { return nil, nil },
}
if !p.Provides("three") {
t.Error("Expected provider to provide three")
}
}
func TestProviders(t *testing.T) {
ps := Providers{
{[]string{"one", "three"}, func(h, e, l, m string) (Getter, error) { return nil, nil }},
{[]string{"two", "four"}, func(h, e, l, m string) (Getter, error) { return nil, nil }},
}
if _, err := ps.ByScheme("one"); err != nil {
t.Error(err)
}
if _, err := ps.ByScheme("four"); err != nil {
t.Error(err)
}
if _, err := ps.ByScheme("five"); err == nil {
t.Error("Did not expect handler for five")
}
}
func TestAll(t *testing.T) {
oldhh := os.Getenv("HELM_HOME")
defer os.Setenv("HELM_HOME", oldhh)
os.Setenv("HELM_HOME", "")
env := hh(false)
all := All(env)
if len(all) != 3 {
t.Errorf("expected 3 providers (default plus two plugins), got %d", len(all))
}
if _, err := all.ByScheme("test2"); err != nil {
t.Error(err)
}
}
func TestByScheme(t *testing.T) {
oldhh := os.Getenv("HELM_HOME")
defer os.Setenv("HELM_HOME", oldhh)
os.Setenv("HELM_HOME", "")
env := hh(false)
if _, err := ByScheme("test", env); err != nil {
t.Error(err)
}
if _, err := ByScheme("https", env); err != nil {
t.Error(err)
}
}

@ -1,11 +1,10 @@
/* /*
Copyright 2016 The Kubernetes Authors All rights reserved. Copyright 2016 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
@ -14,7 +13,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package httpgetter package getter
import ( import (
"bytes" "bytes"
@ -22,18 +21,17 @@ import (
"io" "io"
"net/http" "net/http"
"k8s.io/helm/pkg/getter"
"k8s.io/helm/pkg/tlsutil" "k8s.io/helm/pkg/tlsutil"
"k8s.io/helm/pkg/urlutil" "k8s.io/helm/pkg/urlutil"
) )
//HTTPGetter is the efault HTTP(/S) backend handler //httpGetter is the efault HTTP(/S) backend handler
type HTTPGetter struct { type httpGetter struct {
client *http.Client client *http.Client
} }
//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) {
buf := bytes.NewBuffer(nil) buf := bytes.NewBuffer(nil)
resp, err := g.client.Get(href) resp, err := g.client.Get(href)
@ -49,9 +47,9 @@ func (g *HTTPGetter) Get(href string) (*bytes.Buffer, error) {
return buf, err return buf, err
} }
//New constructs a valid http/https client as Getter // newHTTPGetter constructs a valid http/https client as Getter
func New(URL, CertFile, KeyFile, CAFile string) (getter.Getter, error) { func newHTTPGetter(URL, CertFile, KeyFile, CAFile string) (Getter, error) {
var client HTTPGetter var client httpGetter
if CertFile != "" && KeyFile != "" && CAFile != "" { if CertFile != "" && KeyFile != "" && CAFile != "" {
tlsConf, err := tlsutil.NewClientTLS(CertFile, KeyFile, CAFile) tlsConf, err := tlsutil.NewClientTLS(CertFile, KeyFile, CAFile)
if err != nil { if err != nil {

@ -0,0 +1,48 @@
/*
Copyright 2017 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package getter
import (
"net/http"
"path/filepath"
"testing"
)
func TestHTTPGetter(t *testing.T) {
g, err := newHTTPGetter("http://example.com", "", "", "")
if err != nil {
t.Fatal(err)
}
if hg, ok := g.(*httpGetter); !ok {
t.Fatal("Expected newHTTPGetter to produce an httpGetter")
} else if hg.client != http.DefaultClient {
t.Fatal("Expected newHTTPGetter to return a default HTTP client.")
}
// Test with SSL:
cd := "../../testdata"
join := filepath.Join
ca, pub, priv := join(cd, "ca.pem"), join(cd, "crt.pem"), join(cd, "key.pem")
g, err = newHTTPGetter("http://example.com/", pub, priv, ca)
if err != nil {
t.Fatal(err)
}
if _, ok := g.(*httpGetter); !ok {
t.Fatal("Expected newHTTPGetter to produce an httpGetter")
}
}

@ -13,7 +13,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package plugingetter package getter
import ( import (
"bytes" "bytes"
@ -22,14 +22,37 @@ import (
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"k8s.io/helm/pkg/getter"
"k8s.io/helm/pkg/helm/environment" "k8s.io/helm/pkg/helm/environment"
"k8s.io/helm/pkg/plugin" "k8s.io/helm/pkg/plugin"
) )
// PluginGetter is a generic type to invoke custom downloaders, // collectPlugins scans for getter plugins.
// This will load plugins according to the environment.
func collectPlugins(settings environment.EnvSettings) (Providers, error) {
plugins, err := plugin.FindPlugins(settings.PlugDirs)
if err != nil {
return nil, err
}
var result Providers
for _, plugin := range plugins {
for _, downloader := range plugin.Metadata.Downloaders {
result = append(result, Provider{
Schemes: downloader.Protocols,
New: newPluginGetter(
downloader.Command,
settings,
plugin.Metadata.Name,
plugin.Dir,
),
})
}
}
return result, nil
}
// pluginGetter is a generic type to invoke custom downloaders,
// implemented in plugins. // implemented in plugins.
type PluginGetter struct { type pluginGetter struct {
command string command string
certFile, keyFile, cAFile string certFile, keyFile, cAFile string
settings environment.EnvSettings settings environment.EnvSettings
@ -38,7 +61,7 @@ type PluginGetter struct {
} }
// Get runs downloader plugin command // Get runs downloader plugin command
func (p *PluginGetter) Get(href string) (*bytes.Buffer, error) { func (p *pluginGetter) Get(href string) (*bytes.Buffer, error) {
argv := []string{p.certFile, p.keyFile, p.cAFile, href} argv := []string{p.certFile, p.keyFile, p.cAFile, href}
prog := exec.Command(filepath.Join(p.base, p.command), argv...) prog := exec.Command(filepath.Join(p.base, p.command), argv...)
plugin.SetupPluginEnv(p.settings, p.name, p.base) plugin.SetupPluginEnv(p.settings, p.name, p.base)
@ -56,13 +79,10 @@ func (p *PluginGetter) Get(href string) (*bytes.Buffer, error) {
return buf, nil return buf, nil
} }
// ConstructNew constructs a valid plugin getter // newPluginGetter constructs a valid plugin getter
func ConstructNew(command string, func newPluginGetter(command string, settings environment.EnvSettings, name, base string) Constructor {
settings environment.EnvSettings, return func(URL, CertFile, KeyFile, CAFile string) (Getter, error) {
name string, result := &pluginGetter{
base string) getter.Constructor {
return func(URL, CertFile, KeyFile, CAFile string) (getter.Getter, error) {
result := &PluginGetter{
command: command, command: command,
certFile: CertFile, certFile: CertFile,
keyFile: KeyFile, keyFile: KeyFile,

@ -0,0 +1,92 @@
/*
Copyright 2017 The Kubernetes Authors All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package getter
import (
"os"
"path/filepath"
"strings"
"testing"
"k8s.io/helm/pkg/helm/environment"
"k8s.io/helm/pkg/helm/helmpath"
)
func hh(debug bool) environment.EnvSettings {
apath, err := filepath.Abs("./testdata")
if err != nil {
panic(err)
}
hp := helmpath.Home(apath)
return environment.EnvSettings{
Home: hp,
PlugDirs: hp.Plugins(),
Debug: debug,
}
}
func TestCollectPlugins(t *testing.T) {
// Reset HELM HOME to testdata.
oldhh := os.Getenv("HELM_HOME")
defer os.Setenv("HELM_HOME", oldhh)
os.Setenv("HELM_HOME", "")
env := hh(false)
p, err := collectPlugins(env)
if err != nil {
t.Fatal(err)
}
if len(p) != 2 {
t.Errorf("Expected 2 plugins, got %d: %v", len(p), p)
}
if _, err := p.ByScheme("test2"); err != nil {
t.Error(err)
}
if _, err := p.ByScheme("test"); err != nil {
t.Error(err)
}
if _, err := p.ByScheme("nosuchthing"); err == nil {
t.Fatal("did not expect protocol handler for nosuchthing")
}
}
func TestPluginGetter(t *testing.T) {
oldhh := os.Getenv("HELM_HOME")
defer os.Setenv("HELM_HOME", oldhh)
os.Setenv("HELM_HOME", "")
env := hh(false)
pg := newPluginGetter("echo", env, "test", ".")
g, err := pg("test://foo/bar", "", "", "")
if err != nil {
t.Fatal(err)
}
data, err := g.Get("test://foo/bar")
if err != nil {
t.Fatal(err)
}
expect := "test://foo/bar"
got := strings.TrimSpace(data.String())
if got != expect {
t.Errorf("Expected %q, got %q", expect, got)
}
}

@ -0,0 +1,8 @@
#!/bin/bash
echo ENVIRONMENT
env
echo ""
echo ARGUMENTS
echo $@

@ -0,0 +1,15 @@
name: "testgetter"
version: "0.1.0"
usage: "Fetch a package from a test:// source"
description: |-
Print the environment that the plugin was given, then exit.
This registers the test:// protocol.
command: "$HELM_PLUGIN_DIR/get.sh"
ignoreFlags: true
downloaders:
#- command: "$HELM_PLUGIN_DIR/get.sh"
- command: "echo"
protocols:
- "test"

@ -0,0 +1,8 @@
#!/bin/bash
echo ENVIRONMENT
env
echo ""
echo ARGUMENTS
echo $@

@ -0,0 +1,10 @@
name: "testgetter2"
version: "0.1.0"
usage: "Fetch a different package from a test2:// source"
description: "Handle test2 scheme"
command: "$HELM_PLUGIN_DIR/get.sh"
ignoreFlags: true
downloaders:
- command: "echo"
protocols:
- "test2"

@ -0,0 +1 @@
repository/local/index.yaml

File diff suppressed because it is too large Load Diff

@ -0,0 +1,3 @@
apiVersion: v1
entries: {}
generated: 2017-04-28T12:34:38.900985501-06:00

@ -0,0 +1,15 @@
apiVersion: v1
generated: 2017-04-28T12:34:38.551693035-06:00
repositories:
- caFile: ""
cache: repository/cache/stable-index.yaml
certFile: ""
keyFile: ""
name: stable
url: https://kubernetes-charts.storage.googleapis.com
- caFile: ""
cache: repository/cache/local-index.yaml
certFile: ""
keyFile: ""
name: local
url: http://127.0.0.1:8879/charts

@ -50,13 +50,13 @@ type ChartRepository struct {
} }
// NewChartRepository constructs ChartRepository // NewChartRepository constructs ChartRepository
func NewChartRepository(cfg *Entry, getters []getter.Prop) (*ChartRepository, error) { func NewChartRepository(cfg *Entry, getters getter.Providers) (*ChartRepository, error) {
u, err := url.Parse(cfg.URL) u, err := url.Parse(cfg.URL)
if err != nil { if err != nil {
return nil, fmt.Errorf("invalid chart URL format: %s", cfg.URL) return nil, fmt.Errorf("invalid chart URL format: %s", cfg.URL)
} }
getterConstructor, err := getter.ConstructorByScheme(getters, u.Scheme) getterConstructor, err := getters.ByScheme(u.Scheme)
if err != nil { if err != nil {
return nil, fmt.Errorf("Could not find protocol handler for: %s", u.Scheme) return nil, fmt.Errorf("Could not find protocol handler for: %s", u.Scheme)
} }

@ -23,7 +23,7 @@ import (
"testing" "testing"
"time" "time"
"k8s.io/helm/pkg/getter/defaultgetters" "k8s.io/helm/pkg/getter"
"k8s.io/helm/pkg/helm/environment" "k8s.io/helm/pkg/helm/environment"
"k8s.io/helm/pkg/proto/hapi/chart" "k8s.io/helm/pkg/proto/hapi/chart"
) )
@ -37,7 +37,7 @@ func TestLoadChartRepository(t *testing.T) {
r, err := NewChartRepository(&Entry{ r, err := NewChartRepository(&Entry{
Name: testRepository, Name: testRepository,
URL: testURL, URL: testURL,
}, defaultgetters.Get(environment.EnvSettings{})) }, getter.All(environment.EnvSettings{}))
if err != nil { if err != nil {
t.Errorf("Problem creating chart repository from %s: %v", testRepository, err) t.Errorf("Problem creating chart repository from %s: %v", testRepository, err)
} }
@ -69,7 +69,7 @@ func TestIndex(t *testing.T) {
r, err := NewChartRepository(&Entry{ r, err := NewChartRepository(&Entry{
Name: testRepository, Name: testRepository,
URL: testURL, URL: testURL,
}, defaultgetters.Get(environment.EnvSettings{})) }, getter.All(environment.EnvSettings{}))
if err != nil { if err != nil {
t.Errorf("Problem creating chart repository from %s: %v", testRepository, err) t.Errorf("Problem creating chart repository from %s: %v", testRepository, err)
} }

@ -24,7 +24,7 @@ import (
"path/filepath" "path/filepath"
"testing" "testing"
"k8s.io/helm/pkg/getter/defaultgetters" "k8s.io/helm/pkg/getter"
"k8s.io/helm/pkg/helm/environment" "k8s.io/helm/pkg/helm/environment"
"k8s.io/helm/pkg/proto/hapi/chart" "k8s.io/helm/pkg/proto/hapi/chart"
) )
@ -152,7 +152,7 @@ func TestDownloadIndexFile(t *testing.T) {
Name: testRepo, Name: testRepo,
URL: srv.URL, URL: srv.URL,
Cache: indexFilePath, Cache: indexFilePath,
}, defaultgetters.Get(environment.EnvSettings{})) }, getter.All(environment.EnvSettings{}))
if err != nil { if err != nil {
t.Errorf("Problem creating chart repository from %s: %v", testRepo, err) t.Errorf("Problem creating chart repository from %s: %v", testRepo, err)
} }

@ -17,10 +17,10 @@ limitations under the License.
package urlutil package urlutil
import ( import (
"net"
"net/url" "net/url"
"path" "path"
"path/filepath" "path/filepath"
"strings"
) )
// URLJoin joins a base URL to one or more path components. // URLJoin joins a base URL to one or more path components.
@ -70,10 +70,18 @@ func ExtractHostname(addr string) (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
return stripPort(u.Host), nil
}
host, _, err := net.SplitHostPort(u.Host) // Backported from Go 1.8 because Circle is still on 1.7
if err != nil { func stripPort(hostport string) string {
return "", err colon := strings.IndexByte(hostport, ':')
if colon == -1 {
return hostport
} }
return host, nil if i := strings.IndexByte(hostport, ']'); i != -1 {
return strings.TrimPrefix(hostport[:i], "[")
}
return hostport[:colon]
} }

@ -62,3 +62,16 @@ func TestEqual(t *testing.T) {
} }
} }
} }
func TestExtractHostname(t *testing.T) {
tests := map[string]string{
"http://example.com": "example.com",
"https://example.com/foo": "example.com",
"https://example.com:31337/not/with/a/bang/but/a/whimper": "example.com",
}
for start, expect := range tests {
if got, _ := ExtractHostname(start); got != expect {
t.Errorf("Got %q, expected %q", got, expect)
}
}
}

Loading…
Cancel
Save