github.com/sri09kanth/helm@v3.0.0-beta.3+incompatible/pkg/repo/chartrepo_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  	"bytes"
    21  	"io/ioutil"
    22  	"net/http"
    23  	"net/http/httptest"
    24  	"os"
    25  	"path/filepath"
    26  	"reflect"
    27  	"strings"
    28  	"testing"
    29  	"time"
    30  
    31  	"sigs.k8s.io/yaml"
    32  
    33  	"helm.sh/helm/internal/test/ensure"
    34  	"helm.sh/helm/pkg/chart"
    35  	"helm.sh/helm/pkg/cli"
    36  	"helm.sh/helm/pkg/getter"
    37  )
    38  
    39  const (
    40  	testRepository = "testdata/repository"
    41  	testURL        = "http://example-charts.com"
    42  )
    43  
    44  func TestLoadChartRepository(t *testing.T) {
    45  	r, err := NewChartRepository(&Entry{
    46  		Name: testRepository,
    47  		URL:  testURL,
    48  	}, getter.All(&cli.EnvSettings{}))
    49  	if err != nil {
    50  		t.Errorf("Problem creating chart repository from %s: %v", testRepository, err)
    51  	}
    52  
    53  	if err := r.Load(); err != nil {
    54  		t.Errorf("Problem loading chart repository from %s: %v", testRepository, err)
    55  	}
    56  
    57  	paths := []string{
    58  		filepath.Join(testRepository, "frobnitz-1.2.3.tgz"),
    59  		filepath.Join(testRepository, "sprocket-1.1.0.tgz"),
    60  		filepath.Join(testRepository, "sprocket-1.2.0.tgz"),
    61  		filepath.Join(testRepository, "universe/zarthal-1.0.0.tgz"),
    62  	}
    63  
    64  	if r.Config.Name != testRepository {
    65  		t.Errorf("Expected %s as Name but got %s", testRepository, r.Config.Name)
    66  	}
    67  
    68  	if !reflect.DeepEqual(r.ChartPaths, paths) {
    69  		t.Errorf("Expected %#v but got %#v\n", paths, r.ChartPaths)
    70  	}
    71  
    72  	if r.Config.URL != testURL {
    73  		t.Errorf("Expected url for chart repository to be %s but got %s", testURL, r.Config.URL)
    74  	}
    75  }
    76  
    77  func TestIndex(t *testing.T) {
    78  	r, err := NewChartRepository(&Entry{
    79  		Name: testRepository,
    80  		URL:  testURL,
    81  	}, getter.All(&cli.EnvSettings{}))
    82  	if err != nil {
    83  		t.Errorf("Problem creating chart repository from %s: %v", testRepository, err)
    84  	}
    85  
    86  	if err := r.Load(); err != nil {
    87  		t.Errorf("Problem loading chart repository from %s: %v", testRepository, err)
    88  	}
    89  
    90  	err = r.Index()
    91  	if err != nil {
    92  		t.Errorf("Error performing index: %v\n", err)
    93  	}
    94  
    95  	tempIndexPath := filepath.Join(testRepository, indexPath)
    96  	actual, err := LoadIndexFile(tempIndexPath)
    97  	defer os.Remove(tempIndexPath) // clean up
    98  	if err != nil {
    99  		t.Errorf("Error loading index file %v", err)
   100  	}
   101  	verifyIndex(t, actual)
   102  
   103  	// Re-index and test again.
   104  	err = r.Index()
   105  	if err != nil {
   106  		t.Errorf("Error performing re-index: %s\n", err)
   107  	}
   108  	second, err := LoadIndexFile(tempIndexPath)
   109  	if err != nil {
   110  		t.Errorf("Error re-loading index file %v", err)
   111  	}
   112  	verifyIndex(t, second)
   113  }
   114  
   115  type CustomGetter struct {
   116  	repoUrls []string
   117  }
   118  
   119  func (g *CustomGetter) Get(href string, options ...getter.Option) (*bytes.Buffer, error) {
   120  	index := &IndexFile{
   121  		APIVersion: "v1",
   122  		Generated:  time.Now(),
   123  	}
   124  	indexBytes, err := yaml.Marshal(index)
   125  	if err != nil {
   126  		return nil, err
   127  	}
   128  	g.repoUrls = append(g.repoUrls, href)
   129  	return bytes.NewBuffer(indexBytes), nil
   130  }
   131  
   132  func TestIndexCustomSchemeDownload(t *testing.T) {
   133  	repoName := "gcs-repo"
   134  	repoURL := "gs://some-gcs-bucket"
   135  	myCustomGetter := &CustomGetter{}
   136  	customGetterConstructor := func(options ...getter.Option) (getter.Getter, error) {
   137  		return myCustomGetter, nil
   138  	}
   139  	providers := getter.Providers{{
   140  		Schemes: []string{"gs"},
   141  		New:     customGetterConstructor,
   142  	}}
   143  	repo, err := NewChartRepository(&Entry{
   144  		Name: repoName,
   145  		URL:  repoURL,
   146  	}, providers)
   147  	if err != nil {
   148  		t.Fatalf("Problem loading chart repository from %s: %v", repoURL, err)
   149  	}
   150  	repo.CachePath = ensure.TempDir(t)
   151  
   152  	tempIndexFile, err := ioutil.TempFile("", "test-repo")
   153  	if err != nil {
   154  		t.Fatalf("Failed to create temp index file: %v", err)
   155  	}
   156  	defer os.Remove(tempIndexFile.Name())
   157  
   158  	idx, err := repo.DownloadIndexFile()
   159  	if err != nil {
   160  		t.Fatalf("Failed to download index file to %s: %v", idx, err)
   161  	}
   162  
   163  	if len(myCustomGetter.repoUrls) != 1 {
   164  		t.Fatalf("Custom Getter.Get should be called once")
   165  	}
   166  
   167  	expectedRepoIndexURL := repoURL + "/index.yaml"
   168  	if myCustomGetter.repoUrls[0] != expectedRepoIndexURL {
   169  		t.Fatalf("Custom Getter.Get should be called with %s", expectedRepoIndexURL)
   170  	}
   171  }
   172  
   173  func verifyIndex(t *testing.T, actual *IndexFile) {
   174  	var empty time.Time
   175  	if actual.Generated == empty {
   176  		t.Errorf("Generated should be greater than 0: %s", actual.Generated)
   177  	}
   178  
   179  	if actual.APIVersion != APIVersionV1 {
   180  		t.Error("Expected v1 API")
   181  	}
   182  
   183  	entries := actual.Entries
   184  	if numEntries := len(entries); numEntries != 3 {
   185  		t.Errorf("Expected 3 charts to be listed in index file but got %v", numEntries)
   186  	}
   187  
   188  	expects := map[string]ChartVersions{
   189  		"frobnitz": {
   190  			{
   191  				Metadata: &chart.Metadata{
   192  					Name:    "frobnitz",
   193  					Version: "1.2.3",
   194  				},
   195  			},
   196  		},
   197  		"sprocket": {
   198  			{
   199  				Metadata: &chart.Metadata{
   200  					Name:    "sprocket",
   201  					Version: "1.2.0",
   202  				},
   203  			},
   204  			{
   205  				Metadata: &chart.Metadata{
   206  					Name:    "sprocket",
   207  					Version: "1.1.0",
   208  				},
   209  			},
   210  		},
   211  		"zarthal": {
   212  			{
   213  				Metadata: &chart.Metadata{
   214  					Name:    "zarthal",
   215  					Version: "1.0.0",
   216  				},
   217  			},
   218  		},
   219  	}
   220  
   221  	for name, versions := range expects {
   222  		got, ok := entries[name]
   223  		if !ok {
   224  			t.Errorf("Could not find %q entry", name)
   225  			continue
   226  		}
   227  		if len(versions) != len(got) {
   228  			t.Errorf("Expected %d versions, got %d", len(versions), len(got))
   229  			continue
   230  		}
   231  		for i, e := range versions {
   232  			g := got[i]
   233  			if e.Name != g.Name {
   234  				t.Errorf("Expected %q, got %q", e.Name, g.Name)
   235  			}
   236  			if e.Version != g.Version {
   237  				t.Errorf("Expected %q, got %q", e.Version, g.Version)
   238  			}
   239  			if len(g.Keywords) != 3 {
   240  				t.Error("Expected 3 keyrwords.")
   241  			}
   242  			if len(g.Maintainers) != 2 {
   243  				t.Error("Expected 2 maintainers.")
   244  			}
   245  			if g.Created == empty {
   246  				t.Error("Expected created to be non-empty")
   247  			}
   248  			if g.Description == "" {
   249  				t.Error("Expected description to be non-empty")
   250  			}
   251  			if g.Home == "" {
   252  				t.Error("Expected home to be non-empty")
   253  			}
   254  			if g.Digest == "" {
   255  				t.Error("Expected digest to be non-empty")
   256  			}
   257  			if len(g.URLs) != 1 {
   258  				t.Error("Expected exactly 1 URL")
   259  			}
   260  		}
   261  	}
   262  }
   263  
   264  // startLocalServerForTests Start the local helm server
   265  func startLocalServerForTests(handler http.Handler) (*httptest.Server, error) {
   266  	if handler == nil {
   267  		fileBytes, err := ioutil.ReadFile("testdata/local-index.yaml")
   268  		if err != nil {
   269  			return nil, err
   270  		}
   271  		handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   272  			w.Write(fileBytes)
   273  		})
   274  	}
   275  
   276  	return httptest.NewServer(handler), nil
   277  }
   278  
   279  func TestFindChartInRepoURL(t *testing.T) {
   280  	srv, err := startLocalServerForTests(nil)
   281  	if err != nil {
   282  		t.Fatal(err)
   283  	}
   284  	defer srv.Close()
   285  
   286  	chartURL, err := FindChartInRepoURL(srv.URL, "nginx", "", "", "", "", getter.All(&cli.EnvSettings{}))
   287  	if err != nil {
   288  		t.Fatalf("%v", err)
   289  	}
   290  	if chartURL != "https://kubernetes-charts.storage.googleapis.com/nginx-0.2.0.tgz" {
   291  		t.Errorf("%s is not the valid URL", chartURL)
   292  	}
   293  
   294  	chartURL, err = FindChartInRepoURL(srv.URL, "nginx", "0.1.0", "", "", "", getter.All(&cli.EnvSettings{}))
   295  	if err != nil {
   296  		t.Errorf("%s", err)
   297  	}
   298  	if chartURL != "https://kubernetes-charts.storage.googleapis.com/nginx-0.1.0.tgz" {
   299  		t.Errorf("%s is not the valid URL", chartURL)
   300  	}
   301  }
   302  
   303  func TestErrorFindChartInRepoURL(t *testing.T) {
   304  
   305  	g := getter.All(&cli.EnvSettings{
   306  		RepositoryCache: ensure.TempDir(t),
   307  	})
   308  
   309  	if _, err := FindChartInRepoURL("http://someserver/something", "nginx", "", "", "", "", g); err == nil {
   310  		t.Errorf("Expected error for bad chart URL, but did not get any errors")
   311  	} else if !strings.Contains(err.Error(), `looks like "http://someserver/something" is not a valid chart repository or cannot be reached: Get http://someserver/something/index.yaml`) {
   312  		t.Errorf("Expected error for bad chart URL, but got a different error (%v)", err)
   313  	}
   314  
   315  	srv, err := startLocalServerForTests(nil)
   316  	if err != nil {
   317  		t.Fatal(err)
   318  	}
   319  	defer srv.Close()
   320  
   321  	if _, err = FindChartInRepoURL(srv.URL, "nginx1", "", "", "", "", g); err == nil {
   322  		t.Errorf("Expected error for chart not found, but did not get any errors")
   323  	} else if err.Error() != `chart "nginx1" not found in `+srv.URL+` repository` {
   324  		t.Errorf("Expected error for chart not found, but got a different error (%v)", err)
   325  	}
   326  
   327  	if _, err = FindChartInRepoURL(srv.URL, "nginx1", "0.1.0", "", "", "", g); err == nil {
   328  		t.Errorf("Expected error for chart not found, but did not get any errors")
   329  	} else if err.Error() != `chart "nginx1" version "0.1.0" not found in `+srv.URL+` repository` {
   330  		t.Errorf("Expected error for chart not found, but got a different error (%v)", err)
   331  	}
   332  
   333  	if _, err = FindChartInRepoURL(srv.URL, "chartWithNoURL", "", "", "", "", g); err == nil {
   334  		t.Errorf("Expected error for no chart URLs available, but did not get any errors")
   335  	} else if err.Error() != `chart "chartWithNoURL" has no downloadable URLs` {
   336  		t.Errorf("Expected error for chart not found, but got a different error (%v)", err)
   337  	}
   338  }
   339  
   340  func TestResolveReferenceURL(t *testing.T) {
   341  	chartURL, err := ResolveReferenceURL("http://localhost:8123/charts/", "nginx-0.2.0.tgz")
   342  	if err != nil {
   343  		t.Errorf("%s", err)
   344  	}
   345  	if chartURL != "http://localhost:8123/charts/nginx-0.2.0.tgz" {
   346  		t.Errorf("%s", chartURL)
   347  	}
   348  
   349  	chartURL, err = ResolveReferenceURL("http://localhost:8123/charts-with-no-trailing-slash", "nginx-0.2.0.tgz")
   350  	if err != nil {
   351  		t.Errorf("%s", err)
   352  	}
   353  	if chartURL != "http://localhost:8123/charts-with-no-trailing-slash/nginx-0.2.0.tgz" {
   354  		t.Errorf("%s", chartURL)
   355  	}
   356  
   357  	chartURL, err = ResolveReferenceURL("http://localhost:8123", "https://kubernetes-charts.storage.googleapis.com/nginx-0.2.0.tgz")
   358  	if err != nil {
   359  		t.Errorf("%s", err)
   360  	}
   361  	if chartURL != "https://kubernetes-charts.storage.googleapis.com/nginx-0.2.0.tgz" {
   362  		t.Errorf("%s", chartURL)
   363  	}
   364  }