feat(helm): optionally hide validation warnings

when doing the following commands:
* `helm repo add`
* `helm repo update`
* `helm search repo`

the new flag `--hide-validation-warnings` will suppress the message
"skipping loading invalid entry for chart"

Closes #9407

Signed-off-by: Russell Cousineau <russell.cousineau@xandr.com>
pull/9604/head
Russell Cousineau 5 years ago
parent a499b4b179
commit a590688b15

@ -109,7 +109,7 @@ func TestDependencyBuildCmd(t *testing.T) {
t.Fatal(err)
}
i, err := repo.LoadIndexFile(filepath.Join(rootDir, "index.yaml"))
i, err := repo.LoadIndexFile(filepath.Join(rootDir, "index.yaml"), false)
if err != nil {
t.Fatal(err)
}

@ -96,7 +96,7 @@ func TestDependencyUpdateCmd(t *testing.T) {
t.Fatal(err)
}
i, err := repo.LoadIndexFile(dir(helmpath.CacheIndexFile("test")))
i, err := repo.LoadIndexFile(dir(helmpath.CacheIndexFile("test")), false)
if err != nil {
t.Fatal(err)
}

@ -150,7 +150,7 @@ func compVersionFlag(chartRef string, toComplete string) ([]string, cobra.ShellC
path := filepath.Join(settings.RepositoryCache, helmpath.CacheIndexFile(repoName))
var versions []string
if indexFile, err := repo.LoadIndexFile(path); err == nil {
if indexFile, err := repo.LoadIndexFile(path, false); err == nil {
for _, details := range indexFile.Entries[chartName] {
version := details.Metadata.Version
if strings.HasPrefix(version, toComplete) {

@ -50,6 +50,7 @@ type repoAddOptions struct {
password string
forceUpdate bool
allowDeprecatedRepos bool
hideValidationWarnings bool
certFile string
keyFile string
@ -91,6 +92,7 @@ func newRepoAddCmd(out io.Writer) *cobra.Command {
f.StringVar(&o.caFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle")
f.BoolVar(&o.insecureSkipTLSverify, "insecure-skip-tls-verify", false, "skip tls certificate checks for the repository")
f.BoolVar(&o.allowDeprecatedRepos, "allow-deprecated-repos", false, "by default, this command will not allow adding official repos that have been permanently deleted. This disables that behavior")
f.BoolVar(&o.hideValidationWarnings, "hide-validation-warnings", false, "hide validation warnings while indexing repository")
return cmd
}
@ -180,7 +182,7 @@ func (o *repoAddOptions) run(out io.Writer) error {
if o.repoCache != "" {
r.CachePath = o.repoCache
}
if _, err := r.DownloadIndexFile(); err != nil {
if _, err := r.DownloadIndexFile(o.hideValidationWarnings); err != nil {
return errors.Wrapf(err, "looks like %q is not a valid chart repository or cannot be reached", o.url)
}

@ -97,7 +97,7 @@ func index(dir, url, mergeTo string) error {
i2 = repo.NewIndexFile()
i2.WriteFile(mergeTo, 0644)
} else {
i2, err = repo.LoadIndexFile(mergeTo)
i2, err = repo.LoadIndexFile(mergeTo, false)
if err != nil {
return errors.Wrap(err, "merge failed")
}

@ -49,7 +49,7 @@ func TestRepoIndexCmd(t *testing.T) {
destIndex := filepath.Join(dir, "index.yaml")
index, err := repo.LoadIndexFile(destIndex)
index, err := repo.LoadIndexFile(destIndex, false)
if err != nil {
t.Fatal(err)
}
@ -90,7 +90,7 @@ func TestRepoIndexCmd(t *testing.T) {
t.Error(err)
}
index, err = repo.LoadIndexFile(destIndex)
index, err = repo.LoadIndexFile(destIndex, false)
if err != nil {
t.Fatal(err)
}
@ -119,7 +119,7 @@ func TestRepoIndexCmd(t *testing.T) {
t.Error(err)
}
index, err = repo.LoadIndexFile(destIndex)
index, err = repo.LoadIndexFile(destIndex, false)
if err != nil {
t.Fatal(err)
}

@ -24,7 +24,6 @@ import (
"github.com/pkg/errors"
"github.com/spf13/cobra"
"helm.sh/helm/v3/cmd/helm/require"
"helm.sh/helm/v3/pkg/getter"
"helm.sh/helm/v3/pkg/repo"
)
@ -37,7 +36,8 @@ Information is cached locally, where it is used by commands like 'helm search'.
var errNoRepositories = errors.New("no repositories found. You must add one before updating")
type repoUpdateOptions struct {
update func([]*repo.ChartRepository, io.Writer)
hideValidationWarnings bool
update func([]*repo.ChartRepository, io.Writer, bool)
repoFile string
repoCache string
}
@ -50,18 +50,21 @@ func newRepoUpdateCmd(out io.Writer) *cobra.Command {
Aliases: []string{"up"},
Short: "update information of available charts locally from chart repositories",
Long: updateDesc,
Args: require.NoArgs,
ValidArgsFunction: noCompletions,
RunE: func(cmd *cobra.Command, args []string) error {
o.repoFile = settings.RepositoryConfig
o.repoCache = settings.RepositoryCache
return o.run(out)
return o.run(out, args)
},
}
f := cmd.Flags()
f.BoolVar(&o.hideValidationWarnings, "hide-validation-warnings", false, "hide validation warnings while indexing repository")
return cmd
}
func (o *repoUpdateOptions) run(out io.Writer) error {
func (o *repoUpdateOptions) run(out io.Writer, args []string) error {
f, err := repo.LoadFile(o.repoFile)
switch {
case isNotExist(err):
@ -84,18 +87,18 @@ func (o *repoUpdateOptions) run(out io.Writer) error {
repos = append(repos, r)
}
o.update(repos, out)
o.update(repos, out, o.hideValidationWarnings)
return nil
}
func updateCharts(repos []*repo.ChartRepository, out io.Writer) {
func updateCharts(repos []*repo.ChartRepository, out io.Writer, hideValidationWarnings bool) {
fmt.Fprintln(out, "Hang tight while we grab the latest from your chart repositories...")
var wg sync.WaitGroup
for _, re := range repos {
wg.Add(1)
go func(re *repo.ChartRepository) {
defer wg.Done()
if _, err := re.DownloadIndexFile(); err != nil {
if _, err := re.DownloadIndexFile(hideValidationWarnings); err != nil {
fmt.Fprintf(out, "...Unable to get an update from the %q chart repository (%s):\n\t%s\n", re.Config.Name, re.Config.URL, err)
} else {
fmt.Fprintf(out, "...Successfully got an update from the %q chart repository\n", re.Config.Name)

@ -35,7 +35,7 @@ func TestUpdateCmd(t *testing.T) {
var out bytes.Buffer
// Instead of using the HTTP updater, we provide our own for this test.
// The TestUpdateCharts test verifies the HTTP behavior independently.
updater := func(repos []*repo.ChartRepository, out io.Writer) {
updater := func(repos []*repo.ChartRepository, out io.Writer, hideValidationWarnings bool) {
for _, re := range repos {
fmt.Fprintln(out, re.Config.Name)
}
@ -44,7 +44,7 @@ func TestUpdateCmd(t *testing.T) {
update: updater,
repoFile: "testdata/repositories.yaml",
}
if err := o.run(&out); err != nil {
if err := o.run(&out, []string{}); err != nil {
t.Fatal(err)
}
@ -71,7 +71,7 @@ func TestUpdateCustomCacheCmd(t *testing.T) {
repoCache: cachePath,
}
b := ioutil.Discard
if err := o.run(b); err != nil {
if err := o.run(b, []string{}); err != nil {
t.Fatal(err)
}
if _, err := os.Stat(filepath.Join(cachePath, "test-index.yaml")); err != nil {
@ -98,7 +98,7 @@ func TestUpdateCharts(t *testing.T) {
}
b := bytes.NewBuffer(nil)
updateCharts([]*repo.ChartRepository{r}, b)
updateCharts([]*repo.ChartRepository{r}, b, false)
got := b.String()
if strings.Contains(got, "Unable to get an update") {

@ -66,6 +66,7 @@ type searchRepoOptions struct {
versions bool
regexp bool
devel bool
hideValidationWarnings bool
version string
maxColWidth uint
repoFile string
@ -91,6 +92,7 @@ func newSearchRepoCmd(out io.Writer) *cobra.Command {
f.BoolVarP(&o.regexp, "regexp", "r", false, "use regular expressions for searching repositories you have added")
f.BoolVarP(&o.versions, "versions", "l", false, "show the long listing, with each version of each chart on its own line, for repositories you have added")
f.BoolVar(&o.devel, "devel", false, "use development versions (alpha, beta, and release candidate releases), too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored")
f.BoolVar(&o.hideValidationWarnings, "hide-validation-warnings", false, "hide validation warnings while indexing repository")
f.StringVar(&o.version, "version", "", "search using semantic versioning constraints on repositories you have added")
f.UintVar(&o.maxColWidth, "max-col-width", 50, "maximum column width for output table")
bindOutputFlag(cmd, &o.outputFormat)
@ -184,7 +186,7 @@ func (o *searchRepoOptions) buildIndex() (*search.Index, error) {
for _, re := range rf.Repositories {
n := re.Name
f := filepath.Join(o.repoCacheDir, helmpath.CacheIndexFile(n))
ind, err := repo.LoadIndexFile(f)
ind, err := repo.LoadIndexFile(f, o.hideValidationWarnings)
if err != nil {
warning("Repo %q is corrupt or missing. Try 'helm repo update'.", n)
warning("%s", err)
@ -276,7 +278,7 @@ func compListChartsOfRepo(repoName string, prefix string) []string {
// installed but before the user does a 'helm repo update' to generate the
// first cached charts file.
path = filepath.Join(settings.RepositoryCache, helmpath.CacheIndexFile(repoName))
if indexFile, err := repo.LoadIndexFile(path); err == nil {
if indexFile, err := repo.LoadIndexFile(path, false); err == nil {
for name := range indexFile.Entries {
fullName := fmt.Sprintf("%s/%s", repoName, name)
if strings.HasPrefix(fullName, prefix) {

@ -113,7 +113,7 @@ func (r *Resolver) Resolve(reqs []*chart.Dependency, repoNames map[string]string
var ok bool
found := true
if !strings.HasPrefix(d.Repository, "oci://") {
repoIndex, err := repo.LoadIndexFile(filepath.Join(r.cachepath, helmpath.CacheIndexFile(repoName)))
repoIndex, err := repo.LoadIndexFile(filepath.Join(r.cachepath, helmpath.CacheIndexFile(repoName)), false)
if err != nil {
return nil, errors.Wrapf(err, "no cached repository for %s found. (try 'helm repo update')", repoName)
}

@ -230,7 +230,7 @@ func (c *ChartDownloader) ResolveChartVersion(ref, version string) (*url.URL, er
// Next, we need to load the index, and actually look up the chart.
idxFile := filepath.Join(c.RepositoryCache, helmpath.CacheIndexFile(r.Config.Name))
i, err := repo.LoadIndexFile(idxFile)
i, err := repo.LoadIndexFile(idxFile, false)
if err != nil {
return u, errors.Wrap(err, "no cached repo found. (try 'helm repo update')")
}
@ -347,7 +347,7 @@ func (c *ChartDownloader) scanReposForURL(u string, rf *repo.File) (*repo.Entry,
}
idxFile := filepath.Join(c.RepositoryCache, helmpath.CacheIndexFile(r.Config.Name))
i, err := repo.LoadIndexFile(idxFile)
i, err := repo.LoadIndexFile(idxFile, false)
if err != nil {
return nil, errors.Wrap(err, "no cached repo found. (try 'helm repo update')")
}

@ -652,7 +652,7 @@ func (m *Manager) parallelRepoUpdate(repos []*repo.Entry) error {
}
wg.Add(1)
go func(r *repo.ChartRepository) {
if _, err := r.DownloadIndexFile(); err != nil {
if _, err := r.DownloadIndexFile(false); err != nil {
// For those dependencies that are not known to helm and using a
// generated key name we display the repo url.
if strings.HasPrefix(r.Config.Name, managerKeyPrefix) {
@ -795,7 +795,7 @@ func (m *Manager) loadChartRepositories() (map[string]*repo.ChartRepository, err
for _, re := range rf.Repositories {
lname := re.Name
idxFile := filepath.Join(m.RepositoryCache, helmpath.CacheIndexFile(lname))
index, err := repo.LoadIndexFile(idxFile)
index, err := repo.LoadIndexFile(idxFile, false)
if err != nil {
return indices, err
}

@ -99,7 +99,7 @@ func (r *ChartRepository) Load() error {
filepath.Walk(r.Config.Name, func(path string, f os.FileInfo, err error) error {
if !f.IsDir() {
if strings.Contains(f.Name(), "-index.yaml") {
i, err := LoadIndexFile(path)
i, err := LoadIndexFile(path, false)
if err != nil {
return err
}
@ -114,7 +114,7 @@ func (r *ChartRepository) Load() error {
}
// DownloadIndexFile fetches the index from a repository.
func (r *ChartRepository) DownloadIndexFile() (string, error) {
func (r *ChartRepository) DownloadIndexFile(hideValidationWarnings bool) (string, error) {
parsedURL, err := url.Parse(r.Config.URL)
if err != nil {
return "", err
@ -139,7 +139,7 @@ func (r *ChartRepository) DownloadIndexFile() (string, error) {
return "", err
}
indexFile, err := loadIndex(index, r.Config.URL)
indexFile, err := loadIndex(index, r.Config.URL, hideValidationWarnings)
if err != nil {
return "", err
}
@ -237,13 +237,13 @@ func FindChartInAuthAndTLSRepoURL(repoURL, username, password, chartName, chartV
if err != nil {
return "", err
}
idx, err := r.DownloadIndexFile()
idx, err := r.DownloadIndexFile(false)
if err != nil {
return "", errors.Wrapf(err, "looks like %q is not a valid chart repository or cannot be reached", repoURL)
}
// Read the index file for the repository to get chart information and return chart URL
repoIndex, err := LoadIndexFile(idx)
repoIndex, err := LoadIndexFile(idx, false)
if err != nil {
return "", err
}

@ -93,7 +93,7 @@ func TestIndex(t *testing.T) {
}
tempIndexPath := filepath.Join(testRepository, indexPath)
actual, err := LoadIndexFile(tempIndexPath)
actual, err := LoadIndexFile(tempIndexPath, false)
defer os.Remove(tempIndexPath) // clean up
if err != nil {
t.Errorf("Error loading index file %v", err)
@ -105,7 +105,7 @@ func TestIndex(t *testing.T) {
if err != nil {
t.Errorf("Error performing re-index: %s\n", err)
}
second, err := LoadIndexFile(tempIndexPath)
second, err := LoadIndexFile(tempIndexPath, false)
if err != nil {
t.Errorf("Error re-loading index file %v", err)
}
@ -156,7 +156,7 @@ func TestIndexCustomSchemeDownload(t *testing.T) {
}
defer os.Remove(tempIndexFile.Name())
idx, err := repo.DownloadIndexFile()
idx, err := repo.DownloadIndexFile(false)
if err != nil {
t.Fatalf("Failed to download index file to %s: %v", idx, err)
}

@ -101,12 +101,12 @@ func NewIndexFile() *IndexFile {
}
// LoadIndexFile takes a file at the given path and returns an IndexFile object
func LoadIndexFile(path string) (*IndexFile, error) {
func LoadIndexFile(path string, hideValidationWarnings bool) (*IndexFile, error) {
b, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
i, err := loadIndex(b, path)
i, err := loadIndex(b, path, hideValidationWarnings)
if err != nil {
return nil, errors.Wrapf(err, "error loading %s", path)
}
@ -324,7 +324,7 @@ func IndexDirectory(dir, baseURL string) (*IndexFile, error) {
//
// The source parameter is only used for logging.
// This will fail if API Version is not set (ErrNoAPIVersion) or if the unmarshal fails.
func loadIndex(data []byte, source string) (*IndexFile, error) {
func loadIndex(data []byte, source string, hideValidationWarnings bool) (*IndexFile, error) {
i := &IndexFile{}
if err := yaml.UnmarshalStrict(data, i); err != nil {
return i, err
@ -336,7 +336,9 @@ func loadIndex(data []byte, source string) (*IndexFile, error) {
cvs[idx].APIVersion = chart.APIVersionV1
}
if err := cvs[idx].Validate(); err != nil {
if !hideValidationWarnings {
log.Printf("skipping loading invalid entry for chart %q %q from %s: %s", name, cvs[idx].Version, source, err)
}
cvs = append(cvs[:idx], cvs[idx+1:]...)
}
}

@ -136,7 +136,7 @@ func TestLoadIndex(t *testing.T) {
tc := tc
t.Run(tc.Name, func(t *testing.T) {
t.Parallel()
i, err := LoadIndexFile(tc.Filename)
i, err := LoadIndexFile(tc.Filename, false)
if err != nil {
t.Fatal(err)
}
@ -147,13 +147,13 @@ func TestLoadIndex(t *testing.T) {
// TestLoadIndex_Duplicates is a regression to make sure that we don't non-deterministically allow duplicate packages.
func TestLoadIndex_Duplicates(t *testing.T) {
if _, err := loadIndex([]byte(indexWithDuplicates), "indexWithDuplicates"); err == nil {
if _, err := loadIndex([]byte(indexWithDuplicates), "indexWithDuplicates", false); err == nil {
t.Errorf("Expected an error when duplicate entries are present")
}
}
func TestLoadIndexFileAnnotations(t *testing.T) {
i, err := LoadIndexFile(annotationstestfile)
i, err := LoadIndexFile(annotationstestfile, false)
if err != nil {
t.Fatal(err)
}
@ -168,7 +168,7 @@ func TestLoadIndexFileAnnotations(t *testing.T) {
}
func TestLoadUnorderedIndex(t *testing.T) {
i, err := LoadIndexFile(unorderedTestfile)
i, err := LoadIndexFile(unorderedTestfile, false)
if err != nil {
t.Fatal(err)
}
@ -230,7 +230,7 @@ func TestDownloadIndexFile(t *testing.T) {
t.Errorf("Problem creating chart repository from %s: %v", testRepo, err)
}
idx, err := r.DownloadIndexFile()
idx, err := r.DownloadIndexFile(false)
if err != nil {
t.Fatalf("Failed to download index file to %s: %#v", idx, err)
}
@ -239,7 +239,7 @@ func TestDownloadIndexFile(t *testing.T) {
t.Fatalf("error finding created index file: %#v", err)
}
i, err := LoadIndexFile(idx)
i, err := LoadIndexFile(idx, false)
if err != nil {
t.Fatalf("Index %q failed to parse: %s", testfile, err)
}
@ -283,7 +283,7 @@ func TestDownloadIndexFile(t *testing.T) {
t.Errorf("Problem creating chart repository from %s: %v", testRepo, err)
}
idx, err := r.DownloadIndexFile()
idx, err := r.DownloadIndexFile(false)
if err != nil {
t.Fatalf("Failed to download index file to %s: %#v", idx, err)
}
@ -292,7 +292,7 @@ func TestDownloadIndexFile(t *testing.T) {
t.Fatalf("error finding created index file: %#v", err)
}
i, err := LoadIndexFile(idx)
i, err := LoadIndexFile(idx, false)
if err != nil {
t.Fatalf("Index %q failed to parse: %s", testfile, err)
}

Loading…
Cancel
Save