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 }