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 }