github.com/latiif/helm@v2.15.0+incompatible/pkg/repo/index_test.go (about)

     1  /*
     2  Copyright The Helm Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package repo
    18  
    19  import (
    20  	"io/ioutil"
    21  	"net/http"
    22  	"os"
    23  	"path/filepath"
    24  	"strings"
    25  	"testing"
    26  
    27  	"k8s.io/helm/pkg/getter"
    28  	"k8s.io/helm/pkg/helm/environment"
    29  	"k8s.io/helm/pkg/proto/hapi/chart"
    30  )
    31  
    32  const (
    33  	testfile          = "testdata/local-index.yaml"
    34  	unorderedTestfile = "testdata/local-index-unordered.yaml"
    35  	testRepo          = "test-repo"
    36  )
    37  
    38  func TestIndexFile(t *testing.T) {
    39  	i := NewIndexFile()
    40  	i.Add(&chart.Metadata{Name: "clipper", Version: "0.1.0"}, "clipper-0.1.0.tgz", "http://example.com/charts", "sha256:1234567890")
    41  	i.Add(&chart.Metadata{Name: "cutter", Version: "0.1.1"}, "cutter-0.1.1.tgz", "http://example.com/charts", "sha256:1234567890abc")
    42  	i.Add(&chart.Metadata{Name: "cutter", Version: "0.1.0"}, "cutter-0.1.0.tgz", "http://example.com/charts", "sha256:1234567890abc")
    43  	i.Add(&chart.Metadata{Name: "cutter", Version: "0.2.0"}, "cutter-0.2.0.tgz", "http://example.com/charts", "sha256:1234567890abc")
    44  	i.Add(&chart.Metadata{Name: "setter", Version: "0.1.9+alpha"}, "setter-0.1.9+alpha.tgz", "http://example.com/charts", "sha256:1234567890abc")
    45  	i.Add(&chart.Metadata{Name: "setter", Version: "0.1.9+beta"}, "setter-0.1.9+beta.tgz", "http://example.com/charts", "sha256:1234567890abc")
    46  
    47  	i.SortEntries()
    48  
    49  	if i.APIVersion != APIVersionV1 {
    50  		t.Error("Expected API version v1")
    51  	}
    52  
    53  	if len(i.Entries) != 3 {
    54  		t.Errorf("Expected 3 charts. Got %d", len(i.Entries))
    55  	}
    56  
    57  	if i.Entries["clipper"][0].Name != "clipper" {
    58  		t.Errorf("Expected clipper, got %s", i.Entries["clipper"][0].Name)
    59  	}
    60  
    61  	if len(i.Entries["cutter"]) != 3 {
    62  		t.Error("Expected three cutters.")
    63  	}
    64  
    65  	// Test that the sort worked. 0.2 should be at the first index for Cutter.
    66  	if v := i.Entries["cutter"][0].Version; v != "0.2.0" {
    67  		t.Errorf("Unexpected first version: %s", v)
    68  	}
    69  
    70  	cv, err := i.Get("setter", "0.1.9")
    71  	if err == nil && strings.Index(cv.Metadata.Version, "0.1.9") < 0 {
    72  		t.Errorf("Unexpected version: %s", cv.Metadata.Version)
    73  	}
    74  
    75  	cv, err = i.Get("setter", "0.1.9+alpha")
    76  	if err != nil || cv.Metadata.Version != "0.1.9+alpha" {
    77  		t.Errorf("Expected version: 0.1.9+alpha")
    78  	}
    79  }
    80  
    81  func TestLoadIndex(t *testing.T) {
    82  	b, err := ioutil.ReadFile(testfile)
    83  	if err != nil {
    84  		t.Fatal(err)
    85  	}
    86  	i, err := loadIndex(b)
    87  	if err != nil {
    88  		t.Fatal(err)
    89  	}
    90  	verifyLocalIndex(t, i)
    91  }
    92  
    93  func TestLoadIndexFile(t *testing.T) {
    94  	i, err := LoadIndexFile(testfile)
    95  	if err != nil {
    96  		t.Fatal(err)
    97  	}
    98  	verifyLocalIndex(t, i)
    99  }
   100  
   101  func TestLoadUnorderedIndex(t *testing.T) {
   102  	b, err := ioutil.ReadFile(unorderedTestfile)
   103  	if err != nil {
   104  		t.Fatal(err)
   105  	}
   106  	i, err := loadIndex(b)
   107  	if err != nil {
   108  		t.Fatal(err)
   109  	}
   110  	verifyLocalIndex(t, i)
   111  }
   112  
   113  func TestMerge(t *testing.T) {
   114  	ind1 := NewIndexFile()
   115  	ind1.Add(&chart.Metadata{
   116  		Name:    "dreadnought",
   117  		Version: "0.1.0",
   118  	}, "dreadnought-0.1.0.tgz", "http://example.com", "aaaa")
   119  
   120  	ind2 := NewIndexFile()
   121  	ind2.Add(&chart.Metadata{
   122  		Name:    "dreadnought",
   123  		Version: "0.2.0",
   124  	}, "dreadnought-0.2.0.tgz", "http://example.com", "aaaabbbb")
   125  	ind2.Add(&chart.Metadata{
   126  		Name:    "doughnut",
   127  		Version: "0.2.0",
   128  	}, "doughnut-0.2.0.tgz", "http://example.com", "ccccbbbb")
   129  
   130  	ind1.Merge(ind2)
   131  
   132  	if len(ind1.Entries) != 2 {
   133  		t.Errorf("Expected 2 entries, got %d", len(ind1.Entries))
   134  		vs := ind1.Entries["dreadnaught"]
   135  		if len(vs) != 2 {
   136  			t.Errorf("Expected 2 versions, got %d", len(vs))
   137  		}
   138  		v := vs[0]
   139  		if v.Version != "0.2.0" {
   140  			t.Errorf("Expected %q version to be 0.2.0, got %s", v.Name, v.Version)
   141  		}
   142  	}
   143  
   144  }
   145  
   146  func TestDownloadIndexFile(t *testing.T) {
   147  	t.Run("should  download index file", func(t *testing.T) {
   148  		srv, err := startLocalServerForTests(nil)
   149  		if err != nil {
   150  			t.Fatal(err)
   151  		}
   152  		defer srv.Close()
   153  
   154  		dirName, err := ioutil.TempDir("", "tmp")
   155  		if err != nil {
   156  			t.Fatal(err)
   157  		}
   158  		defer os.RemoveAll(dirName)
   159  
   160  		indexFilePath := filepath.Join(dirName, testRepo+"-index.yaml")
   161  		r, err := NewChartRepository(&Entry{
   162  			Name:  testRepo,
   163  			URL:   srv.URL,
   164  			Cache: indexFilePath,
   165  		}, getter.All(environment.EnvSettings{}))
   166  		if err != nil {
   167  			t.Errorf("Problem creating chart repository from %s: %v", testRepo, err)
   168  		}
   169  
   170  		if err := r.DownloadIndexFile(""); err != nil {
   171  			t.Errorf("%#v", err)
   172  		}
   173  
   174  		if _, err := os.Stat(indexFilePath); err != nil {
   175  			t.Errorf("error finding created index file: %#v", err)
   176  		}
   177  
   178  		b, err := ioutil.ReadFile(indexFilePath)
   179  		if err != nil {
   180  			t.Errorf("error reading index file: %#v", err)
   181  		}
   182  
   183  		i, err := loadIndex(b)
   184  		if err != nil {
   185  			t.Errorf("Index %q failed to parse: %s", testfile, err)
   186  			return
   187  		}
   188  
   189  		verifyLocalIndex(t, i)
   190  	})
   191  
   192  	t.Run("should not decode the path in the repo url while downloading index", func(t *testing.T) {
   193  		chartRepoURLPath := "/some%2Fpath/test"
   194  		fileBytes, err := ioutil.ReadFile("testdata/local-index.yaml")
   195  		if err != nil {
   196  			t.Fatal(err)
   197  		}
   198  		handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   199  			if r.URL.RawPath == chartRepoURLPath+"/index.yaml" {
   200  				w.Write(fileBytes)
   201  			}
   202  		})
   203  		srv, err := startLocalServerForTests(handler)
   204  		if err != nil {
   205  			t.Fatal(err)
   206  		}
   207  		defer srv.Close()
   208  
   209  		dirName, err := ioutil.TempDir("", "tmp")
   210  		if err != nil {
   211  			t.Fatal(err)
   212  		}
   213  		defer os.RemoveAll(dirName)
   214  
   215  		indexFilePath := filepath.Join(dirName, testRepo+"-index.yaml")
   216  		r, err := NewChartRepository(&Entry{
   217  			Name:  testRepo,
   218  			URL:   srv.URL + chartRepoURLPath,
   219  			Cache: indexFilePath,
   220  		}, getter.All(environment.EnvSettings{}))
   221  		if err != nil {
   222  			t.Errorf("Problem creating chart repository from %s: %v", "testrepo", err)
   223  		}
   224  
   225  		if err := r.DownloadIndexFile(""); err != nil {
   226  			t.Errorf("%#v", err)
   227  		}
   228  
   229  		if _, err := os.Stat(indexFilePath); err != nil {
   230  			t.Errorf("error finding created index file: %#v", err)
   231  		}
   232  
   233  		b, err := ioutil.ReadFile(indexFilePath)
   234  		if err != nil {
   235  			t.Errorf("error reading index file: %#v", err)
   236  		}
   237  
   238  		i, err := loadIndex(b)
   239  		if err != nil {
   240  			t.Errorf("Index %q failed to parse: %s", testfile, err)
   241  			return
   242  		}
   243  
   244  		verifyLocalIndex(t, i)
   245  	})
   246  }
   247  
   248  func verifyLocalIndex(t *testing.T, i *IndexFile) {
   249  	numEntries := len(i.Entries)
   250  	if numEntries != 3 {
   251  		t.Errorf("Expected 3 entries in index file but got %d", numEntries)
   252  	}
   253  
   254  	alpine, ok := i.Entries["alpine"]
   255  	if !ok {
   256  		t.Errorf("'alpine' section not found.")
   257  		return
   258  	}
   259  
   260  	if l := len(alpine); l != 1 {
   261  		t.Errorf("'alpine' should have 1 chart, got %d", l)
   262  		return
   263  	}
   264  
   265  	nginx, ok := i.Entries["nginx"]
   266  	if !ok || len(nginx) != 2 {
   267  		t.Error("Expected 2 nginx entries")
   268  		return
   269  	}
   270  
   271  	expects := []*ChartVersion{
   272  		{
   273  			Metadata: &chart.Metadata{
   274  				Name:        "alpine",
   275  				Description: "string",
   276  				Version:     "1.0.0",
   277  				Keywords:    []string{"linux", "alpine", "small", "sumtin"},
   278  				Home:        "https://github.com/something",
   279  			},
   280  			URLs: []string{
   281  				"https://kubernetes-charts.storage.googleapis.com/alpine-1.0.0.tgz",
   282  				"http://storage2.googleapis.com/kubernetes-charts/alpine-1.0.0.tgz",
   283  			},
   284  			Digest: "sha256:1234567890abcdef",
   285  		},
   286  		{
   287  			Metadata: &chart.Metadata{
   288  				Name:        "nginx",
   289  				Description: "string",
   290  				Version:     "0.2.0",
   291  				Keywords:    []string{"popular", "web server", "proxy"},
   292  				Home:        "https://github.com/something/else",
   293  			},
   294  			URLs: []string{
   295  				"https://kubernetes-charts.storage.googleapis.com/nginx-0.2.0.tgz",
   296  			},
   297  			Digest: "sha256:1234567890abcdef",
   298  		},
   299  		{
   300  			Metadata: &chart.Metadata{
   301  				Name:        "nginx",
   302  				Description: "string",
   303  				Version:     "0.1.0",
   304  				Keywords:    []string{"popular", "web server", "proxy"},
   305  				Home:        "https://github.com/something",
   306  			},
   307  			URLs: []string{
   308  				"https://kubernetes-charts.storage.googleapis.com/nginx-0.1.0.tgz",
   309  			},
   310  			Digest: "sha256:1234567890abcdef",
   311  		},
   312  	}
   313  	tests := []*ChartVersion{alpine[0], nginx[0], nginx[1]}
   314  
   315  	for i, tt := range tests {
   316  		expect := expects[i]
   317  		if tt.Name != expect.Name {
   318  			t.Errorf("Expected name %q, got %q", expect.Name, tt.Name)
   319  		}
   320  		if tt.Description != expect.Description {
   321  			t.Errorf("Expected description %q, got %q", expect.Description, tt.Description)
   322  		}
   323  		if tt.Version != expect.Version {
   324  			t.Errorf("Expected version %q, got %q", expect.Version, tt.Version)
   325  		}
   326  		if tt.Digest != expect.Digest {
   327  			t.Errorf("Expected digest %q, got %q", expect.Digest, tt.Digest)
   328  		}
   329  		if tt.Home != expect.Home {
   330  			t.Errorf("Expected home %q, got %q", expect.Home, tt.Home)
   331  		}
   332  
   333  		for i, url := range tt.URLs {
   334  			if url != expect.URLs[i] {
   335  				t.Errorf("Expected URL %q, got %q", expect.URLs[i], url)
   336  			}
   337  		}
   338  		for i, kw := range tt.Keywords {
   339  			if kw != expect.Keywords[i] {
   340  				t.Errorf("Expected keywords %q, got %q", expect.Keywords[i], kw)
   341  			}
   342  		}
   343  	}
   344  }
   345  
   346  func TestIndexDirectory(t *testing.T) {
   347  	dir := filepath.Join("testdata", "repository")
   348  	index, err := IndexDirectory(dir, "http://localhost:8080")
   349  	if err != nil {
   350  		t.Fatal(err)
   351  	}
   352  
   353  	if l := len(index.Entries); l != 3 {
   354  		t.Fatalf("Expected 3 entries, got %d", l)
   355  	}
   356  
   357  	// Other things test the entry generation more thoroughly. We just test a
   358  	// few fields.
   359  
   360  	corpus := []struct{ chartName, downloadLink string }{
   361  		{"frobnitz", "http://localhost:8080/frobnitz-1.2.3.tgz"},
   362  		{"zarthal", "http://localhost:8080/universe/zarthal-1.0.0.tgz"},
   363  	}
   364  
   365  	for _, test := range corpus {
   366  		cname := test.chartName
   367  		frobs, ok := index.Entries[cname]
   368  		if !ok {
   369  			t.Fatalf("Could not read chart %s", cname)
   370  		}
   371  
   372  		frob := frobs[0]
   373  		if len(frob.Digest) == 0 {
   374  			t.Errorf("Missing digest of file %s.", frob.Name)
   375  		}
   376  		if frob.URLs[0] != test.downloadLink {
   377  			t.Errorf("Unexpected URLs: %v", frob.URLs)
   378  		}
   379  		if frob.Name != cname {
   380  			t.Errorf("Expected %q, got %q", cname, frob.Name)
   381  		}
   382  	}
   383  }
   384  
   385  func TestLoadUnversionedIndex(t *testing.T) {
   386  	data, err := ioutil.ReadFile("testdata/unversioned-index.yaml")
   387  	if err != nil {
   388  		t.Fatal(err)
   389  	}
   390  
   391  	ind, err := loadUnversionedIndex(data)
   392  	if err != nil {
   393  		t.Fatal(err)
   394  	}
   395  
   396  	if l := len(ind.Entries); l != 2 {
   397  		t.Fatalf("Expected 2 entries, got %d", l)
   398  	}
   399  
   400  	if l := len(ind.Entries["mysql"]); l != 3 {
   401  		t.Fatalf("Expected 3 mysql versions, got %d", l)
   402  	}
   403  }
   404  
   405  func TestIndexAdd(t *testing.T) {
   406  	i := NewIndexFile()
   407  	i.Add(&chart.Metadata{Name: "clipper", Version: "0.1.0"}, "clipper-0.1.0.tgz", "http://example.com/charts", "sha256:1234567890")
   408  
   409  	if i.Entries["clipper"][0].URLs[0] != "http://example.com/charts/clipper-0.1.0.tgz" {
   410  		t.Errorf("Expected http://example.com/charts/clipper-0.1.0.tgz, got %s", i.Entries["clipper"][0].URLs[0])
   411  	}
   412  
   413  	i.Add(&chart.Metadata{Name: "alpine", Version: "0.1.0"}, "/home/charts/alpine-0.1.0.tgz", "http://example.com/charts", "sha256:1234567890")
   414  
   415  	if i.Entries["alpine"][0].URLs[0] != "http://example.com/charts/alpine-0.1.0.tgz" {
   416  		t.Errorf("Expected http://example.com/charts/alpine-0.1.0.tgz, got %s", i.Entries["alpine"][0].URLs[0])
   417  	}
   418  
   419  	i.Add(&chart.Metadata{Name: "deis", Version: "0.1.0"}, "/home/charts/deis-0.1.0.tgz", "http://example.com/charts/", "sha256:1234567890")
   420  
   421  	if i.Entries["deis"][0].URLs[0] != "http://example.com/charts/deis-0.1.0.tgz" {
   422  		t.Errorf("Expected http://example.com/charts/deis-0.1.0.tgz, got %s", i.Entries["deis"][0].URLs[0])
   423  	}
   424  }