mirror of https://github.com/helm/helm.git
ref(getter): flatten the getter package tree
This flattens the getter package tree, adds tests, and changes a little bit of the terminology to follow Go idioms. This also makes much of the getter API private to begin with. This will give us more flexibility in the future.
This commit is contained in:
parent
045bf78f80
commit
bd02f39384
|
@ -21,7 +21,7 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
|
||||
"k8s.io/helm/pkg/downloader"
|
||||
"k8s.io/helm/pkg/getter/defaultgetters"
|
||||
"k8s.io/helm/pkg/getter"
|
||||
"k8s.io/helm/pkg/helm/helmpath"
|
||||
)
|
||||
|
||||
|
@ -77,7 +77,7 @@ func (d *dependencyBuildCmd) run() error {
|
|||
ChartPath: d.chartpath,
|
||||
HelmHome: d.helmhome,
|
||||
Keyring: d.keyring,
|
||||
Getters: defaultgetters.Get(settings),
|
||||
Getters: getter.All(settings),
|
||||
}
|
||||
if d.verify {
|
||||
man.Verify = downloader.VerifyIfPossible
|
||||
|
|
|
@ -21,7 +21,7 @@ import (
|
|||
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/helm/pkg/downloader"
|
||||
"k8s.io/helm/pkg/getter/defaultgetters"
|
||||
"k8s.io/helm/pkg/getter"
|
||||
"k8s.io/helm/pkg/helm/helmpath"
|
||||
)
|
||||
|
||||
|
@ -95,7 +95,7 @@ func (d *dependencyUpdateCmd) run() error {
|
|||
HelmHome: d.helmhome,
|
||||
Keyring: d.keyring,
|
||||
SkipUpdate: d.skipRefresh,
|
||||
Getters: defaultgetters.Get(settings),
|
||||
Getters: getter.All(settings),
|
||||
}
|
||||
if d.verify {
|
||||
man.Verify = downloader.VerifyIfPossible
|
||||
|
|
|
@ -26,7 +26,7 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
"k8s.io/helm/pkg/chartutil"
|
||||
"k8s.io/helm/pkg/downloader"
|
||||
"k8s.io/helm/pkg/getter/defaultgetters"
|
||||
"k8s.io/helm/pkg/getter"
|
||||
)
|
||||
|
||||
const fetchDesc = `
|
||||
|
@ -97,7 +97,7 @@ func (f *fetchCmd) run() error {
|
|||
Out: f.out,
|
||||
Keyring: f.keyring,
|
||||
Verify: downloader.VerifyNever,
|
||||
Getters: defaultgetters.Get(settings),
|
||||
Getters: getter.All(settings),
|
||||
}
|
||||
|
||||
if f.verify {
|
||||
|
|
|
@ -27,7 +27,7 @@ import (
|
|||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
|
||||
"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/repo"
|
||||
)
|
||||
|
@ -314,7 +314,7 @@ func initStableRepo(cacheFile string, skipRefresh bool) (*repo.Entry, error) {
|
|||
URL: stableRepositoryURL,
|
||||
Cache: cacheFile,
|
||||
}
|
||||
r, err := repo.NewChartRepository(&c, defaultgetters.Get(settings))
|
||||
r, err := repo.NewChartRepository(&c, getter.All(settings))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ import (
|
|||
|
||||
"k8s.io/helm/pkg/chartutil"
|
||||
"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/kube"
|
||||
"k8s.io/helm/pkg/proto/hapi/chart"
|
||||
|
@ -357,7 +357,7 @@ func locateChartPath(name, version string, verify bool, keyring string) (string,
|
|||
HelmHome: settings.Home,
|
||||
Out: os.Stdout,
|
||||
Keyring: keyring,
|
||||
Getters: defaultgetters.Get(settings),
|
||||
Getters: getter.All(settings),
|
||||
}
|
||||
if verify {
|
||||
dl.Verify = downloader.VerifyAlways
|
||||
|
|
|
@ -22,7 +22,7 @@ import (
|
|||
|
||||
"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/repo"
|
||||
)
|
||||
|
@ -98,7 +98,7 @@ func addRepository(name, url string, home helmpath.Home, certFile, keyFile, caFi
|
|||
CAFile: caFile,
|
||||
}
|
||||
|
||||
r, err := repo.NewChartRepository(&c, defaultgetters.Get(settings))
|
||||
r, err := repo.NewChartRepository(&c, getter.All(settings))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ import (
|
|||
|
||||
"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/repo"
|
||||
)
|
||||
|
@ -76,7 +76,7 @@ func (u *repoUpdateCmd) run() error {
|
|||
}
|
||||
var repos []*repo.ChartRepository
|
||||
for _, cfg := range f.Repositories {
|
||||
r, err := repo.NewChartRepository(cfg, defaultgetters.Get(settings))
|
||||
r, err := repo.NewChartRepository(cfg, getter.All(settings))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"k8s.io/helm/pkg/getter/defaultgetters"
|
||||
"k8s.io/helm/pkg/getter"
|
||||
"k8s.io/helm/pkg/helm/helmpath"
|
||||
"k8s.io/helm/pkg/repo"
|
||||
"k8s.io/helm/pkg/repo/repotest"
|
||||
|
@ -85,7 +85,7 @@ func TestUpdateCharts(t *testing.T) {
|
|||
Name: "charts",
|
||||
URL: ts.URL(),
|
||||
Cache: hh.CacheIndex("charts"),
|
||||
}, defaultgetters.Get(settings))
|
||||
}, getter.All(settings))
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ type ChartDownloader struct {
|
|||
// HelmHome is the $HELM_HOME.
|
||||
HelmHome helmpath.Home
|
||||
// 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.
|
||||
|
@ -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
|
||||
// swallow the error.
|
||||
if err == ErrNoOwnerRepo {
|
||||
getterConstructor, err := getter.ConstructorByScheme(c.Getters, u.Scheme)
|
||||
getterConstructor, err := c.Getters.ByScheme(u.Scheme)
|
||||
if err != nil {
|
||||
return u, nil, err
|
||||
}
|
||||
|
|
|
@ -25,8 +25,7 @@ import (
|
|||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"k8s.io/helm/pkg/getter/defaultgetters"
|
||||
"k8s.io/helm/pkg/getter/http"
|
||||
"k8s.io/helm/pkg/getter"
|
||||
"k8s.io/helm/pkg/helm/environment"
|
||||
"k8s.io/helm/pkg/helm/helmpath"
|
||||
"k8s.io/helm/pkg/repo"
|
||||
|
@ -52,7 +51,7 @@ func TestResolveChartRef(t *testing.T) {
|
|||
c := ChartDownloader{
|
||||
HelmHome: helmpath.Home("testdata/helmhome"),
|
||||
Out: os.Stderr,
|
||||
Getters: defaultgetters.Get(environment.EnvSettings{}),
|
||||
Getters: getter.All(environment.EnvSettings{}),
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
@ -89,7 +88,12 @@ func TestDownload(t *testing.T) {
|
|||
}))
|
||||
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 {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -182,7 +186,7 @@ func TestDownloadTo(t *testing.T) {
|
|||
Out: os.Stderr,
|
||||
Verify: VerifyAlways,
|
||||
Keyring: "testdata/helm-test-key.pub",
|
||||
Getters: defaultgetters.Get(environment.EnvSettings{}),
|
||||
Getters: getter.All(environment.EnvSettings{}),
|
||||
}
|
||||
cname := "/signtest-0.1.0.tgz"
|
||||
where, v, err := c.DownloadTo(srv.URL()+cname, "", dest)
|
||||
|
@ -245,7 +249,7 @@ func TestDownloadTo_VerifyLater(t *testing.T) {
|
|||
HelmHome: hh,
|
||||
Out: os.Stderr,
|
||||
Verify: VerifyLater,
|
||||
Getters: defaultgetters.Get(environment.EnvSettings{}),
|
||||
Getters: getter.All(environment.EnvSettings{}),
|
||||
}
|
||||
cname := "/signtest-0.1.0.tgz"
|
||||
where, _, err := c.DownloadTo(srv.URL()+cname, "", dest)
|
||||
|
@ -274,7 +278,7 @@ func TestScanReposForURL(t *testing.T) {
|
|||
HelmHome: hh,
|
||||
Out: os.Stderr,
|
||||
Verify: VerifyLater,
|
||||
Getters: defaultgetters.Get(environment.EnvSettings{}),
|
||||
Getters: getter.All(environment.EnvSettings{}),
|
||||
}
|
||||
|
||||
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 bool
|
||||
// Getter collection for the operation
|
||||
Getters []getter.Prop
|
||||
Getters []getter.Provider
|
||||
}
|
||||
|
||||
// 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 (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/helm/pkg/helm/environment"
|
||||
)
|
||||
|
||||
// Getter is an interface to support GET to the specified URL.
|
||||
|
@ -27,27 +29,70 @@ type Getter interface {
|
|||
Get(url string) (*bytes.Buffer, error)
|
||||
}
|
||||
|
||||
//Schemes is the list to represent a specific Getter's protocol capabilities
|
||||
type Schemes []string
|
||||
|
||||
//Constructor is the function for every getter which creates a specific instance
|
||||
//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)
|
||||
|
||||
//Prop represents any getter and its capability
|
||||
type Prop struct {
|
||||
Schemes Schemes
|
||||
Constructor Constructor
|
||||
// Provider represents any getter and the schemes that it supports.
|
||||
//
|
||||
// For example, an HTTP provider may provide one getter that handles both
|
||||
// 'http' and 'https' schemes.
|
||||
type Provider struct {
|
||||
Schemes []string
|
||||
New Constructor
|
||||
}
|
||||
|
||||
//ConstructorByScheme returns a contstructor based on the required scheme
|
||||
func ConstructorByScheme(props []Prop, requiredScheme string) (Constructor, error) {
|
||||
for _, item := range props {
|
||||
for _, itemScheme := range item.Schemes {
|
||||
if itemScheme == requiredScheme {
|
||||
return item.Constructor, nil
|
||||
}
|
||||
// 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 nil, fmt.Errorf("Getter not found")
|
||||
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
|
||||
}
|
||||
|
||||
// ByScheme returns a getter for the given scheme.
|
||||
//
|
||||
// If the scheme is not supported, this will return an error.
|
||||
func ByScheme(scheme string, settings environment.EnvSettings) (Provider, error) {
|
||||
// Q: What do you call a scheme string who's the boss?
|
||||
// A: Bruce Schemestring, of course.
|
||||
a := All(settings)
|
||||
for _, p := range a {
|
||||
if p.Provides(scheme) {
|
||||
return p, nil
|
||||
}
|
||||
}
|
||||
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.
|
||||
|
||||
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
|
||||
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,
|
||||
|
@ -14,7 +13,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package httpgetter
|
||||
package getter
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -22,18 +21,17 @@ import (
|
|||
"io"
|
||||
"net/http"
|
||||
|
||||
"k8s.io/helm/pkg/getter"
|
||||
"k8s.io/helm/pkg/tlsutil"
|
||||
"k8s.io/helm/pkg/urlutil"
|
||||
)
|
||||
|
||||
//HTTPGetter is the efault HTTP(/S) backend handler
|
||||
type HTTPGetter struct {
|
||||
//httpGetter is the efault HTTP(/S) backend handler
|
||||
type httpGetter struct {
|
||||
client *http.Client
|
||||
}
|
||||
|
||||
//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)
|
||||
|
||||
resp, err := g.client.Get(href)
|
||||
|
@ -49,9 +47,9 @@ func (g *HTTPGetter) Get(href string) (*bytes.Buffer, error) {
|
|||
return buf, err
|
||||
}
|
||||
|
||||
//New constructs a valid http/https client as Getter
|
||||
func New(URL, CertFile, KeyFile, CAFile string) (getter.Getter, error) {
|
||||
var client HTTPGetter
|
||||
// newHTTPGetter constructs a valid http/https client as Getter
|
||||
func newHTTPGetter(URL, CertFile, KeyFile, CAFile string) (Getter, error) {
|
||||
var client httpGetter
|
||||
if CertFile != "" && KeyFile != "" && CAFile != "" {
|
||||
tlsConf, err := tlsutil.NewClientTLS(CertFile, KeyFile, CAFile)
|
||||
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.
|
||||
*/
|
||||
|
||||
package plugingetter
|
||||
package getter
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
@ -22,14 +22,37 @@ import (
|
|||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
"k8s.io/helm/pkg/getter"
|
||||
"k8s.io/helm/pkg/helm/environment"
|
||||
"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.
|
||||
type PluginGetter struct {
|
||||
type pluginGetter struct {
|
||||
command string
|
||||
certFile, keyFile, cAFile string
|
||||
settings environment.EnvSettings
|
||||
|
@ -38,7 +61,7 @@ type PluginGetter struct {
|
|||
}
|
||||
|
||||
// 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}
|
||||
prog := exec.Command(filepath.Join(p.base, p.command), argv...)
|
||||
plugin.SetupPluginEnv(p.settings, p.name, p.base)
|
||||
|
@ -56,13 +79,10 @@ func (p *PluginGetter) Get(href string) (*bytes.Buffer, error) {
|
|||
return buf, nil
|
||||
}
|
||||
|
||||
// ConstructNew constructs a valid plugin getter
|
||||
func ConstructNew(command string,
|
||||
settings environment.EnvSettings,
|
||||
name string,
|
||||
base string) getter.Constructor {
|
||||
return func(URL, CertFile, KeyFile, CAFile string) (getter.Getter, error) {
|
||||
result := &PluginGetter{
|
||||
// newPluginGetter constructs a valid plugin getter
|
||||
func newPluginGetter(command string, settings environment.EnvSettings, name, base string) Constructor {
|
||||
return func(URL, CertFile, KeyFile, CAFile string) (Getter, error) {
|
||||
result := &pluginGetter{
|
||||
command: command,
|
||||
certFile: CertFile,
|
||||
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
|
||||
func NewChartRepository(cfg *Entry, getters []getter.Prop) (*ChartRepository, error) {
|
||||
func NewChartRepository(cfg *Entry, getters getter.Providers) (*ChartRepository, error) {
|
||||
u, err := url.Parse(cfg.URL)
|
||||
if err != nil {
|
||||
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 {
|
||||
return nil, fmt.Errorf("Could not find protocol handler for: %s", u.Scheme)
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"k8s.io/helm/pkg/getter/defaultgetters"
|
||||
"k8s.io/helm/pkg/getter"
|
||||
"k8s.io/helm/pkg/helm/environment"
|
||||
"k8s.io/helm/pkg/proto/hapi/chart"
|
||||
)
|
||||
|
@ -37,7 +37,7 @@ func TestLoadChartRepository(t *testing.T) {
|
|||
r, err := NewChartRepository(&Entry{
|
||||
Name: testRepository,
|
||||
URL: testURL,
|
||||
}, defaultgetters.Get(environment.EnvSettings{}))
|
||||
}, getter.All(environment.EnvSettings{}))
|
||||
if err != nil {
|
||||
t.Errorf("Problem creating chart repository from %s: %v", testRepository, err)
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ func TestIndex(t *testing.T) {
|
|||
r, err := NewChartRepository(&Entry{
|
||||
Name: testRepository,
|
||||
URL: testURL,
|
||||
}, defaultgetters.Get(environment.EnvSettings{}))
|
||||
}, getter.All(environment.EnvSettings{}))
|
||||
if err != nil {
|
||||
t.Errorf("Problem creating chart repository from %s: %v", testRepository, err)
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ import (
|
|||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"k8s.io/helm/pkg/getter/defaultgetters"
|
||||
"k8s.io/helm/pkg/getter"
|
||||
"k8s.io/helm/pkg/helm/environment"
|
||||
"k8s.io/helm/pkg/proto/hapi/chart"
|
||||
)
|
||||
|
@ -152,7 +152,7 @@ func TestDownloadIndexFile(t *testing.T) {
|
|||
Name: testRepo,
|
||||
URL: srv.URL,
|
||||
Cache: indexFilePath,
|
||||
}, defaultgetters.Get(environment.EnvSettings{}))
|
||||
}, getter.All(environment.EnvSettings{}))
|
||||
if err != nil {
|
||||
t.Errorf("Problem creating chart repository from %s: %v", testRepo, err)
|
||||
}
|
||||
|
|
|
@ -17,10 +17,10 @@ limitations under the License.
|
|||
package urlutil
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/url"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// URLJoin joins a base URL to one or more path components.
|
||||
|
@ -70,10 +70,18 @@ func ExtractHostname(addr string) (string, error) {
|
|||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
host, _, err := net.SplitHostPort(u.Host)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return host, nil
|
||||
return stripPort(u.Host), nil
|
||||
}
|
||||
|
||||
// Backported from Go 1.8 because Circle is still on 1.7
|
||||
func stripPort(hostport string) string {
|
||||
colon := strings.IndexByte(hostport, ':')
|
||||
if colon == -1 {
|
||||
return hostport
|
||||
}
|
||||
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…
Reference in New Issue