Skip to content
This repository was archived by the owner on Jul 16, 2021. It is now read-only.

Commit 3ee5f19

Browse files
sozercanprydonius
authored andcommitted
Add support for extracting values.yaml from charts for chart-repo-sync (#421)
* add support for extracting values.yaml from chart * merge readme and values into files collection
1 parent 68f2b0c commit 3ee5f19

File tree

3 files changed

+58
-37
lines changed

3 files changed

+58
-37
lines changed

src/api/cmd/chart-repo-sync/sync.go

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ import (
2727
)
2828

2929
const (
30-
chartCollection = "charts"
31-
chartReadmeCollection = "readmes"
30+
chartCollection = "charts"
31+
chartFilesCollection = "files"
3232
)
3333

3434
type importChartFilesJob struct {
@@ -84,8 +84,8 @@ func main() {
8484
// Syncing is performed in the following steps:
8585
// 1. Update database to match chart metadata from index
8686
// 2. Concurrently process icons for charts (concurrently)
87-
// 3. Concurrently process the README for the latest chart version of each chart
88-
// 4. Concurrently process READMEs for historic chart versions
87+
// 3. Concurrently process the README and values.yaml for the latest chart version of each chart
88+
// 4. Concurrently process READMEs and values.yaml for historic chart versions
8989
//
9090
// These steps are processed in this way to ensure relevant chart data is
9191
// imported into the database as fast as possible. E.g. we want all icons for
@@ -231,7 +231,7 @@ func importCharts(charts []chart) error {
231231
// Upsert pairs of selectors, charts
232232
bulk.Upsert(pairs...)
233233

234-
// Remove charts no longer existing in index
234+
// Remove charts no longer existing in index
235235
bulk.RemoveAll(bson.M{
236236
"_id": bson.M{
237237
"$nin": chartIDs,
@@ -252,9 +252,9 @@ func importWorker(wg *sync.WaitGroup, icons <-chan chart, chartFiles <-chan impo
252252
}
253253
}
254254
for j := range chartFiles {
255-
log.WithFields(log.Fields{"name": j.Name, "version": j.ChartVersion.Version}).Debug("importing readme")
256-
if err := fetchAndImportReadme(j.Name, j.Repo, j.ChartVersion); err != nil {
257-
log.WithFields(log.Fields{"name": j.Name, "version": j.ChartVersion.Version}).WithError(err).Error("failed to import readme")
255+
log.WithFields(log.Fields{"name": j.Name, "version": j.ChartVersion.Version}).Debug("importing readme and values")
256+
if err := fetchAndImportFiles(j.Name, j.Repo, j.ChartVersion); err != nil {
257+
log.WithFields(log.Fields{"name": j.Name, "version": j.ChartVersion.Version}).WithError(err).Error("failed to import files")
258258
}
259259
}
260260
}
@@ -297,15 +297,15 @@ func fetchAndImportIcon(c chart) error {
297297
return db.C(chartCollection).UpdateId(c.ID, bson.M{"$set": bson.M{"raw_icon": b.Bytes()}})
298298
}
299299

300-
func fetchAndImportReadme(name string, r repo, cv chartVersion) error {
301-
chartReadmeID := fmt.Sprintf("%s/%s-%s", r.Name, name, cv.Version)
300+
func fetchAndImportFiles(name string, r repo, cv chartVersion) error {
301+
chartFilesID := fmt.Sprintf("%s/%s-%s", r.Name, name, cv.Version)
302302
db, closer := dbSession.DB()
303303
defer closer()
304-
if err := db.C(chartReadmeCollection).FindId(chartReadmeID).One(&chartReadme{}); err == nil {
305-
log.WithFields(log.Fields{"name": name, "version": cv.Version}).Debug("skipping existing readme")
304+
if err := db.C(chartFilesCollection).FindId(chartFilesID).One(&chartFiles{}); err == nil {
305+
log.WithFields(log.Fields{"name": name, "version": cv.Version}).Debug("skipping existing files")
306306
return nil
307307
}
308-
log.WithFields(log.Fields{"name": name, "version": cv.Version}).Debug("fetching readme")
308+
log.WithFields(log.Fields{"name": name, "version": cv.Version}).Debug("fetching files")
309309

310310
url := chartTarballURL(r, cv)
311311
req, err := http.NewRequest("GET", url, nil)
@@ -333,22 +333,37 @@ func fetchAndImportReadme(name string, r repo, cv chartVersion) error {
333333
tarf := tar.NewReader(gzf)
334334

335335
readmeFileName := name + "/README.md"
336-
readme, err := extractFileFromTarball(readmeFileName, tarf)
337-
if err != nil && !strings.Contains(err.Error(), "file not found") {
338-
return err
339-
}
336+
valuesFileName := name + "/values.yaml"
337+
fileNames := []string{valuesFileName, readmeFileName}
340338

341-
// Even if the readme doesn't exist, we create an empty entry to avoid
342-
// refetching for this chart version in the future
343-
if readme == "" {
344-
log.WithFields(log.Fields{"name": name, "version": cv.Version}).Info("readme not found")
345-
}
339+
files, err := getFiles(cv, name, fileNames, tarf)
340+
values := files[0]
341+
readme := files[1]
346342

347-
db.C(chartReadmeCollection).Insert(chartReadme{chartReadmeID, readme})
343+
db.C(chartFilesCollection).Insert(chartFiles{chartFilesID, readme, values})
348344

349345
return nil
350346
}
351347

348+
func getFiles(cv chartVersion, name string, filenames []string, tarf *tar.Reader) ([]string, error) {
349+
var files []string
350+
351+
for _, filename := range filenames {
352+
file, err := extractFileFromTarball(filename, tarf)
353+
if err != nil && !strings.Contains(err.Error(), "file not found") {
354+
return nil, err
355+
}
356+
357+
if file == "" {
358+
log.WithFields(log.Fields{"name": name, "version": cv.Version}).Info(filename + " not found")
359+
}
360+
361+
files = append(files, file)
362+
}
363+
364+
return files, nil
365+
}
366+
352367
func chartTarballURL(r repo, cv chartVersion) string {
353368
source := cv.URLs[0]
354369
if _, err := url.ParseRequestURI(source); err != nil {

src/api/cmd/chart-repo-sync/sync_test.go

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -85,14 +85,19 @@ func (h *goodIconClient) Do(req *http.Request) (*http.Response, error) {
8585
type goodTarballClient struct {
8686
c chart
8787
skipReadme bool
88+
skipValues bool
8889
}
8990

9091
var testChartReadme = "# readme for chart\n\nBest chart in town"
92+
var testChartValues = "image: test"
9193

9294
func (h *goodTarballClient) Do(req *http.Request) (*http.Response, error) {
9395
w := httptest.NewRecorder()
9496
gzw := gzip.NewWriter(w)
9597
files := []tarballFile{{h.c.Name + "/Chart.yaml", "should be a Chart.yaml here..."}}
98+
if !h.skipValues {
99+
files = append(files, tarballFile{h.c.Name + "/values.yaml", testChartValues})
100+
}
96101
if !h.skipReadme {
97102
files = append(files, tarballFile{h.c.Name + "/README.md", testChartReadme})
98103
}
@@ -247,7 +252,7 @@ func Test_fetchAndImportIcon(t *testing.T) {
247252
})
248253
}
249254

250-
func Test_fetchAndImportReadme(t *testing.T) {
255+
func Test_fetchAndImportFiles(t *testing.T) {
251256
index, _ := parseRepoIndex([]byte(validRepoIndexYAML))
252257
charts := chartsFromIndex(index, repo{Name: "test", URL: "http://testrepo.com"})
253258
cv := charts[0].ChartVersions[0]
@@ -257,37 +262,37 @@ func Test_fetchAndImportReadme(t *testing.T) {
257262
m.On("One", mock.Anything).Return(errors.New("return an error when checking if readme already exists to force fetching"))
258263
dbSession = mockstore.NewMockSession(&m)
259264
netClient = &badHTTPClient{}
260-
assert.Err(t, io.EOF, fetchAndImportReadme(charts[0].Name, charts[0].Repo, cv))
265+
assert.Err(t, io.EOF, fetchAndImportFiles(charts[0].Name, charts[0].Repo, cv))
261266
})
262267

263-
t.Run("readme not found", func(t *testing.T) {
264-
netClient = &goodTarballClient{c: charts[0], skipReadme: true}
268+
t.Run("file not found", func(t *testing.T) {
269+
netClient = &goodTarballClient{c: charts[0], skipValues: true, skipReadme: true}
265270
m := mock.Mock{}
266-
m.On("One", mock.Anything).Return(errors.New("return an error when checking if readme already exists to force fetching"))
267-
m.On("Insert", chartReadme{fmt.Sprintf("%s/%s-%s", charts[0].Repo.Name, charts[0].Name, cv.Version), ""})
271+
m.On("One", mock.Anything).Return(errors.New("return an error when checking if files already exists to force fetching"))
272+
m.On("Insert", chartFiles{fmt.Sprintf("%s/%s-%s", charts[0].Repo.Name, charts[0].Name, cv.Version), "", ""})
268273
dbSession = mockstore.NewMockSession(&m)
269-
err := fetchAndImportReadme(charts[0].Name, charts[0].Repo, cv)
274+
err := fetchAndImportFiles(charts[0].Name, charts[0].Repo, cv)
270275
assert.NoErr(t, err)
271276
m.AssertExpectations(t)
272277
})
273278

274279
t.Run("valid tarball", func(t *testing.T) {
275280
netClient = &goodTarballClient{c: charts[0]}
276281
m := mock.Mock{}
277-
m.On("One", mock.Anything).Return(errors.New("return an error when checking if readme already exists to force fetching"))
278-
m.On("Insert", chartReadme{fmt.Sprintf("%s/%s-%s", charts[0].Repo.Name, charts[0].Name, cv.Version), testChartReadme})
282+
m.On("One", mock.Anything).Return(errors.New("return an error when checking if files already exists to force fetching"))
283+
m.On("Insert", chartFiles{fmt.Sprintf("%s/%s-%s", charts[0].Repo.Name, charts[0].Name, cv.Version), testChartReadme, testChartValues})
279284
dbSession = mockstore.NewMockSession(&m)
280-
err := fetchAndImportReadme(charts[0].Name, charts[0].Repo, cv)
285+
err := fetchAndImportFiles(charts[0].Name, charts[0].Repo, cv)
281286
assert.NoErr(t, err)
282287
m.AssertExpectations(t)
283288
})
284289

285-
t.Run("readme exists", func(t *testing.T) {
290+
t.Run("file exists", func(t *testing.T) {
286291
m := mock.Mock{}
287-
// don't return an error when checking if readme already exists
292+
// don't return an error when checking if files already exists
288293
m.On("One", mock.Anything).Return(nil)
289294
dbSession = mockstore.NewMockSession(&m)
290-
err := fetchAndImportReadme(charts[0].Name, charts[0].Repo, cv)
295+
err := fetchAndImportFiles(charts[0].Name, charts[0].Repo, cv)
291296
assert.NoErr(t, err)
292297
m.AssertNotCalled(t, "Insert", mock.Anything)
293298
})

src/api/cmd/chart-repo-sync/types.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ type chartVersion struct {
3535
URLs []string
3636
}
3737

38-
type chartReadme struct {
38+
type chartFiles struct {
3939
ID string `bson:"_id"`
4040
Readme string
41+
Values string
4142
}

0 commit comments

Comments
 (0)