github.com/cloudposse/helm@v2.2.3+incompatible/pkg/downloader/chart_downloader_test.go (about)

     1  /*
     2  Copyright 2016 The Kubernetes Authors All rights reserved.
     3  Licensed under the Apache License, Version 2.0 (the "License");
     4  you may not use this file except in compliance with the License.
     5  You may obtain a copy of the License at
     6  
     7  http://www.apache.org/licenses/LICENSE-2.0
     8  
     9  Unless required by applicable law or agreed to in writing, software
    10  distributed under the License is distributed on an "AS IS" BASIS,
    11  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  See the License for the specific language governing permissions and
    13  limitations under the License.
    14  */
    15  
    16  package downloader
    17  
    18  import (
    19  	"fmt"
    20  	"io/ioutil"
    21  	"net/http"
    22  	"net/http/httptest"
    23  	"net/url"
    24  	"os"
    25  	"path/filepath"
    26  	"testing"
    27  
    28  	"k8s.io/helm/cmd/helm/helmpath"
    29  	"k8s.io/helm/pkg/repo"
    30  	"k8s.io/helm/pkg/repo/repotest"
    31  )
    32  
    33  func TestResolveChartRef(t *testing.T) {
    34  	tests := []struct {
    35  		name, ref, expect, version string
    36  		fail                       bool
    37  	}{
    38  		{name: "full URL", ref: "http://example.com/foo-1.2.3.tgz", expect: "http://example.com/foo-1.2.3.tgz"},
    39  		{name: "full URL, HTTPS", ref: "https://example.com/foo-1.2.3.tgz", expect: "https://example.com/foo-1.2.3.tgz"},
    40  		{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"},
    41  		{name: "reference, testing repo", ref: "testing/alpine", expect: "http://example.com/alpine-1.2.3.tgz"},
    42  		{name: "reference, version, testing repo", ref: "testing/alpine", version: "0.2.0", expect: "http://example.com/alpine-0.2.0.tgz"},
    43  		{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},
    44  		{name: "full URL, file", ref: "file:///foo-1.2.3.tgz", fail: true},
    45  		{name: "invalid", ref: "invalid-1.2.3", fail: true},
    46  		{name: "not found", ref: "nosuchthing/invalid-1.2.3", fail: true},
    47  	}
    48  
    49  	c := ChartDownloader{
    50  		HelmHome: helmpath.Home("testdata/helmhome"),
    51  		Out:      os.Stderr,
    52  	}
    53  
    54  	for _, tt := range tests {
    55  		u, _, err := c.ResolveChartVersion(tt.ref, tt.version)
    56  		if err != nil {
    57  			if tt.fail {
    58  				continue
    59  			}
    60  			t.Errorf("%s: failed with error %s", tt.name, err)
    61  			continue
    62  		}
    63  		if got := u.String(); got != tt.expect {
    64  			t.Errorf("%s: expected %s, got %s", tt.name, tt.expect, got)
    65  		}
    66  	}
    67  }
    68  
    69  func TestVerifyChart(t *testing.T) {
    70  	v, err := VerifyChart("testdata/signtest-0.1.0.tgz", "testdata/helm-test-key.pub")
    71  	if err != nil {
    72  		t.Fatal(err)
    73  	}
    74  	// The verification is tested at length in the provenance package. Here,
    75  	// we just want a quick sanity check that the v is not empty.
    76  	if len(v.FileHash) == 0 {
    77  		t.Error("Digest missing")
    78  	}
    79  }
    80  
    81  func TestDownload(t *testing.T) {
    82  	expect := "Call me Ishmael"
    83  	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    84  		fmt.Fprint(w, expect)
    85  	}))
    86  	defer srv.Close()
    87  
    88  	got, err := download(srv.URL, http.DefaultClient)
    89  	if err != nil {
    90  		t.Fatal(err)
    91  	}
    92  
    93  	if got.String() != expect {
    94  		t.Errorf("Expected %q, got %q", expect, got.String())
    95  	}
    96  
    97  	// test with server backed by basic auth
    98  	basicAuthSrv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    99  		username, password, ok := r.BasicAuth()
   100  		if !ok || username != "username" && password != "password" {
   101  			t.Errorf("Expected request to use basic auth and for username == 'username' and password == 'password', got '%v', '%s', '%s'", ok, username, password)
   102  		}
   103  		fmt.Fprint(w, expect)
   104  	}))
   105  	defer basicAuthSrv.Close()
   106  
   107  	u, _ := url.ParseRequestURI(basicAuthSrv.URL)
   108  	u.User = url.UserPassword("username", "password")
   109  	got, err = download(u.String(), http.DefaultClient)
   110  	if err != nil {
   111  		t.Fatal(err)
   112  	}
   113  
   114  	if got.String() != expect {
   115  		t.Errorf("Expected %q, got %q", expect, got.String())
   116  	}
   117  }
   118  
   119  func TestIsTar(t *testing.T) {
   120  	tests := map[string]bool{
   121  		"foo.tgz":           true,
   122  		"foo/bar/baz.tgz":   true,
   123  		"foo-1.2.3.4.5.tgz": true,
   124  		"foo.tar.gz":        false, // for our purposes
   125  		"foo.tgz.1":         false,
   126  		"footgz":            false,
   127  	}
   128  
   129  	for src, expect := range tests {
   130  		if isTar(src) != expect {
   131  			t.Errorf("%q should be %t", src, expect)
   132  		}
   133  	}
   134  }
   135  
   136  func TestDownloadTo(t *testing.T) {
   137  	tmp, err := ioutil.TempDir("", "helm-downloadto-")
   138  	if err != nil {
   139  		t.Fatal(err)
   140  	}
   141  	defer os.RemoveAll(tmp)
   142  
   143  	hh := helmpath.Home(tmp)
   144  	dest := filepath.Join(hh.String(), "dest")
   145  	configDirectories := []string{
   146  		hh.String(),
   147  		hh.Repository(),
   148  		hh.Cache(),
   149  		dest,
   150  	}
   151  	for _, p := range configDirectories {
   152  		if fi, err := os.Stat(p); err != nil {
   153  			if err := os.MkdirAll(p, 0755); err != nil {
   154  				t.Fatalf("Could not create %s: %s", p, err)
   155  			}
   156  		} else if !fi.IsDir() {
   157  			t.Fatalf("%s must be a directory", p)
   158  		}
   159  	}
   160  
   161  	// Set up a fake repo
   162  	srv := repotest.NewServer(tmp)
   163  	defer srv.Stop()
   164  	if _, err := srv.CopyCharts("testdata/*.tgz*"); err != nil {
   165  		t.Error(err)
   166  		return
   167  	}
   168  	if err := srv.LinkIndices(); err != nil {
   169  		t.Fatal(err)
   170  	}
   171  
   172  	c := ChartDownloader{
   173  		HelmHome: hh,
   174  		Out:      os.Stderr,
   175  		Verify:   VerifyAlways,
   176  		Keyring:  "testdata/helm-test-key.pub",
   177  	}
   178  	cname := "/signtest-0.1.0.tgz"
   179  	where, v, err := c.DownloadTo(srv.URL()+cname, "", dest)
   180  	if err != nil {
   181  		t.Error(err)
   182  		return
   183  	}
   184  
   185  	if expect := filepath.Join(dest, cname); where != expect {
   186  		t.Errorf("Expected download to %s, got %s", expect, where)
   187  	}
   188  
   189  	if v.FileHash == "" {
   190  		t.Error("File hash was empty, but verification is required.")
   191  	}
   192  
   193  	if _, err := os.Stat(filepath.Join(dest, cname)); err != nil {
   194  		t.Error(err)
   195  		return
   196  	}
   197  }
   198  
   199  func TestDownloadTo_VerifyLater(t *testing.T) {
   200  	tmp, err := ioutil.TempDir("", "helm-downloadto-")
   201  	if err != nil {
   202  		t.Fatal(err)
   203  	}
   204  	defer os.RemoveAll(tmp)
   205  
   206  	hh := helmpath.Home(tmp)
   207  	dest := filepath.Join(hh.String(), "dest")
   208  	configDirectories := []string{
   209  		hh.String(),
   210  		hh.Repository(),
   211  		hh.Cache(),
   212  		dest,
   213  	}
   214  	for _, p := range configDirectories {
   215  		if fi, err := os.Stat(p); err != nil {
   216  			if err := os.MkdirAll(p, 0755); err != nil {
   217  				t.Fatalf("Could not create %s: %s", p, err)
   218  			}
   219  		} else if !fi.IsDir() {
   220  			t.Fatalf("%s must be a directory", p)
   221  		}
   222  	}
   223  
   224  	// Set up a fake repo
   225  	srv := repotest.NewServer(tmp)
   226  	defer srv.Stop()
   227  	if _, err := srv.CopyCharts("testdata/*.tgz*"); err != nil {
   228  		t.Error(err)
   229  		return
   230  	}
   231  	if err := srv.LinkIndices(); err != nil {
   232  		t.Fatal(err)
   233  	}
   234  
   235  	c := ChartDownloader{
   236  		HelmHome: hh,
   237  		Out:      os.Stderr,
   238  		Verify:   VerifyLater,
   239  	}
   240  	cname := "/signtest-0.1.0.tgz"
   241  	where, _, err := c.DownloadTo(srv.URL()+cname, "", dest)
   242  	if err != nil {
   243  		t.Error(err)
   244  		return
   245  	}
   246  
   247  	if expect := filepath.Join(dest, cname); where != expect {
   248  		t.Errorf("Expected download to %s, got %s", expect, where)
   249  	}
   250  
   251  	if _, err := os.Stat(filepath.Join(dest, cname)); err != nil {
   252  		t.Error(err)
   253  		return
   254  	}
   255  	if _, err := os.Stat(filepath.Join(dest, cname+".prov")); err != nil {
   256  		t.Error(err)
   257  		return
   258  	}
   259  }
   260  
   261  func TestScanReposForURL(t *testing.T) {
   262  	hh := helmpath.Home("testdata/helmhome")
   263  	c := ChartDownloader{
   264  		HelmHome: hh,
   265  		Out:      os.Stderr,
   266  		Verify:   VerifyLater,
   267  	}
   268  
   269  	u := "http://example.com/alpine-0.2.0.tgz"
   270  	rf, err := repo.LoadRepositoriesFile(c.HelmHome.RepositoryFile())
   271  	if err != nil {
   272  		t.Fatal(err)
   273  	}
   274  
   275  	entry, err := c.scanReposForURL(u, rf)
   276  	if err != nil {
   277  		t.Fatal(err)
   278  	}
   279  
   280  	if entry.Name != "testing" {
   281  		t.Errorf("Unexpected repo %q for URL %q", entry.Name, u)
   282  	}
   283  
   284  	// A lookup failure should produce an ErrNoOwnerRepo
   285  	u = "https://no.such.repo/foo/bar-1.23.4.tgz"
   286  	if _, err = c.scanReposForURL(u, rf); err != ErrNoOwnerRepo {
   287  		t.Fatalf("expected ErrNoOwnerRepo, got %v", err)
   288  	}
   289  }