github.com/azure-devops-engineer/helm@v3.0.0-alpha.2+incompatible/pkg/downloader/chart_downloader_test.go (about)

     1  /*
     2  Copyright The Helm Authors.
     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  	"io/ioutil"
    20  	"net/http"
    21  	"os"
    22  	"path/filepath"
    23  	"testing"
    24  
    25  	"helm.sh/helm/pkg/cli"
    26  	"helm.sh/helm/pkg/getter"
    27  	"helm.sh/helm/pkg/helmpath"
    28  	"helm.sh/helm/pkg/repo"
    29  	"helm.sh/helm/pkg/repo/repotest"
    30  )
    31  
    32  func TestResolveChartRef(t *testing.T) {
    33  	tests := []struct {
    34  		name, ref, expect, version string
    35  		fail                       bool
    36  	}{
    37  		{name: "full URL", ref: "http://example.com/foo-1.2.3.tgz", expect: "http://example.com/foo-1.2.3.tgz"},
    38  		{name: "full URL, HTTPS", ref: "https://example.com/foo-1.2.3.tgz", expect: "https://example.com/foo-1.2.3.tgz"},
    39  		{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"},
    40  		{name: "reference, testing repo", ref: "testing/alpine", expect: "http://example.com/alpine-1.2.3.tgz"},
    41  		{name: "reference, version, testing repo", ref: "testing/alpine", version: "0.2.0", expect: "http://example.com/alpine-0.2.0.tgz"},
    42  		{name: "reference, version, malformed repo", ref: "malformed/alpine", version: "1.2.3", expect: "http://dl.example.com/alpine-1.2.3.tgz"},
    43  		{name: "reference, querystring repo", ref: "testing-querystring/alpine", expect: "http://example.com/alpine-1.2.3.tgz?key=value"},
    44  		{name: "reference, testing-relative repo", ref: "testing-relative/foo", expect: "http://example.com/helm/charts/foo-1.2.3.tgz"},
    45  		{name: "reference, testing-relative repo", ref: "testing-relative/bar", expect: "http://example.com/helm/bar-1.2.3.tgz"},
    46  		{name: "reference, testing-relative-trailing-slash repo", ref: "testing-relative-trailing-slash/foo", expect: "http://example.com/helm/charts/foo-1.2.3.tgz"},
    47  		{name: "reference, testing-relative-trailing-slash repo", ref: "testing-relative-trailing-slash/bar", expect: "http://example.com/helm/bar-1.2.3.tgz"},
    48  		{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},
    49  		{name: "full URL, file", ref: "file:///foo-1.2.3.tgz", fail: true},
    50  		{name: "invalid", ref: "invalid-1.2.3", fail: true},
    51  		{name: "not found", ref: "nosuchthing/invalid-1.2.3", fail: true},
    52  	}
    53  
    54  	c := ChartDownloader{
    55  		HelmHome: helmpath.Home("testdata/helmhome"),
    56  		Out:      os.Stderr,
    57  		Getters:  getter.All(cli.EnvSettings{}),
    58  	}
    59  
    60  	for _, tt := range tests {
    61  		u, err := c.ResolveChartVersion(tt.ref, tt.version)
    62  		if err != nil {
    63  			if tt.fail {
    64  				continue
    65  			}
    66  			t.Errorf("%s: failed with error %s", tt.name, err)
    67  			continue
    68  		}
    69  		if got := u.String(); got != tt.expect {
    70  			t.Errorf("%s: expected %s, got %s", tt.name, tt.expect, got)
    71  		}
    72  	}
    73  }
    74  
    75  func TestVerifyChart(t *testing.T) {
    76  	v, err := VerifyChart("testdata/signtest-0.1.0.tgz", "testdata/helm-test-key.pub")
    77  	if err != nil {
    78  		t.Fatal(err)
    79  	}
    80  	// The verification is tested at length in the provenance package. Here,
    81  	// we just want a quick sanity check that the v is not empty.
    82  	if len(v.FileHash) == 0 {
    83  		t.Error("Digest missing")
    84  	}
    85  }
    86  
    87  func TestIsTar(t *testing.T) {
    88  	tests := map[string]bool{
    89  		"foo.tgz":           true,
    90  		"foo/bar/baz.tgz":   true,
    91  		"foo-1.2.3.4.5.tgz": true,
    92  		"foo.tar.gz":        false, // for our purposes
    93  		"foo.tgz.1":         false,
    94  		"footgz":            false,
    95  	}
    96  
    97  	for src, expect := range tests {
    98  		if isTar(src) != expect {
    99  			t.Errorf("%q should be %t", src, expect)
   100  		}
   101  	}
   102  }
   103  
   104  func TestDownloadTo(t *testing.T) {
   105  	tmp, err := ioutil.TempDir("", "helm-downloadto-")
   106  	if err != nil {
   107  		t.Fatal(err)
   108  	}
   109  	defer os.RemoveAll(tmp)
   110  
   111  	hh := helmpath.Home(tmp)
   112  	dest := filepath.Join(hh.String(), "dest")
   113  	configDirectories := []string{
   114  		hh.String(),
   115  		hh.Repository(),
   116  		hh.Cache(),
   117  		dest,
   118  	}
   119  	for _, p := range configDirectories {
   120  		if fi, err := os.Stat(p); err != nil {
   121  			if err := os.MkdirAll(p, 0755); err != nil {
   122  				t.Fatalf("Could not create %s: %s", p, err)
   123  			}
   124  		} else if !fi.IsDir() {
   125  			t.Fatalf("%s must be a directory", p)
   126  		}
   127  	}
   128  
   129  	// Set up a fake repo
   130  	srv := repotest.NewServer(tmp)
   131  	defer srv.Stop()
   132  	if _, err := srv.CopyCharts("testdata/*.tgz*"); err != nil {
   133  		t.Error(err)
   134  		return
   135  	}
   136  	if err := srv.LinkIndices(); err != nil {
   137  		t.Fatal(err)
   138  	}
   139  
   140  	c := ChartDownloader{
   141  		HelmHome: hh,
   142  		Out:      os.Stderr,
   143  		Verify:   VerifyAlways,
   144  		Keyring:  "testdata/helm-test-key.pub",
   145  		Getters:  getter.All(cli.EnvSettings{}),
   146  	}
   147  	cname := "/signtest-0.1.0.tgz"
   148  	where, v, err := c.DownloadTo(srv.URL()+cname, "", dest)
   149  	if err != nil {
   150  		t.Error(err)
   151  		return
   152  	}
   153  
   154  	if expect := filepath.Join(dest, cname); where != expect {
   155  		t.Errorf("Expected download to %s, got %s", expect, where)
   156  	}
   157  
   158  	if v.FileHash == "" {
   159  		t.Error("File hash was empty, but verification is required.")
   160  	}
   161  
   162  	if _, err := os.Stat(filepath.Join(dest, cname)); err != nil {
   163  		t.Error(err)
   164  		return
   165  	}
   166  }
   167  
   168  func TestDownloadTo_WithOptions(t *testing.T) {
   169  	tmp, err := ioutil.TempDir("", "helm-downloadto-")
   170  	if err != nil {
   171  		t.Fatal(err)
   172  	}
   173  	defer os.RemoveAll(tmp)
   174  
   175  	hh := helmpath.Home(tmp)
   176  	dest := filepath.Join(hh.String(), "dest")
   177  	configDirectories := []string{
   178  		hh.String(),
   179  		hh.Repository(),
   180  		hh.Cache(),
   181  		dest,
   182  	}
   183  	for _, p := range configDirectories {
   184  		if fi, err := os.Stat(p); err != nil {
   185  			if err := os.MkdirAll(p, 0755); err != nil {
   186  				t.Fatalf("Could not create %s: %s", p, err)
   187  			}
   188  		} else if !fi.IsDir() {
   189  			t.Fatalf("%s must be a directory", p)
   190  		}
   191  	}
   192  
   193  	// Set up a fake repo with basic auth enabled
   194  	srv := repotest.NewServer(tmp)
   195  	srv.Stop()
   196  	srv.WithMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   197  		username, password, ok := r.BasicAuth()
   198  		if !ok || username != "username" || password != "password" {
   199  			t.Errorf("Expected request to use basic auth and for username == 'username' and password == 'password', got '%v', '%s', '%s'", ok, username, password)
   200  		}
   201  	}))
   202  	srv.Start()
   203  	defer srv.Stop()
   204  	if _, err := srv.CopyCharts("testdata/*.tgz*"); err != nil {
   205  		t.Error(err)
   206  		return
   207  	}
   208  	if err := srv.LinkIndices(); err != nil {
   209  		t.Fatal(err)
   210  	}
   211  
   212  	c := ChartDownloader{
   213  		HelmHome: hh,
   214  		Out:      os.Stderr,
   215  		Verify:   VerifyAlways,
   216  		Keyring:  "testdata/helm-test-key.pub",
   217  		Getters:  getter.All(cli.EnvSettings{}),
   218  		Options: []getter.Option{
   219  			getter.WithBasicAuth("username", "password"),
   220  		},
   221  	}
   222  	cname := "/signtest-0.1.0.tgz"
   223  	where, v, err := c.DownloadTo(srv.URL()+cname, "", dest)
   224  	if err != nil {
   225  		t.Error(err)
   226  		return
   227  	}
   228  
   229  	if expect := filepath.Join(dest, cname); where != expect {
   230  		t.Errorf("Expected download to %s, got %s", expect, where)
   231  	}
   232  
   233  	if v.FileHash == "" {
   234  		t.Error("File hash was empty, but verification is required.")
   235  	}
   236  
   237  	if _, err := os.Stat(filepath.Join(dest, cname)); err != nil {
   238  		t.Error(err)
   239  		return
   240  	}
   241  }
   242  
   243  func TestDownloadTo_VerifyLater(t *testing.T) {
   244  	tmp, err := ioutil.TempDir("", "helm-downloadto-")
   245  	if err != nil {
   246  		t.Fatal(err)
   247  	}
   248  	defer os.RemoveAll(tmp)
   249  
   250  	hh := helmpath.Home(tmp)
   251  	dest := filepath.Join(hh.String(), "dest")
   252  	configDirectories := []string{
   253  		hh.String(),
   254  		hh.Repository(),
   255  		hh.Cache(),
   256  		dest,
   257  	}
   258  	for _, p := range configDirectories {
   259  		if fi, err := os.Stat(p); err != nil {
   260  			if err := os.MkdirAll(p, 0755); err != nil {
   261  				t.Fatalf("Could not create %s: %s", p, err)
   262  			}
   263  		} else if !fi.IsDir() {
   264  			t.Fatalf("%s must be a directory", p)
   265  		}
   266  	}
   267  
   268  	// Set up a fake repo
   269  	srv := repotest.NewServer(tmp)
   270  	defer srv.Stop()
   271  	if _, err := srv.CopyCharts("testdata/*.tgz*"); err != nil {
   272  		t.Error(err)
   273  		return
   274  	}
   275  	if err := srv.LinkIndices(); err != nil {
   276  		t.Fatal(err)
   277  	}
   278  
   279  	c := ChartDownloader{
   280  		HelmHome: hh,
   281  		Out:      os.Stderr,
   282  		Verify:   VerifyLater,
   283  		Getters:  getter.All(cli.EnvSettings{}),
   284  	}
   285  	cname := "/signtest-0.1.0.tgz"
   286  	where, _, err := c.DownloadTo(srv.URL()+cname, "", dest)
   287  	if err != nil {
   288  		t.Error(err)
   289  		return
   290  	}
   291  
   292  	if expect := filepath.Join(dest, cname); where != expect {
   293  		t.Errorf("Expected download to %s, got %s", expect, where)
   294  	}
   295  
   296  	if _, err := os.Stat(filepath.Join(dest, cname)); err != nil {
   297  		t.Error(err)
   298  		return
   299  	}
   300  	if _, err := os.Stat(filepath.Join(dest, cname+".prov")); err != nil {
   301  		t.Error(err)
   302  		return
   303  	}
   304  }
   305  
   306  func TestScanReposForURL(t *testing.T) {
   307  	hh := helmpath.Home("testdata/helmhome")
   308  	c := ChartDownloader{
   309  		HelmHome: hh,
   310  		Out:      os.Stderr,
   311  		Verify:   VerifyLater,
   312  		Getters:  getter.All(cli.EnvSettings{}),
   313  	}
   314  
   315  	u := "http://example.com/alpine-0.2.0.tgz"
   316  	rf, err := repo.LoadFile(c.HelmHome.RepositoryFile())
   317  	if err != nil {
   318  		t.Fatal(err)
   319  	}
   320  
   321  	entry, err := c.scanReposForURL(u, rf)
   322  	if err != nil {
   323  		t.Fatal(err)
   324  	}
   325  
   326  	if entry.Name != "testing" {
   327  		t.Errorf("Unexpected repo %q for URL %q", entry.Name, u)
   328  	}
   329  
   330  	// A lookup failure should produce an ErrNoOwnerRepo
   331  	u = "https://no.such.repo/foo/bar-1.23.4.tgz"
   332  	if _, err = c.scanReposForURL(u, rf); err != ErrNoOwnerRepo {
   333  		t.Fatalf("expected ErrNoOwnerRepo, got %v", err)
   334  	}
   335  }