diff --git a/cmd/helm/docs.go b/cmd/helm/docs.go index dd0cf60c7..658f18696 100644 --- a/cmd/helm/docs.go +++ b/cmd/helm/docs.go @@ -22,7 +22,6 @@ import ( "path/filepath" "strings" - "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/cobra/doc" "golang.org/x/text/cases" @@ -99,6 +98,6 @@ func (o *docsOptions) run(_ io.Writer) error { case "bash": return o.topCmd.GenBashCompletionFile(filepath.Join(o.dest, "completions.bash")) default: - return errors.Errorf("unknown doc type %q. Try 'markdown' or 'man'", o.docTypeString) + return fmt.Errorf("unknown doc type %q. Try 'markdown' or 'man'", o.docTypeString) } } diff --git a/cmd/helm/install.go b/cmd/helm/install.go index 1e451486b..45dcf7d52 100644 --- a/cmd/helm/install.go +++ b/cmd/helm/install.go @@ -18,6 +18,7 @@ package main import ( "context" + "errors" "fmt" "io" "log" @@ -26,7 +27,6 @@ import ( "syscall" "time" - "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -155,7 +155,7 @@ func newInstallCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { } rel, err := runInstall(args, client, valueOpts, out) if err != nil { - return errors.Wrap(err, "INSTALLATION FAILED") + return fmt.Errorf("INSTALLATION FAILED: %w", err) } return outfmt.Write(out, &statusPrinter{rel, settings.Debug, false, false, false, client.HideNotes}) @@ -265,7 +265,7 @@ func runInstall(args []string, client *action.Install, valueOpts *values.Options // As of Helm 2.4.0, this is treated as a stopping condition: // https://github.com/helm/helm/issues/2209 if err := action.CheckDependencies(chartRequested, req); err != nil { - err = errors.Wrap(err, "An error occurred while checking for chart dependencies. You may need to run `helm dependency build` to fetch missing dependencies") + err = fmt.Errorf("An error occurred while checking for chart dependencies. You may need to run `helm dependency build` to fetch missing dependencies: %w", err) if client.DependencyUpdate { man := &downloader.Manager{ Out: out, @@ -283,7 +283,7 @@ func runInstall(args []string, client *action.Install, valueOpts *values.Options } // Reload the chart with the updated Chart.lock file. if chartRequested, err = loader.Load(cp); err != nil { - return nil, errors.Wrap(err, "failed reloading chart after repo update") + return nil, fmt.Errorf("failed reloading chart after repo update: %w", err) } } else { return nil, err @@ -324,7 +324,7 @@ func checkIfInstallable(ch *chart.Chart) error { case "", "application": return nil } - return errors.Errorf("%s charts are not installable", ch.Metadata.Type) + return fmt.Errorf("%s charts are not installable", ch.Metadata.Type) } // Provide dynamic auto-completion for the install and template commands diff --git a/cmd/helm/lint.go b/cmd/helm/lint.go index 4c5e24149..216cdf077 100644 --- a/cmd/helm/lint.go +++ b/cmd/helm/lint.go @@ -17,13 +17,13 @@ limitations under the License. package main import ( + "errors" "fmt" "io" "os" "path/filepath" "strings" - "github.com/pkg/errors" "github.com/spf13/cobra" "helm.sh/helm/v3/pkg/action" diff --git a/cmd/helm/load_plugins.go b/cmd/helm/load_plugins.go index 5ae638124..cbf382862 100644 --- a/cmd/helm/load_plugins.go +++ b/cmd/helm/load_plugins.go @@ -27,7 +27,6 @@ import ( "strings" "syscall" - "github.com/pkg/errors" "github.com/spf13/cobra" "sigs.k8s.io/yaml" @@ -50,7 +49,6 @@ type pluginError struct { // to inspect its environment and then add commands to the base command // as it finds them. func loadPlugins(baseCmd *cobra.Command, out io.Writer) { - // If HELM_NO_PLUGINS is set to 1, do not load plugins. if os.Getenv("HELM_NO_PLUGINS") == "1" { return @@ -87,7 +85,7 @@ func loadPlugins(baseCmd *cobra.Command, out io.Writer) { main, argv, prepCmdErr := plug.PrepareCommand(u) if prepCmdErr != nil { os.Stderr.WriteString(prepCmdErr.Error()) - return errors.Errorf("plugin %q exited with error", md.Name) + return fmt.Errorf("plugin %q exited with error", md.Name) } return callPluginExecutable(md.Name, main, argv, out) @@ -139,7 +137,7 @@ func callPluginExecutable(pluginName string, main string, argv []string, out io. os.Stderr.Write(eerr.Stderr) status := eerr.Sys().(syscall.WaitStatus) return pluginError{ - error: errors.Errorf("plugin %q exited with error", pluginName), + error: fmt.Errorf("plugin %q exited with error", pluginName), code: status.ExitStatus(), } } diff --git a/cmd/helm/package.go b/cmd/helm/package.go index b96110ee8..236a66188 100644 --- a/cmd/helm/package.go +++ b/cmd/helm/package.go @@ -17,12 +17,12 @@ limitations under the License. package main import ( + "errors" "fmt" "io" "os" "path/filepath" - "github.com/pkg/errors" "github.com/spf13/cobra" "helm.sh/helm/v3/pkg/action" @@ -57,7 +57,7 @@ func newPackageCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { Long: packageDesc, RunE: func(_ *cobra.Command, args []string) error { if len(args) == 0 { - return errors.Errorf("need at least one argument, the path to the chart") + return fmt.Errorf("need at least one argument, the path to the chart") } if client.Sign { if client.Key == "" { diff --git a/cmd/helm/plugin.go b/cmd/helm/plugin.go index 8e1044f54..23716cf1d 100644 --- a/cmd/helm/plugin.go +++ b/cmd/helm/plugin.go @@ -16,11 +16,11 @@ limitations under the License. package main import ( + "fmt" "io" "os" "os/exec" - "github.com/pkg/errors" "github.com/spf13/cobra" "helm.sh/helm/v3/pkg/plugin" @@ -64,7 +64,7 @@ func runHook(p *plugin.Plugin, event string) error { if err := prog.Run(); err != nil { if eerr, ok := err.(*exec.ExitError); ok { os.Stderr.Write(eerr.Stderr) - return errors.Errorf("plugin %s hook for %q exited with error", event, p.Metadata.Name) + return fmt.Errorf("plugin %s hook for %q exited with error", event, p.Metadata.Name) } return err } diff --git a/cmd/helm/plugin_install.go b/cmd/helm/plugin_install.go index 0a96954f9..9b3df38b1 100644 --- a/cmd/helm/plugin_install.go +++ b/cmd/helm/plugin_install.go @@ -19,7 +19,6 @@ import ( "fmt" "io" - "github.com/pkg/errors" "github.com/spf13/cobra" "helm.sh/helm/v3/cmd/helm/require" @@ -82,7 +81,7 @@ func (o *pluginInstallOptions) run(out io.Writer) error { debug("loading plugin from %s", i.Path()) p, err := plugin.LoadDir(i.Path()) if err != nil { - return errors.Wrap(err, "plugin is installed but unusable") + return fmt.Errorf("plugin is installed but unusable: %w", err) } if err := runHook(p, plugin.Install); err != nil { diff --git a/cmd/helm/plugin_uninstall.go b/cmd/helm/plugin_uninstall.go index 607baab2e..b9148dd86 100644 --- a/cmd/helm/plugin_uninstall.go +++ b/cmd/helm/plugin_uninstall.go @@ -16,12 +16,11 @@ limitations under the License. package main import ( + "errors" "fmt" "io" "os" - "strings" - "github.com/pkg/errors" "github.com/spf13/cobra" "helm.sh/helm/v3/pkg/plugin" @@ -65,20 +64,20 @@ func (o *pluginUninstallOptions) run(out io.Writer) error { if err != nil { return err } - var errorPlugins []string + var errorPlugins []error for _, name := range o.names { if found := findPlugin(plugins, name); found != nil { if err := uninstallPlugin(found); err != nil { - errorPlugins = append(errorPlugins, fmt.Sprintf("Failed to uninstall plugin %s, got error (%v)", name, err)) + errorPlugins = append(errorPlugins, fmt.Errorf("Failed to uninstall plugin %s, got error (%v)", name, err)) } else { fmt.Fprintf(out, "Uninstalled plugin: %s\n", name) } } else { - errorPlugins = append(errorPlugins, fmt.Sprintf("Plugin: %s not found", name)) + errorPlugins = append(errorPlugins, fmt.Errorf("Plugin: %s not found", name)) } } if len(errorPlugins) > 0 { - return errors.Errorf(strings.Join(errorPlugins, "\n")) + return errors.Join(errorPlugins...) } return nil } diff --git a/cmd/helm/plugin_update.go b/cmd/helm/plugin_update.go index 3f6d963fb..54d290597 100644 --- a/cmd/helm/plugin_update.go +++ b/cmd/helm/plugin_update.go @@ -16,12 +16,11 @@ limitations under the License. package main import ( + "errors" "fmt" "io" "path/filepath" - "strings" - "github.com/pkg/errors" "github.com/spf13/cobra" "helm.sh/helm/v3/pkg/plugin" @@ -67,21 +66,21 @@ func (o *pluginUpdateOptions) run(out io.Writer) error { if err != nil { return err } - var errorPlugins []string + var errorPlugins []error for _, name := range o.names { if found := findPlugin(plugins, name); found != nil { if err := updatePlugin(found); err != nil { - errorPlugins = append(errorPlugins, fmt.Sprintf("Failed to update plugin %s, got error (%v)", name, err)) + errorPlugins = append(errorPlugins, fmt.Errorf("Failed to update plugin %s, got error (%v)", name, err)) } else { fmt.Fprintf(out, "Updated plugin: %s\n", name) } } else { - errorPlugins = append(errorPlugins, fmt.Sprintf("Plugin: %s not found", name)) + errorPlugins = append(errorPlugins, fmt.Errorf("Plugin: %s not found", name)) } } if len(errorPlugins) > 0 { - return errors.Errorf(strings.Join(errorPlugins, "\n")) + return errors.Join(errorPlugins...) } return nil } diff --git a/cmd/helm/repo.go b/cmd/helm/repo.go index ad6ceaa8f..11121be5b 100644 --- a/cmd/helm/repo.go +++ b/cmd/helm/repo.go @@ -17,10 +17,10 @@ limitations under the License. package main import ( + "errors" "io" - "os" + "io/fs" - "github.com/pkg/errors" "github.com/spf13/cobra" "helm.sh/helm/v3/cmd/helm/require" @@ -50,5 +50,5 @@ func newRepoCmd(out io.Writer) *cobra.Command { } func isNotExist(err error) bool { - return os.IsNotExist(errors.Cause(err)) + return errors.Is(err, fs.ErrNotExist) } diff --git a/cmd/helm/repo_add.go b/cmd/helm/repo_add.go index 6a8a70a0f..967e98bea 100644 --- a/cmd/helm/repo_add.go +++ b/cmd/helm/repo_add.go @@ -26,7 +26,6 @@ import ( "time" "github.com/gofrs/flock" - "github.com/pkg/errors" "github.com/spf13/cobra" "golang.org/x/term" "sigs.k8s.io/yaml" @@ -183,7 +182,7 @@ func (o *repoAddOptions) run(out io.Writer) error { // Check if the repo name is legal if strings.Contains(o.name, "/") { - return errors.Errorf("repository name (%s) contains '/', please specify a different name without '/'", o.name) + return fmt.Errorf("repository name (%s) contains '/', please specify a different name without '/'", o.name) } // If the repo exists do one of two things: @@ -192,10 +191,9 @@ func (o *repoAddOptions) run(out io.Writer) error { if !o.forceUpdate && f.Has(o.name) { existing := f.Get(o.name) if c != *existing { - // The input coming in for the name is different from what is already // configured. Return an error. - return errors.Errorf("repository name (%s) already exists, please specify a different name", o.name) + return fmt.Errorf("repository name (%s) already exists, please specify a different name", o.name) } // The add is idempotent so do nothing @@ -212,12 +210,12 @@ func (o *repoAddOptions) run(out io.Writer) error { r.CachePath = o.repoCache } if _, err := r.DownloadIndexFile(); err != nil { - return errors.Wrapf(err, "looks like %q is not a valid chart repository or cannot be reached", o.url) + return fmt.Errorf("looks like %q is not a valid chart repository or cannot be reached: %w", o.url, err) } f.Update(&c) - if err := f.WriteFile(o.repoFile, 0600); err != nil { + if err := f.WriteFile(o.repoFile, 0o600); err != nil { return err } fmt.Fprintf(out, "%q has been added to your repositories\n", o.name) diff --git a/cmd/helm/repo_index.go b/cmd/helm/repo_index.go index a61062e0e..06bd6b4c6 100644 --- a/cmd/helm/repo_index.go +++ b/cmd/helm/repo_index.go @@ -17,11 +17,11 @@ limitations under the License. package main import ( + "fmt" "io" "os" "path/filepath" - "github.com/pkg/errors" "github.com/spf13/cobra" "helm.sh/helm/v3/cmd/helm/require" @@ -103,7 +103,7 @@ func index(dir, url, mergeTo string, json bool) error { } else { i2, err = repo.LoadIndexFile(mergeTo) if err != nil { - return errors.Wrap(err, "merge failed") + return fmt.Errorf("merge failed: %w", err) } } i.Merge(i2) @@ -114,7 +114,7 @@ func index(dir, url, mergeTo string, json bool) error { func writeIndexFile(i *repo.IndexFile, out string, json bool) error { if json { - return i.WriteJSONFile(out, 0644) + return i.WriteJSONFile(out, 0o644) } - return i.WriteFile(out, 0644) + return i.WriteFile(out, 0o644) } diff --git a/cmd/helm/repo_list.go b/cmd/helm/repo_list.go index 6c0b970be..7ac83b489 100644 --- a/cmd/helm/repo_list.go +++ b/cmd/helm/repo_list.go @@ -17,11 +17,11 @@ limitations under the License. package main import ( + "errors" "fmt" "io" "github.com/gosuri/uitable" - "github.com/pkg/errors" "github.com/spf13/cobra" "helm.sh/helm/v3/cmd/helm/require" diff --git a/cmd/helm/repo_remove.go b/cmd/helm/repo_remove.go index 82a235fec..1b6b90bfd 100644 --- a/cmd/helm/repo_remove.go +++ b/cmd/helm/repo_remove.go @@ -17,12 +17,12 @@ limitations under the License. package main import ( + "errors" "fmt" "io" "os" "path/filepath" - "github.com/pkg/errors" "github.com/spf13/cobra" "helm.sh/helm/v3/cmd/helm/require" @@ -65,7 +65,7 @@ func (o *repoRemoveOptions) run(out io.Writer) error { for _, name := range o.names { if !r.Remove(name) { - return errors.Errorf("no repo named %q found", name) + return fmt.Errorf("no repo named %q found", name) } if err := r.WriteFile(o.repoFile, 0600); err != nil { return err @@ -90,7 +90,7 @@ func removeRepoCache(root, name string) error { if _, err := os.Stat(idx); os.IsNotExist(err) { return nil } else if err != nil { - return errors.Wrapf(err, "can't remove index file %s", idx) + return fmt.Errorf("can't remove index file %s: %w", idx, err) } return os.Remove(idx) } diff --git a/cmd/helm/repo_update.go b/cmd/helm/repo_update.go index 8d5f532f1..186f7c3b4 100644 --- a/cmd/helm/repo_update.go +++ b/cmd/helm/repo_update.go @@ -17,11 +17,11 @@ limitations under the License. package main import ( + "errors" "fmt" "io" "sync" - "github.com/pkg/errors" "github.com/spf13/cobra" "helm.sh/helm/v3/cmd/helm/require" @@ -83,7 +83,7 @@ func (o *repoUpdateOptions) run(out io.Writer) error { case isNotExist(err): return errNoRepositories case err != nil: - return errors.Wrapf(err, "failed loading file: %s", o.repoFile) + return fmt.Errorf("failed loading file: %s: %w", o.repoFile, err) case len(f.Repositories) == 0: return errNoRepositories } @@ -151,7 +151,7 @@ func checkRequestedRepos(requestedRepos []string, validRepos []*repo.Entry) erro } } if !found { - return errors.Errorf("no repositories found matching '%s'. Nothing will be updated", requestedRepo) + return fmt.Errorf("no repositories found matching '%s'. Nothing will be updated", requestedRepo) } } return nil diff --git a/cmd/helm/require/args.go b/cmd/helm/require/args.go index cfa8a0169..f5e0888f1 100644 --- a/cmd/helm/require/args.go +++ b/cmd/helm/require/args.go @@ -16,14 +16,15 @@ limitations under the License. package require import ( - "github.com/pkg/errors" + "fmt" + "github.com/spf13/cobra" ) // NoArgs returns an error if any args are included. func NoArgs(cmd *cobra.Command, args []string) error { if len(args) > 0 { - return errors.Errorf( + return fmt.Errorf( "%q accepts no arguments\n\nUsage: %s", cmd.CommandPath(), cmd.UseLine(), @@ -36,7 +37,7 @@ func NoArgs(cmd *cobra.Command, args []string) error { func ExactArgs(n int) cobra.PositionalArgs { return func(cmd *cobra.Command, args []string) error { if len(args) != n { - return errors.Errorf( + return fmt.Errorf( "%q requires %d %s\n\nUsage: %s", cmd.CommandPath(), n, @@ -52,7 +53,7 @@ func ExactArgs(n int) cobra.PositionalArgs { func MaximumNArgs(n int) cobra.PositionalArgs { return func(cmd *cobra.Command, args []string) error { if len(args) > n { - return errors.Errorf( + return fmt.Errorf( "%q accepts at most %d %s\n\nUsage: %s", cmd.CommandPath(), n, @@ -68,7 +69,7 @@ func MaximumNArgs(n int) cobra.PositionalArgs { func MinimumNArgs(n int) cobra.PositionalArgs { return func(cmd *cobra.Command, args []string) error { if len(args) < n { - return errors.Errorf( + return fmt.Errorf( "%q requires at least %d %s\n\nUsage: %s", cmd.CommandPath(), n, diff --git a/cmd/helm/search_hub.go b/cmd/helm/search_hub.go index d9482f67a..7b777328d 100644 --- a/cmd/helm/search_hub.go +++ b/cmd/helm/search_hub.go @@ -22,7 +22,6 @@ import ( "strings" "github.com/gosuri/uitable" - "github.com/pkg/errors" "github.com/spf13/cobra" "helm.sh/helm/v3/internal/monocular" @@ -83,7 +82,7 @@ func newSearchHubCmd(out io.Writer) *cobra.Command { func (o *searchHubOptions) run(out io.Writer, args []string) error { c, err := monocular.New(o.searchEndpoint) if err != nil { - return errors.Wrap(err, fmt.Sprintf("unable to create connection to %q", o.searchEndpoint)) + return fmt.Errorf("unable to create connection to %q: %w", o.searchEndpoint, err) } q := strings.Join(args, " ") diff --git a/cmd/helm/search_repo.go b/cmd/helm/search_repo.go index 3acd9ab4b..af92c5f21 100644 --- a/cmd/helm/search_repo.go +++ b/cmd/helm/search_repo.go @@ -19,6 +19,7 @@ package main import ( "bufio" "bytes" + "errors" "fmt" "io" "os" @@ -27,7 +28,6 @@ import ( "github.com/Masterminds/semver/v3" "github.com/gosuri/uitable" - "github.com/pkg/errors" "github.com/spf13/cobra" "helm.sh/helm/v3/cmd/helm/search" @@ -152,7 +152,7 @@ func (o *searchRepoOptions) applyConstraint(res []*search.Result) ([]*search.Res constraint, err := semver.NewConstraint(o.version) if err != nil { - return res, errors.Wrap(err, "an invalid version/constraint format") + return res, fmt.Errorf("an invalid version/constraint format: %w", err) } data := res[:0] diff --git a/cmd/helm/status.go b/cmd/helm/status.go index 725b3f367..636528675 100644 --- a/cmd/helm/status.go +++ b/cmd/helm/status.go @@ -144,7 +144,7 @@ func (s statusPrinter) WriteTable(out io.Writer) error { _, _ = fmt.Fprintf(out, "DESCRIPTION: %s\n", s.release.Info.Description) } - if s.showResources && s.release.Info.Resources != nil && len(s.release.Info.Resources) > 0 { + if len(s.release.Info.Resources) > 0 { buf := new(bytes.Buffer) printFlags := get.NewHumanPrintFlags() typePrinter, _ := printFlags.ToPrinter("") diff --git a/cmd/helm/upgrade.go b/cmd/helm/upgrade.go index 108550cbf..ed25bc7d7 100644 --- a/cmd/helm/upgrade.go +++ b/cmd/helm/upgrade.go @@ -26,7 +26,6 @@ import ( "syscall" "time" - "github.com/pkg/errors" "github.com/spf13/cobra" "helm.sh/helm/v3/cmd/helm/require" @@ -193,7 +192,7 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { } if req := ch.Metadata.Dependencies; req != nil { if err := action.CheckDependencies(ch, req); err != nil { - err = errors.Wrap(err, "An error occurred while checking for chart dependencies. You may need to run `helm dependency build` to fetch missing dependencies") + err = fmt.Errorf("An error occurred while checking for chart dependencies. You may need to run `helm dependency build` to fetch missing dependencies: %w", err) if client.DependencyUpdate { man := &downloader.Manager{ Out: out, @@ -210,7 +209,7 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { } // Reload the chart with the updated Chart.lock file. if ch, err = loader.Load(chartPath); err != nil { - return errors.Wrap(err, "failed reloading chart after repo update") + return fmt.Errorf("failed reloading chart after repo update: %w", err) } } else { return err @@ -240,7 +239,7 @@ func newUpgradeCmd(cfg *action.Configuration, out io.Writer) *cobra.Command { rel, err := client.RunWithContext(ctx, args[0], ch, vals) if err != nil { - return errors.Wrap(err, "UPGRADE FAILED") + return fmt.Errorf("UPGRADE FAILED: %w", err) } if outfmt == output.Table { diff --git a/internal/resolver/resolver.go b/internal/resolver/resolver.go index b6f45da9e..73a36e9bb 100644 --- a/internal/resolver/resolver.go +++ b/internal/resolver/resolver.go @@ -25,7 +25,6 @@ import ( "time" "github.com/Masterminds/semver/v3" - "github.com/pkg/errors" "helm.sh/helm/v3/pkg/chart" "helm.sh/helm/v3/pkg/chart/loader" @@ -60,7 +59,7 @@ func (r *Resolver) Resolve(reqs []*chart.Dependency, repoNames map[string]string for i, d := range reqs { constraint, err := semver.NewConstraint(d.Version) if err != nil { - return nil, errors.Wrapf(err, "dependency %q has an invalid version/constraint format", d.Name) + return nil, fmt.Errorf("dependency %q has an invalid version/constraint format: %w", d.Name, err) } if d.Repository == "" { @@ -124,12 +123,12 @@ func (r *Resolver) Resolve(reqs []*chart.Dependency, repoNames map[string]string if !registry.IsOCI(d.Repository) { repoIndex, err := repo.LoadIndexFile(filepath.Join(r.cachepath, helmpath.CacheIndexFile(repoName))) if err != nil { - return nil, errors.Wrapf(err, "no cached repository for %s found. (try 'helm repo update')", repoName) + return nil, fmt.Errorf("no cached repository for %s found. (try 'helm repo update'): %w", repoName, err) } vs, ok = repoIndex.Entries[d.Name] if !ok { - return nil, errors.Errorf("%s chart not found in repo %s", d.Name, d.Repository) + return nil, fmt.Errorf("%s chart not found in repo %s", d.Name, d.Repository) } found = false } else { @@ -151,7 +150,7 @@ func (r *Resolver) Resolve(reqs []*chart.Dependency, repoNames map[string]string ref := fmt.Sprintf("%s/%s", strings.TrimPrefix(d.Repository, fmt.Sprintf("%s://", registry.OCIScheme)), d.Name) tags, err := r.registryClient.Tags(ref) if err != nil { - return nil, errors.Wrapf(err, "could not retrieve list of tags for repository %s", d.Repository) + return nil, fmt.Errorf("could not retrieve list of tags for repository %s: %w", d.Repository, err) } vs = make(repo.ChartVersions, len(tags)) @@ -192,7 +191,7 @@ func (r *Resolver) Resolve(reqs []*chart.Dependency, repoNames map[string]string } } if len(missing) > 0 { - return nil, errors.Errorf("can't get a valid version for %d subchart(s): %s. Make sure a matching chart version exists in the repo, or change the version constraint in Chart.yaml", len(missing), strings.Join(missing, ", ")) + return nil, fmt.Errorf("can't get a valid version for %d subchart(s): %s. Make sure a matching chart version exists in the repo, or change the version constraint in Chart.yaml", len(missing), strings.Join(missing, ", ")) } digest, err := HashReq(reqs, locked) @@ -253,7 +252,7 @@ func GetLocalPath(repo, chartpath string) (string, error) { } if _, err = os.Stat(depPath); os.IsNotExist(err) { - return "", errors.Errorf("directory %s not found", depPath) + return "", fmt.Errorf("directory %s not found", depPath) } else if err != nil { return "", err } diff --git a/internal/sympath/walk.go b/internal/sympath/walk.go index 6b221fb6c..5ee988ede 100644 --- a/internal/sympath/walk.go +++ b/internal/sympath/walk.go @@ -21,12 +21,11 @@ limitations under the License. package sympath import ( + "fmt" "log" "os" "path/filepath" "sort" - - "github.com/pkg/errors" ) // Walk walks the file tree rooted at root, calling walkFn for each file or directory @@ -69,9 +68,9 @@ func symwalk(path string, info os.FileInfo, walkFn filepath.WalkFunc) error { if IsSymlink(info) { resolved, err := filepath.EvalSymlinks(path) if err != nil { - return errors.Wrapf(err, "error evaluating symlink %s", path) + return fmt.Errorf("error evaluating symlink %s: %w", path, err) } - //This log message is to highlight a symlink that is being used within a chart, symlinks can be used for nefarious reasons. + // This log message is to highlight a symlink that is being used within a chart, symlinks can be used for nefarious reasons. log.Printf("found symbolic link in path: %s resolves to %s. Contents of linked file included and used", path, resolved) if info, err = os.Lstat(resolved); err != nil { return err diff --git a/internal/test/test.go b/internal/test/test.go index e6821282c..53eb1c34b 100644 --- a/internal/test/test.go +++ b/internal/test/test.go @@ -19,10 +19,9 @@ package test import ( "bytes" "flag" + "fmt" "os" "path/filepath" - - "github.com/pkg/errors" ) // UpdateGolden writes out the golden files with the latest values, rather than failing the test. @@ -75,11 +74,11 @@ func compare(actual []byte, filename string) error { expected, err := os.ReadFile(filename) if err != nil { - return errors.Wrapf(err, "unable to read testdata %s", filename) + return fmt.Errorf("unable to read testdata %s: %w", filename, err) } expected = normalize(expected) if !bytes.Equal(expected, actual) { - return errors.Errorf("does not match golden file %s\n\nWANT:\n'%s'\n\nGOT:\n'%s'", filename, expected, actual) + return fmt.Errorf("does not match golden file %s\n\nWANT:\n'%s'\n\nGOT:\n'%s'", filename, expected, actual) } return nil } diff --git a/internal/third_party/dep/fs/fs.go b/internal/third_party/dep/fs/fs.go index d29bb5f87..9491fed6e 100644 --- a/internal/third_party/dep/fs/fs.go +++ b/internal/third_party/dep/fs/fs.go @@ -32,13 +32,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package fs import ( + "errors" + "fmt" "io" "os" "path/filepath" "runtime" "syscall" - - "github.com/pkg/errors" ) // fs contains a copy of a few functions from dep tool code to avoid a dependency on golang/dep. @@ -51,7 +51,7 @@ import ( func RenameWithFallback(src, dst string) error { _, err := os.Stat(src) if err != nil { - return errors.Wrapf(err, "cannot stat %s", src) + return fmt.Errorf("cannot stat %s: %w", src, err) } err = os.Rename(src, dst) @@ -69,20 +69,24 @@ func renameByCopy(src, dst string) error { if dir, _ := IsDir(src); dir { cerr = CopyDir(src, dst) if cerr != nil { - cerr = errors.Wrap(cerr, "copying directory failed") + cerr = fmt.Errorf("copying directory failed: %w", cerr) } } else { cerr = copyFile(src, dst) if cerr != nil { - cerr = errors.Wrap(cerr, "copying file failed") + cerr = fmt.Errorf("copying file failed: %w", cerr) } } if cerr != nil { - return errors.Wrapf(cerr, "rename fallback failed: cannot rename %s to %s", src, dst) + return fmt.Errorf("rename fallback failed: cannot rename %s to %s: %w", src, dst, cerr) + } + + if cerr = os.RemoveAll(src); cerr != nil { + return fmt.Errorf("cannot delete %s: %w", src, cerr) } - return errors.Wrapf(os.RemoveAll(src), "cannot delete %s", src) + return nil } var ( @@ -115,12 +119,12 @@ func CopyDir(src, dst string) error { } if err = os.MkdirAll(dst, fi.Mode()); err != nil { - return errors.Wrapf(err, "cannot mkdir %s", dst) + return fmt.Errorf("cannot mkdir %s: %w", dst, err) } entries, err := os.ReadDir(src) if err != nil { - return errors.Wrapf(err, "cannot read directory %s", dst) + return fmt.Errorf("cannot read directory %s: %w", dst, err) } for _, entry := range entries { @@ -129,13 +133,13 @@ func CopyDir(src, dst string) error { if entry.IsDir() { if err = CopyDir(srcPath, dstPath); err != nil { - return errors.Wrap(err, "copying directory failed") + return fmt.Errorf("copying directory failed: %w", err) } } else { // This will include symlinks, which is what we want when // copying things. if err = copyFile(srcPath, dstPath); err != nil { - return errors.Wrap(err, "copying file failed") + return fmt.Errorf("copying file failed: %w", err) } } } @@ -149,7 +153,7 @@ func CopyDir(src, dst string) error { // of the source file. The file mode will be copied from the source. func copyFile(src, dst string) (err error) { if sym, err := IsSymlink(src); err != nil { - return errors.Wrap(err, "symlink check failed") + return fmt.Errorf("symlink check failed: %w", err) } else if sym { if err := cloneSymlink(src, dst); err != nil { if runtime.GOOS == "windows" { @@ -226,7 +230,7 @@ func IsDir(name string) (bool, error) { return false, err } if !fi.IsDir() { - return false, errors.Errorf("%q is not a directory", name) + return false, fmt.Errorf("%q is not a directory", name) } return true, nil } diff --git a/internal/third_party/dep/fs/rename.go b/internal/third_party/dep/fs/rename.go index a3e5e56a6..662accffa 100644 --- a/internal/third_party/dep/fs/rename.go +++ b/internal/third_party/dep/fs/rename.go @@ -34,10 +34,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package fs import ( + "fmt" "os" "syscall" - - "github.com/pkg/errors" ) // renameFallback attempts to determine the appropriate fallback to failed rename @@ -51,7 +50,7 @@ func renameFallback(err error, src, dst string) error { if !ok { return err } else if terr.Err != syscall.EXDEV { - return errors.Wrapf(terr, "link error: cannot rename %s to %s", src, dst) + return fmt.Errorf("link error: cannot rename %s to %s: %w", src, dst, err) } return renameByCopy(src, dst) diff --git a/internal/third_party/dep/fs/rename_windows.go b/internal/third_party/dep/fs/rename_windows.go index a377720a6..3c8e64883 100644 --- a/internal/third_party/dep/fs/rename_windows.go +++ b/internal/third_party/dep/fs/rename_windows.go @@ -34,10 +34,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package fs import ( + "errors" "os" "syscall" - - "github.com/pkg/errors" ) // renameFallback attempts to determine the appropriate fallback to failed rename diff --git a/internal/tlsutil/cfg.go b/internal/tlsutil/cfg.go index 8b9d4329f..26da172c5 100644 --- a/internal/tlsutil/cfg.go +++ b/internal/tlsutil/cfg.go @@ -19,9 +19,8 @@ package tlsutil import ( "crypto/tls" "crypto/x509" + "fmt" "os" - - "github.com/pkg/errors" ) // Options represents configurable options used to create client and server TLS configurations. @@ -42,9 +41,9 @@ func ClientConfig(opts Options) (cfg *tls.Config, err error) { if opts.CertFile != "" || opts.KeyFile != "" { if cert, err = CertFromFilePair(opts.CertFile, opts.KeyFile); err != nil { if os.IsNotExist(err) { - return nil, errors.Wrapf(err, "could not load x509 key pair (cert: %q, key: %q)", opts.CertFile, opts.KeyFile) + return nil, fmt.Errorf("could not load x509 key pair (cert: %q, key: %q): %w", opts.CertFile, opts.KeyFile, err) } - return nil, errors.Wrapf(err, "could not read x509 key pair (cert: %q, key: %q)", opts.CertFile, opts.KeyFile) + return nil, fmt.Errorf("could not read x509 key pair (cert: %q, key: %q): %w", opts.CertFile, opts.KeyFile, err) } } if !opts.InsecureSkipVerify && opts.CaCertFile != "" { diff --git a/internal/tlsutil/tls.go b/internal/tlsutil/tls.go index 7cd1dace9..5ba3ca8ee 100644 --- a/internal/tlsutil/tls.go +++ b/internal/tlsutil/tls.go @@ -19,9 +19,8 @@ package tlsutil import ( "crypto/tls" "crypto/x509" + "fmt" "os" - - "github.com/pkg/errors" ) // NewClientTLS returns tls.Config appropriate for client auth. @@ -56,11 +55,11 @@ func NewClientTLS(certFile, keyFile, caFile string, insecureSkipTLSverify bool) func CertPoolFromFile(filename string) (*x509.CertPool, error) { b, err := os.ReadFile(filename) if err != nil { - return nil, errors.Errorf("can't read CA file: %v", filename) + return nil, fmt.Errorf("can't read CA file: %v", filename) } cp := x509.NewCertPool() if !cp.AppendCertsFromPEM(b) { - return nil, errors.Errorf("failed to append certificates from file: %s", filename) + return nil, fmt.Errorf("failed to append certificates from file: %s", filename) } return cp, nil } @@ -72,7 +71,7 @@ func CertPoolFromFile(filename string) (*x509.CertPool, error) { func CertFromFilePair(certFile, keyFile string) (*tls.Certificate, error) { cert, err := tls.LoadX509KeyPair(certFile, keyFile) if err != nil { - return nil, errors.Wrapf(err, "can't load key pair from cert %s and key %s", certFile, keyFile) + return nil, fmt.Errorf("can't load key pair from cert %s and key %s: %w", certFile, keyFile, err) } return &cert, err } diff --git a/pkg/action/action.go b/pkg/action/action.go index 45f1a14e2..ffb4ef0c6 100644 --- a/pkg/action/action.go +++ b/pkg/action/action.go @@ -18,6 +18,7 @@ package action import ( "bytes" + "errors" "fmt" "os" "path" @@ -25,7 +26,6 @@ import ( "regexp" "strings" - "github.com/pkg/errors" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/client-go/discovery" @@ -114,7 +114,7 @@ func (cfg *Configuration) renderResources(ch *chart.Chart, values chartutil.Valu if ch.Metadata.KubeVersion != "" { if !chartutil.IsCompatibleRange(ch.Metadata.KubeVersion, caps.KubeVersion.String()) { - return hs, b, "", errors.Errorf("chart requires kubeVersion: %s which is incompatible with Kubernetes %s", ch.Metadata.KubeVersion, caps.KubeVersion.String()) + return hs, b, "", fmt.Errorf("chart requires kubeVersion: %s which is incompatible with Kubernetes %s", ch.Metadata.KubeVersion, caps.KubeVersion.String()) } } @@ -225,7 +225,7 @@ func (cfg *Configuration) renderResources(ch *chart.Chart, values chartutil.Valu if pr != nil { b, err = pr.Run(b) if err != nil { - return hs, b, notes, errors.Wrap(err, "error while running post render on files") + return hs, b, notes, fmt.Errorf("error while running post render on files: %w", err) } } @@ -249,13 +249,13 @@ func (cfg *Configuration) getCapabilities() (*chartutil.Capabilities, error) { } dc, err := cfg.RESTClientGetter.ToDiscoveryClient() if err != nil { - return nil, errors.Wrap(err, "could not get Kubernetes discovery client") + return nil, fmt.Errorf("could not get Kubernetes discovery client: %w", err) } // force a discovery cache invalidation to always fetch the latest server version/capabilities. dc.Invalidate() kubeVersion, err := dc.ServerVersion() if err != nil { - return nil, errors.Wrap(err, "could not get server version from Kubernetes") + return nil, fmt.Errorf("could not get server version from Kubernetes: %w", err) } // Issue #6361: // Client-Go emits an error when an API service is registered but unimplemented. @@ -268,7 +268,7 @@ func (cfg *Configuration) getCapabilities() (*chartutil.Capabilities, error) { cfg.Log("WARNING: The Kubernetes server has an orphaned API service. Server reports: %s", err) cfg.Log("WARNING: To fix this, kubectl delete apiservice ") } else { - return nil, errors.Wrap(err, "could not get apiVersions from Kubernetes") + return nil, fmt.Errorf("could not get apiVersions from Kubernetes: %w", err) } } @@ -288,7 +288,7 @@ func (cfg *Configuration) getCapabilities() (*chartutil.Capabilities, error) { func (cfg *Configuration) KubernetesClientSet() (kubernetes.Interface, error) { conf, err := cfg.RESTClientGetter.ToRESTConfig() if err != nil { - return nil, errors.Wrap(err, "unable to generate config for kubernetes client") + return nil, fmt.Errorf("unable to generate config for kubernetes client: %w", err) } return kubernetes.NewForConfig(conf) @@ -304,7 +304,7 @@ func (cfg *Configuration) Now() time.Time { func (cfg *Configuration) releaseContent(name string, version int) (*release.Release, error) { if err := chartutil.ValidateReleaseName(name); err != nil { - return nil, errors.Errorf("releaseContent: Release name is invalid: %s", name) + return nil, fmt.Errorf("releaseContent: Release name is invalid: %s", name) } if version <= 0 { @@ -318,7 +318,7 @@ func (cfg *Configuration) releaseContent(name string, version int) (*release.Rel func GetVersionSet(client discovery.ServerResourcesInterface) (chartutil.VersionSet, error) { groups, resources, err := client.ServerGroupsAndResources() if err != nil && !discovery.IsGroupDiscoveryFailedError(err) { - return chartutil.DefaultVersionSet, errors.Wrap(err, "could not get apiVersions from Kubernetes") + return chartutil.DefaultVersionSet, fmt.Errorf("could not get apiVersions from Kubernetes: %w", err) } // FIXME: The Kubernetes test fixture for cli appears to always return nil @@ -411,11 +411,11 @@ func (cfg *Configuration) Init(getter genericclioptions.RESTClientGetter, namesp namespace, ) if err != nil { - return errors.Wrap(err, "unable to instantiate SQL driver") + return fmt.Errorf("unable to instantiate SQL driver: %w", err) } store = storage.Init(d) default: - return errors.Errorf("unknown driver %q", helmDriver) + return fmt.Errorf("unknown driver %q", helmDriver) } cfg.RESTClientGetter = getter diff --git a/pkg/action/history.go b/pkg/action/history.go index 0430aaf7a..125d9a317 100644 --- a/pkg/action/history.go +++ b/pkg/action/history.go @@ -17,7 +17,7 @@ limitations under the License. package action import ( - "github.com/pkg/errors" + "fmt" "helm.sh/helm/v3/pkg/chartutil" "helm.sh/helm/v3/pkg/release" @@ -50,7 +50,7 @@ func (h *History) Run(name string) ([]*release.Release, error) { } if err := chartutil.ValidateReleaseName(name); err != nil { - return nil, errors.Errorf("release name is invalid: %s", name) + return nil, fmt.Errorf("release name is invalid: %s", name) } h.cfg.Log("getting history for release %s", name) diff --git a/pkg/action/hooks.go b/pkg/action/hooks.go index 4bffb6ae0..9aeb46a47 100644 --- a/pkg/action/hooks.go +++ b/pkg/action/hooks.go @@ -17,11 +17,10 @@ package action import ( "bytes" + "fmt" "sort" "time" - "github.com/pkg/errors" - "helm.sh/helm/v3/pkg/kube" "helm.sh/helm/v3/pkg/release" helmtime "helm.sh/helm/v3/pkg/time" @@ -44,7 +43,7 @@ func (cfg *Configuration) execHook(rl *release.Release, hook release.HookEvent, for _, h := range executingHooks { // Set default delete policy to before-hook-creation - if h.DeletePolicies == nil || len(h.DeletePolicies) == 0 { + if len(h.DeletePolicies) == 0 { // TODO(jlegrone): Only apply before-hook-creation delete policy to run to completion // resources. For all other resource types update in place if a // resource with the same name already exists and is owned by the @@ -58,7 +57,7 @@ func (cfg *Configuration) execHook(rl *release.Release, hook release.HookEvent, resources, err := cfg.KubeClient.Build(bytes.NewBufferString(h.Manifest), true) if err != nil { - return errors.Wrapf(err, "unable to build kubernetes object for %s hook %s", hook, h.Path) + return fmt.Errorf("unable to build kubernetes object for %s hook %s: %w", hook, h.Path, err) } // Record the time at which the hook was applied to the cluster @@ -77,7 +76,7 @@ func (cfg *Configuration) execHook(rl *release.Release, hook release.HookEvent, if _, err := cfg.KubeClient.Create(resources); err != nil { h.LastRun.CompletedAt = helmtime.Now() h.LastRun.Phase = release.HookPhaseFailed - return errors.Wrapf(err, "warning: Hook %s %s failed", hook, h.Path) + return fmt.Errorf("warning: Hook %s %s failed: %w", hook, h.Path, err) } // Watch hook resources until they have completed @@ -131,14 +130,14 @@ func (cfg *Configuration) deleteHookByPolicy(h *release.Hook, policy release.Hoo if hookHasDeletePolicy(h, policy) { resources, err := cfg.KubeClient.Build(bytes.NewBufferString(h.Manifest), false) if err != nil { - return errors.Wrapf(err, "unable to build kubernetes object for deleting hook %s", h.Path) + return fmt.Errorf("unable to build kubernetes object for deleting hook %s: %w", h.Path, err) } _, errs := cfg.KubeClient.Delete(resources) if len(errs) > 0 { - return errors.New(joinErrors(errs)) + return joinErrors(errs, "; ") } - //wait for resources until they are deleted to avoid conflicts + // wait for resources until they are deleted to avoid conflicts if kubeClient, ok := cfg.KubeClient.(kube.InterfaceExt); ok { if err := kubeClient.WaitForDelete(resources, timeout); err != nil { return err diff --git a/pkg/action/install.go b/pkg/action/install.go index 6869b268b..aa10dbd46 100644 --- a/pkg/action/install.go +++ b/pkg/action/install.go @@ -19,6 +19,7 @@ package action import ( "bytes" "context" + "errors" "fmt" "io" "net/url" @@ -31,7 +32,6 @@ import ( "time" "github.com/Masterminds/sprig/v3" - "github.com/pkg/errors" v1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" @@ -164,7 +164,7 @@ func (i *Install) installCRDs(crds []chart.CRD) error { // Read in the resources res, err := i.cfg.KubeClient.Build(bytes.NewBuffer(obj.File.Data), false) if err != nil { - return errors.Wrapf(err, "failed to install CRD %s", obj.Name) + return fmt.Errorf("failed to install CRD %s: %w", obj.Name, err) } // Send them to Kube @@ -175,7 +175,7 @@ func (i *Install) installCRDs(crds []chart.CRD) error { i.cfg.Log("CRD %s is already present. Skipping.", crdName) continue } - return errors.Wrapf(err, "failed to install CRD %s", obj.Name) + return fmt.Errorf("failed to install CRD %s: %w", obj.Name, err) } totalItems = append(totalItems, res...) } @@ -331,7 +331,7 @@ func (i *Install) RunWithContext(ctx context.Context, chrt *chart.Chart, vals ma var toBeAdopted kube.ResourceList resources, err := i.cfg.KubeClient.Build(bytes.NewBufferString(rel.Manifest), !i.DisableOpenAPIValidation) if err != nil { - return nil, errors.Wrap(err, "unable to build kubernetes objects from release manifest") + return nil, fmt.Errorf("unable to build kubernetes objects from release manifest: %w", err) } // It is safe to use "force" here because these are resources currently rendered by the chart. @@ -353,7 +353,7 @@ func (i *Install) RunWithContext(ctx context.Context, chrt *chart.Chart, vals ma toBeAdopted, err = existingResourceConflict(resources, rel.Name, rel.Namespace) } if err != nil { - return nil, errors.Wrap(err, "Unable to continue with install") + return nil, fmt.Errorf("Unable to continue with install: %w", err) } } @@ -507,9 +507,9 @@ func (i *Install) failRelease(rel *release.Release, err error) (*release.Release uninstall.KeepHistory = false uninstall.Timeout = i.Timeout if _, uninstallErr := uninstall.Run(i.ReleaseName); uninstallErr != nil { - return rel, errors.Wrapf(uninstallErr, "an error occurred while uninstalling the release. original install error: %s", err) + return rel, fmt.Errorf("an error occurred while uninstalling the release. original install error: %w: %w", err, uninstallErr) } - return rel, errors.Wrapf(err, "release %s failed, and has been uninstalled due to atomic being set", i.ReleaseName) + return rel, fmt.Errorf("release %s failed, and has been uninstalled due to atomic being set: %w", i.ReleaseName, err) } i.recordRelease(rel) // Ignore the error, since we have another error to deal with. return rel, err @@ -527,7 +527,7 @@ func (i *Install) availableName() error { start := i.ReleaseName if err := chartutil.ValidateReleaseName(start); err != nil { - return errors.Wrapf(err, "release name %q", start) + return fmt.Errorf("release name %q: %w", start, err) } // On dry run, bail here if i.isDryRun() { @@ -615,7 +615,6 @@ func writeToFile(outputDir string, name string, data string, append bool) error defer f.Close() _, err = f.WriteString(fmt.Sprintf("---\n# Source: %s\n%s\n", name, data)) - if err != nil { return err } @@ -657,7 +656,7 @@ func (i *Install) NameAndChart(args []string) (string, string, error) { } if len(args) > 2 { - return args[0], args[1], errors.Errorf("expected at most two arguments, unexpected arguments: %v", strings.Join(args[2:], ", ")) + return args[0], args[1], fmt.Errorf("expected at most two arguments, unexpected arguments: %v", strings.Join(args[2:], ", ")) } if len(args) == 2 { @@ -722,7 +721,7 @@ OUTER: } if len(missing) > 0 { - return errors.Errorf("found in Chart.yaml, but missing in charts/ directory: %s", strings.Join(missing, ", ")) + return fmt.Errorf("found in Chart.yaml, but missing in charts/ directory: %s", strings.Join(missing, ", ")) } return nil } @@ -758,7 +757,7 @@ func (c *ChartPathOptions) LocateChart(name string, settings *cli.EnvSettings) ( return abs, nil } if filepath.IsAbs(name) || strings.HasPrefix(name, ".") { - return name, errors.Errorf("path %q not found", name) + return name, fmt.Errorf("path %q not found", name) } dl := downloader.ChartDownloader{ diff --git a/pkg/action/lint.go b/pkg/action/lint.go index 63a1bf354..9fd83e0ea 100644 --- a/pkg/action/lint.go +++ b/pkg/action/lint.go @@ -17,12 +17,11 @@ limitations under the License. package action import ( + "fmt" "os" "path/filepath" "strings" - "github.com/pkg/errors" - "helm.sh/helm/v3/pkg/chartutil" "helm.sh/helm/v3/pkg/lint" "helm.sh/helm/v3/pkg/lint/support" @@ -94,26 +93,26 @@ func lintChart(path string, vals map[string]interface{}, namespace string, kubeV if strings.HasSuffix(path, ".tgz") || strings.HasSuffix(path, ".tar.gz") { tempDir, err := os.MkdirTemp("", "helm-lint") if err != nil { - return linter, errors.Wrap(err, "unable to create temp dir to extract tarball") + return linter, fmt.Errorf("unable to create temp dir to extract tarball: %w", err) } defer os.RemoveAll(tempDir) file, err := os.Open(path) if err != nil { - return linter, errors.Wrap(err, "unable to open tarball") + return linter, fmt.Errorf("unable to open tarball: %w", err) } defer file.Close() if err = chartutil.Expand(tempDir, file); err != nil { - return linter, errors.Wrap(err, "unable to extract tarball") + return linter, fmt.Errorf("unable to extract tarball: %w", err) } files, err := os.ReadDir(tempDir) if err != nil { - return linter, errors.Wrapf(err, "unable to read temporary output directory %s", tempDir) + return linter, fmt.Errorf("unable to read temporary output directory %s: %w", tempDir, err) } if !files[0].IsDir() { - return linter, errors.Errorf("unexpected file %s in temporary output directory %s", files[0].Name(), tempDir) + return linter, fmt.Errorf("unexpected file %s in temporary output directory %s", files[0].Name(), tempDir) } chartPath = filepath.Join(tempDir, files[0].Name()) @@ -123,7 +122,7 @@ func lintChart(path string, vals map[string]interface{}, namespace string, kubeV // Guard: Error out if this is not a chart. if _, err := os.Stat(filepath.Join(chartPath, "Chart.yaml")); err != nil { - return linter, errors.Wrap(err, "unable to check Chart.yaml file in chart") + return linter, fmt.Errorf("unable to check Chart.yaml file in chart: %w", err) } return lint.AllWithKubeVersionAndSchemaValidation(chartPath, vals, namespace, kubeVersion, skipSchemaValidation), nil diff --git a/pkg/action/package.go b/pkg/action/package.go index 013b32f55..f6136c4b9 100644 --- a/pkg/action/package.go +++ b/pkg/action/package.go @@ -18,12 +18,12 @@ package action import ( "bufio" + "errors" "fmt" "os" "syscall" "github.com/Masterminds/semver/v3" - "github.com/pkg/errors" "golang.org/x/term" "helm.sh/helm/v3/pkg/chart/loader" @@ -93,7 +93,7 @@ func (p *Package) Run(path string, _ map[string]interface{}) (string, error) { name, err := chartutil.Save(ch, dest) if err != nil { - return "", errors.Wrap(err, "failed to save") + return "", fmt.Errorf("failed to save: %w", err) } if p.Sign { diff --git a/pkg/action/pull.go b/pkg/action/pull.go index 787553125..184b17a9a 100644 --- a/pkg/action/pull.go +++ b/pkg/action/pull.go @@ -22,8 +22,6 @@ import ( "path/filepath" "strings" - "github.com/pkg/errors" - "helm.sh/helm/v3/pkg/chartutil" "helm.sh/helm/v3/pkg/cli" "helm.sh/helm/v3/pkg/downloader" @@ -116,7 +114,7 @@ func (p *Pull) Run(chartRef string) (string, error) { var err error dest, err = os.MkdirTemp("", "helm-") if err != nil { - return out.String(), errors.Wrap(err, "failed to untar") + return out.String(), fmt.Errorf("failed to untar: %w", err) } defer os.RemoveAll(dest) } @@ -159,11 +157,10 @@ func (p *Pull) Run(chartRef string) (string, error) { if _, err := os.Stat(udCheck); err != nil { if err := os.MkdirAll(udCheck, 0755); err != nil { - return out.String(), errors.Wrap(err, "failed to untar (mkdir)") + return out.String(), fmt.Errorf("failed to untar (mkdir): %w", err) } - } else { - return out.String(), errors.Errorf("failed to untar: a file or directory with the name %s already exists", udCheck) + return out.String(), fmt.Errorf("failed to untar: a file or directory with the name %s already exists", udCheck) } return out.String(), chartutil.ExpandFile(ud, saved) diff --git a/pkg/action/release_testing.go b/pkg/action/release_testing.go index aaffe47ca..17f1b5275 100644 --- a/pkg/action/release_testing.go +++ b/pkg/action/release_testing.go @@ -23,7 +23,6 @@ import ( "sort" "time" - "github.com/pkg/errors" v1 "k8s.io/api/core/v1" "helm.sh/helm/v3/pkg/chartutil" @@ -62,7 +61,7 @@ func (r *ReleaseTesting) Run(name string) (*release.Release, error) { } if err := chartutil.ValidateReleaseName(name); err != nil { - return nil, errors.Errorf("releaseTest: Release name is invalid: %s", name) + return nil, fmt.Errorf("releaseTest: Release name is invalid: %s", name) } // finds the non-deleted release with the given name @@ -111,7 +110,7 @@ func (r *ReleaseTesting) Run(name string) (*release.Release, error) { func (r *ReleaseTesting) GetPodLogs(out io.Writer, rel *release.Release) error { client, err := r.cfg.KubernetesClientSet() if err != nil { - return errors.Wrap(err, "unable to get kubernetes client to fetch pod logs") + return fmt.Errorf("unable to get kubernetes client to fetch pod logs: %w", err) } hooksByWight := append([]*release.Hook{}, rel.Hooks...) @@ -128,14 +127,14 @@ func (r *ReleaseTesting) GetPodLogs(out io.Writer, rel *release.Release) error { req := client.CoreV1().Pods(r.Namespace).GetLogs(h.Name, &v1.PodLogOptions{}) logReader, err := req.Stream(context.Background()) if err != nil { - return errors.Wrapf(err, "unable to get pod logs for %s", h.Name) + return fmt.Errorf("unable to get pod logs for %s: %w", h.Name, err) } fmt.Fprintf(out, "POD LOGS: %s\n", h.Name) _, err = io.Copy(out, logReader) fmt.Fprintln(out) if err != nil { - return errors.Wrapf(err, "unable to write pod logs for %s", h.Name) + return fmt.Errorf("unable to write pod logs for %s: %w", h.Name, err) } } } diff --git a/pkg/action/rollback.go b/pkg/action/rollback.go index b0be17d13..09cb2db37 100644 --- a/pkg/action/rollback.go +++ b/pkg/action/rollback.go @@ -22,8 +22,6 @@ import ( "strings" "time" - "github.com/pkg/errors" - "helm.sh/helm/v3/pkg/chartutil" "helm.sh/helm/v3/pkg/release" helmtime "helm.sh/helm/v3/pkg/time" @@ -93,7 +91,7 @@ func (r *Rollback) Run(name string) error { // the previous release's configuration func (r *Rollback) prepareRollback(name string) (*release.Release, *release.Release, error) { if err := chartutil.ValidateReleaseName(name); err != nil { - return nil, nil, errors.Errorf("prepareRollback: Release name is invalid: %s", name) + return nil, nil, fmt.Errorf("prepareRollback: Release name is invalid: %s", name) } if r.Version < 0 { @@ -125,7 +123,7 @@ func (r *Rollback) prepareRollback(name string) (*release.Release, *release.Rele } } if !previousVersionExist { - return nil, nil, errors.Errorf("release has no %d version", previousVersion) + return nil, nil, fmt.Errorf("release has no %d version", previousVersion) } r.cfg.Log("rolling back %s (current: v%d, target: v%d)", name, currentRelease.Version, previousVersion) @@ -167,11 +165,11 @@ func (r *Rollback) performRollback(currentRelease, targetRelease *release.Releas current, err := r.cfg.KubeClient.Build(bytes.NewBufferString(currentRelease.Manifest), false) if err != nil { - return targetRelease, errors.Wrap(err, "unable to build kubernetes objects from current release manifest") + return targetRelease, fmt.Errorf("unable to build kubernetes objects from current release manifest: %w", err) } target, err := r.cfg.KubeClient.Build(bytes.NewBufferString(targetRelease.Manifest), false) if err != nil { - return targetRelease, errors.Wrap(err, "unable to build kubernetes objects from new release manifest") + return targetRelease, fmt.Errorf("unable to build kubernetes objects from new release manifest: %w", err) } // pre-rollback hooks @@ -186,7 +184,7 @@ func (r *Rollback) performRollback(currentRelease, targetRelease *release.Releas // It is safe to use "force" here because these are resources currently rendered by the chart. err = target.Visit(setMetadataVisitor(targetRelease.Name, targetRelease.Namespace, true)) if err != nil { - return targetRelease, errors.Wrap(err, "unable to set metadata visitor from target release") + return targetRelease, fmt.Errorf("unable to set metadata visitor from target release: %w", err) } results, err := r.cfg.KubeClient.Update(current, target, r.Force) @@ -202,11 +200,9 @@ func (r *Rollback) performRollback(currentRelease, targetRelease *release.Releas r.cfg.Log("Cleanup on fail set, cleaning up %d resources", len(results.Created)) _, errs := r.cfg.KubeClient.Delete(results.Created) if errs != nil { - var errorList []string - for _, e := range errs { - errorList = append(errorList, e.Error()) - } - return targetRelease, errors.Wrapf(fmt.Errorf("unable to cleanup resources: %s", strings.Join(errorList, ", ")), "an error occurred while cleaning up resources. original rollback error: %s", err) + return targetRelease, fmt.Errorf( + "an error occurred while cleaning up resources. original rollback error: %w", + fmt.Errorf("unable to cleanup resources: %w", joinErrors(errs, ", "))) } r.cfg.Log("Resource cleanup complete") } @@ -229,14 +225,14 @@ func (r *Rollback) performRollback(currentRelease, targetRelease *release.Releas targetRelease.SetStatus(release.StatusFailed, fmt.Sprintf("Release %q failed: %s", targetRelease.Name, err.Error())) r.cfg.recordRelease(currentRelease) r.cfg.recordRelease(targetRelease) - return targetRelease, errors.Wrapf(err, "release %s failed", targetRelease.Name) + return targetRelease, fmt.Errorf("release %s failed: %w", targetRelease.Name, err) } } else { if err := r.cfg.KubeClient.Wait(target, r.Timeout); err != nil { targetRelease.SetStatus(release.StatusFailed, fmt.Sprintf("Release %q failed: %s", targetRelease.Name, err.Error())) r.cfg.recordRelease(currentRelease) r.cfg.recordRelease(targetRelease) - return targetRelease, errors.Wrapf(err, "release %s failed", targetRelease.Name) + return targetRelease, fmt.Errorf("release %s failed: %w", targetRelease.Name, err) } } } diff --git a/pkg/action/show.go b/pkg/action/show.go index 6ed855b83..f02005176 100644 --- a/pkg/action/show.go +++ b/pkg/action/show.go @@ -21,7 +21,6 @@ import ( "fmt" "strings" - "github.com/pkg/errors" "k8s.io/cli-runtime/pkg/printers" "sigs.k8s.io/yaml" @@ -114,7 +113,7 @@ func (s *Show) Run(chartpath string) (string, error) { if s.JSONPathTemplate != "" { printer, err := printers.NewJSONPathPrinter(s.JSONPathTemplate) if err != nil { - return "", errors.Wrapf(err, "error parsing jsonpath %s", s.JSONPathTemplate) + return "", fmt.Errorf("error parsing jsonpath %s: %w", s.JSONPathTemplate, err) } printer.Execute(&out, s.chart.Values) } else { diff --git a/pkg/action/uninstall.go b/pkg/action/uninstall.go index ac0c4fee8..822d138af 100644 --- a/pkg/action/uninstall.go +++ b/pkg/action/uninstall.go @@ -17,11 +17,10 @@ limitations under the License. package action import ( + "fmt" "strings" "time" - "github.com/pkg/errors" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "helm.sh/helm/v3/pkg/chartutil" @@ -70,7 +69,7 @@ func (u *Uninstall) Run(name string) (*release.UninstallReleaseResponse, error) } if err := chartutil.ValidateReleaseName(name); err != nil { - return nil, errors.Errorf("uninstall: Release name is invalid: %s", name) + return nil, fmt.Errorf("uninstall: Release name is invalid: %s", name) } rels, err := u.cfg.Releases.History(name) @@ -78,7 +77,7 @@ func (u *Uninstall) Run(name string) (*release.UninstallReleaseResponse, error) if u.IgnoreNotFound { return nil, nil } - return nil, errors.Wrapf(err, "uninstall: Release not loaded: %s", name) + return nil, fmt.Errorf("uninstall: Release not loaded: %s: %w", name, err) } if len(rels) < 1 { return nil, errMissingRelease @@ -92,11 +91,11 @@ func (u *Uninstall) Run(name string) (*release.UninstallReleaseResponse, error) if rel.Info.Status == release.StatusUninstalled { if !u.KeepHistory { if err := u.purgeReleases(rels...); err != nil { - return nil, errors.Wrap(err, "uninstall: Failed to purge the release") + return nil, fmt.Errorf("uninstall: Failed to purge the release: %w", err) } return &release.UninstallReleaseResponse{Release: rel}, nil } - return nil, errors.Errorf("the release named %q is already deleted", name) + return nil, fmt.Errorf("the release named %q is already deleted", name) } u.cfg.Log("uninstall: Deleting %s", name) @@ -122,7 +121,7 @@ func (u *Uninstall) Run(name string) (*release.UninstallReleaseResponse, error) deletedResources, kept, errs := u.deleteRelease(rel) if errs != nil { u.cfg.Log("uninstall: Failed to delete release: %s", errs) - return nil, errors.Errorf("failed to delete release: %s", name) + return nil, fmt.Errorf("failed to delete release: %s", name) } if kept != "" { @@ -155,12 +154,12 @@ func (u *Uninstall) Run(name string) (*release.UninstallReleaseResponse, error) u.cfg.Log("purge requested for %s", name) err := u.purgeReleases(rels...) if err != nil { - errs = append(errs, errors.Wrap(err, "uninstall: Failed to purge the release")) + errs = append(errs, fmt.Errorf("uninstall: Failed to purge the release: %w", err)) } // Return the errors that occurred while deleting the release, if any if len(errs) > 0 { - return res, errors.Errorf("uninstallation completed with %d error(s): %s", len(errs), joinErrors(errs)) + return res, fmt.Errorf("uninstallation completed with %d error(s): %w", len(errs), joinErrors(errs, "; ")) } return res, nil @@ -171,7 +170,7 @@ func (u *Uninstall) Run(name string) (*release.UninstallReleaseResponse, error) } if len(errs) > 0 { - return res, errors.Errorf("uninstallation completed with %d error(s): %s", len(errs), joinErrors(errs)) + return res, fmt.Errorf("uninstallation completed with %d error(s): %w", len(errs), joinErrors(errs, "; ")) } return res, nil } @@ -185,12 +184,28 @@ func (u *Uninstall) purgeReleases(rels ...*release.Release) error { return nil } -func joinErrors(errs []error) string { - es := make([]string, 0, len(errs)) - for _, e := range errs { - es = append(es, e.Error()) +type joinedErrors struct { + errs []error + sep string +} + +func joinErrors(errs []error, sep string) error { + return &joinedErrors{ + errs: errs, + sep: sep, + } +} + +func (e *joinedErrors) Error() string { + errs := make([]string, 0, len(e.errs)) + for _, err := range e.errs { + errs = append(errs, err.Error()) } - return strings.Join(es, "; ") + return strings.Join(errs, e.sep) +} + +func (e *joinedErrors) Unwrap() []error { + return e.errs } // deleteRelease deletes the release and returns list of delete resources and manifests that were kept in the deletion process @@ -204,7 +219,7 @@ func (u *Uninstall) deleteRelease(rel *release.Release) (kube.ResourceList, stri // FIXME: One way to delete at this point would be to try a label-based // deletion. The problem with this is that we could get a false positive // and delete something that was not legitimately part of this release. - return nil, rel.Manifest, []error{errors.Wrap(err, "corrupted release record. You must manually delete the resources")} + return nil, rel.Manifest, []error{fmt.Errorf("corrupted release record. You must manually delete the resources: %w", err)} } filesToKeep, filesToDelete := filterManifestsToKeep(files) @@ -220,7 +235,7 @@ func (u *Uninstall) deleteRelease(rel *release.Release) (kube.ResourceList, stri resources, err := u.cfg.KubeClient.Build(strings.NewReader(builder.String()), false) if err != nil { - return nil, "", []error{errors.Wrap(err, "unable to build kubernetes objects for delete")} + return nil, "", []error{fmt.Errorf("unable to build kubernetes objects for delete: %w", err)} } if len(resources) > 0 { if kubeClient, ok := u.cfg.KubeClient.(kube.InterfaceDeletionPropagation); ok { diff --git a/pkg/action/upgrade.go b/pkg/action/upgrade.go index 5002406ca..1c79fbe51 100644 --- a/pkg/action/upgrade.go +++ b/pkg/action/upgrade.go @@ -19,12 +19,12 @@ package action import ( "bytes" "context" + "errors" "fmt" "strings" "sync" "time" - "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/cli-runtime/pkg/resource" @@ -158,7 +158,7 @@ func (u *Upgrade) RunWithContext(ctx context.Context, name string, chart *chart. u.Wait = u.Wait || u.Atomic if err := chartutil.ValidateReleaseName(name); err != nil { - return nil, errors.Errorf("release name is invalid: %s", name) + return nil, fmt.Errorf("release name is invalid: %s", name) } u.cfg.Log("preparing upgrade for %s", name) @@ -313,15 +313,15 @@ func (u *Upgrade) performUpgrade(ctx context.Context, originalRelease, upgradedR // Checking for removed Kubernetes API error so can provide a more informative error message to the user // Ref: https://github.com/helm/helm/issues/7219 if strings.Contains(err.Error(), "unable to recognize \"\": no matches for kind") { - return upgradedRelease, errors.Wrap(err, "current release manifest contains removed kubernetes api(s) for this "+ + return upgradedRelease, fmt.Errorf("current release manifest contains removed kubernetes api(s) for this "+ "kubernetes version and it is therefore unable to build the kubernetes "+ - "objects for performing the diff. error from kubernetes") + "objects for performing the diff. error from kubernetes: %w", err) } - return upgradedRelease, errors.Wrap(err, "unable to build kubernetes objects from current release manifest") + return upgradedRelease, fmt.Errorf("unable to build kubernetes objects from current release manifest: %w", err) } target, err := u.cfg.KubeClient.Build(bytes.NewBufferString(upgradedRelease.Manifest), !u.DisableOpenAPIValidation) if err != nil { - return upgradedRelease, errors.Wrap(err, "unable to build kubernetes objects from new release manifest") + return upgradedRelease, fmt.Errorf("unable to build kubernetes objects from new release manifest: %w", err) } // It is safe to use force only on target because these are resources currently rendered by the chart. @@ -350,7 +350,7 @@ func (u *Upgrade) performUpgrade(ctx context.Context, originalRelease, upgradedR toBeUpdated, err = existingResourceConflict(toBeCreated, upgradedRelease.Name, upgradedRelease.Namespace) } if err != nil { - return nil, errors.Wrap(err, "Unable to continue with update") + return nil, fmt.Errorf("Unable to continue with update: %w", err) } toBeUpdated.Visit(func(r *resource.Info, err error) error { @@ -493,11 +493,14 @@ func (u *Upgrade) failRelease(rel *release.Release, created kube.ResourceList, e u.cfg.Log("Cleanup on fail set, cleaning up %d resources", len(created)) _, errs := u.cfg.KubeClient.Delete(created) if errs != nil { - var errorList []string - for _, e := range errs { - errorList = append(errorList, e.Error()) - } - return rel, errors.Wrapf(fmt.Errorf("unable to cleanup resources: %s", strings.Join(errorList, ", ")), "an error occurred while cleaning up resources. original upgrade error: %s", err) + return rel, fmt.Errorf( + "an error occurred while cleaning up resources. original upgrade error: %w: %w", + err, + fmt.Errorf( + "unable to cleanup resources: %w", + joinErrors(errs, ", "), + ), + ) } u.cfg.Log("Resource cleanup complete") } @@ -509,7 +512,7 @@ func (u *Upgrade) failRelease(rel *release.Release, created kube.ResourceList, e hist := NewHistory(u.cfg) fullHistory, herr := hist.Run(rel.Name) if herr != nil { - return rel, errors.Wrapf(herr, "an error occurred while finding last successful release. original upgrade error: %s", err) + return rel, fmt.Errorf("an error occurred while finding last successful release. original upgrade error: %w: %w", err, herr) } // There isn't a way to tell if a previous release was successful, but @@ -519,7 +522,7 @@ func (u *Upgrade) failRelease(rel *release.Release, created kube.ResourceList, e return r.Info.Status == release.StatusSuperseded || r.Info.Status == release.StatusDeployed }).Filter(fullHistory) if len(filteredHistory) == 0 { - return rel, errors.Wrap(err, "unable to find a previously successful release when attempting to rollback. original upgrade error") + return rel, fmt.Errorf("unable to find a previously successful release when attempting to rollback. original upgrade error: %w", err) } releaseutil.Reverse(filteredHistory, releaseutil.SortByRevision) @@ -533,9 +536,9 @@ func (u *Upgrade) failRelease(rel *release.Release, created kube.ResourceList, e rollin.Force = u.Force rollin.Timeout = u.Timeout if rollErr := rollin.Run(rel.Name); rollErr != nil { - return rel, errors.Wrapf(rollErr, "an error occurred while rolling back the release. original upgrade error: %s", err) + return rel, fmt.Errorf("an error occurred while rolling back the release. original upgrade error: %w: %w", err, rollErr) } - return rel, errors.Wrapf(err, "release %s failed, and has been rolled back due to atomic being set", rel.Name) + return rel, fmt.Errorf("release %s failed, and has been rolled back due to atomic being set: %w", rel.Name, err) } return rel, err @@ -563,7 +566,7 @@ func (u *Upgrade) reuseValues(chart *chart.Chart, current *release.Release, newV // We have to regenerate the old coalesced values: oldVals, err := chartutil.CoalesceValues(current.Chart, current.Config) if err != nil { - return nil, errors.Wrap(err, "failed to rebuild old values") + return nil, fmt.Errorf("failed to rebuild old values: %w", err) } newVals = chartutil.CoalesceTables(newVals, current.Config) @@ -609,21 +612,21 @@ func recreate(cfg *Configuration, resources kube.ResourceList) error { client, err := cfg.KubernetesClientSet() if err != nil { - return errors.Wrapf(err, "unable to recreate pods for object %s/%s because an error occurred", res.Namespace, res.Name) + return fmt.Errorf("unable to recreate pods for object %s/%s because an error occurred: %w", res.Namespace, res.Name, err) } pods, err := client.CoreV1().Pods(res.Namespace).List(context.Background(), metav1.ListOptions{ LabelSelector: selector.String(), }) if err != nil { - return errors.Wrapf(err, "unable to recreate pods for object %s/%s because an error occurred", res.Namespace, res.Name) + return fmt.Errorf("unable to recreate pods for object %s/%s because an error occurred: %w", res.Namespace, res.Name, err) } // Restart pods for _, pod := range pods.Items { // Delete each pod for get them restarted with changed spec. if err := client.CoreV1().Pods(pod.Namespace).Delete(context.Background(), pod.Name, *metav1.NewPreconditionDeleteOptions(string(pod.UID))); err != nil { - return errors.Wrapf(err, "unable to recreate pods for object %s/%s because an error occurred", res.Namespace, res.Name) + return fmt.Errorf("unable to recreate pods for object %s/%s because an error occurred: %w", res.Namespace, res.Name, err) } } } diff --git a/pkg/action/validate.go b/pkg/action/validate.go index 127e9bf96..cbf48acb7 100644 --- a/pkg/action/validate.go +++ b/pkg/action/validate.go @@ -17,9 +17,9 @@ limitations under the License. package action import ( + "errors" "fmt" - "github.com/pkg/errors" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime" @@ -52,7 +52,7 @@ func requireAdoption(resources kube.ResourceList) (kube.ResourceList, error) { if apierrors.IsNotFound(err) { return nil } - return errors.Wrapf(err, "could not get information about the resource %s", resourceString(info)) + return fmt.Errorf("could not get information about the resource %s: %w", resourceString(info), err) } requireUpdate.Append(info) @@ -76,7 +76,7 @@ func existingResourceConflict(resources kube.ResourceList, releaseName, releaseN if apierrors.IsNotFound(err) { return nil } - return errors.Wrapf(err, "could not get information about the resource %s", resourceString(info)) + return fmt.Errorf("could not get information about the resource %s: %w", resourceString(info), err) } // Allow adoption of the resource if it is managed by Helm and is annotated with correct release name and namespace. diff --git a/pkg/chart/loader/archive.go b/pkg/chart/loader/archive.go index 8bb549346..24d5b5c24 100644 --- a/pkg/chart/loader/archive.go +++ b/pkg/chart/loader/archive.go @@ -20,6 +20,7 @@ import ( "archive/tar" "bytes" "compress/gzip" + "errors" "fmt" "io" "net/http" @@ -28,8 +29,6 @@ import ( "regexp" "strings" - "github.com/pkg/errors" - "helm.sh/helm/v3/pkg/chart" ) @@ -160,7 +159,7 @@ func LoadArchiveFiles(in io.Reader) ([]*BufferedFile, error) { n = path.Clean(n) if n == "." { // In this case, the original path was relative when it should have been absolute. - return nil, errors.Errorf("chart illegally contains content outside the base directory: %q", hd.Name) + return nil, fmt.Errorf("chart illegally contains content outside the base directory: %q", hd.Name) } if strings.HasPrefix(n, "..") { return nil, errors.New("chart illegally references parent directory") diff --git a/pkg/chart/loader/directory.go b/pkg/chart/loader/directory.go index 9bcbee60c..4c95742cb 100644 --- a/pkg/chart/loader/directory.go +++ b/pkg/chart/loader/directory.go @@ -23,8 +23,6 @@ import ( "path/filepath" "strings" - "github.com/pkg/errors" - "helm.sh/helm/v3/internal/sympath" "helm.sh/helm/v3/pkg/chart" "helm.sh/helm/v3/pkg/ignore" @@ -103,7 +101,7 @@ func LoadDir(dir string) (*chart.Chart, error) { data, err := os.ReadFile(name) if err != nil { - return errors.Wrapf(err, "error reading %s", n) + return fmt.Errorf("error reading %s: %w", n, err) } data = bytes.TrimPrefix(data, utf8bom) diff --git a/pkg/chart/loader/load.go b/pkg/chart/loader/load.go index a68a05aa9..86a7353d0 100644 --- a/pkg/chart/loader/load.go +++ b/pkg/chart/loader/load.go @@ -18,12 +18,13 @@ package loader import ( "bytes" + "errors" + "fmt" "log" "os" "path/filepath" "strings" - "github.com/pkg/errors" "sigs.k8s.io/yaml" "helm.sh/helm/v3/pkg/chart" @@ -44,7 +45,6 @@ func Loader(name string) (ChartLoader, error) { return DirLoader(name), nil } return FileLoader(name), nil - } // Load takes a string name, tries to resolve it to a file or directory, and then loads it. @@ -82,7 +82,7 @@ func LoadFiles(files []*BufferedFile) (*chart.Chart, error) { c.Metadata = new(chart.Metadata) } if err := yaml.Unmarshal(f.Data, c.Metadata); err != nil { - return c, errors.Wrap(err, "cannot load Chart.yaml") + return c, fmt.Errorf("cannot load Chart.yaml: %w", err) } // NOTE(bacongobbler): while the chart specification says that APIVersion must be set, // Helm 2 accepted charts that did not provide an APIVersion in their chart metadata. @@ -100,12 +100,12 @@ func LoadFiles(files []*BufferedFile) (*chart.Chart, error) { case f.Name == "Chart.lock": c.Lock = new(chart.Lock) if err := yaml.Unmarshal(f.Data, &c.Lock); err != nil { - return c, errors.Wrap(err, "cannot load Chart.lock") + return c, fmt.Errorf("cannot load Chart.lock: %w", err) } case f.Name == "values.yaml": c.Values = make(map[string]interface{}) if err := yaml.Unmarshal(f.Data, &c.Values); err != nil { - return c, errors.Wrap(err, "cannot load values.yaml") + return c, fmt.Errorf("cannot load values.yaml: %w", err) } case f.Name == "values.schema.json": c.Schema = f.Data @@ -120,7 +120,7 @@ func LoadFiles(files []*BufferedFile) (*chart.Chart, error) { log.Printf("Warning: Dependencies are handled in Chart.yaml since apiVersion \"v2\". We recommend migrating dependencies to Chart.yaml.") } if err := yaml.Unmarshal(f.Data, c.Metadata); err != nil { - return c, errors.Wrap(err, "cannot load requirements.yaml") + return c, fmt.Errorf("cannot load requirements.yaml: %w", err) } if c.Metadata.APIVersion == chart.APIVersionV1 { c.Files = append(c.Files, &chart.File{Name: f.Name, Data: f.Data}) @@ -129,7 +129,7 @@ func LoadFiles(files []*BufferedFile) (*chart.Chart, error) { case f.Name == "requirements.lock": c.Lock = new(chart.Lock) if err := yaml.Unmarshal(f.Data, &c.Lock); err != nil { - return c, errors.Wrap(err, "cannot load requirements.lock") + return c, fmt.Errorf("cannot load requirements.lock: %w", err) } if c.Metadata == nil { c.Metadata = new(chart.Metadata) @@ -174,7 +174,7 @@ func LoadFiles(files []*BufferedFile) (*chart.Chart, error) { case filepath.Ext(n) == ".tgz": file := files[0] if file.Name != n { - return c, errors.Errorf("error unpacking subchart tar in %s: expected %s, got %s", c.Name(), n, file.Name) + return c, fmt.Errorf("error unpacking subchart tar in %s: expected %s, got %s", c.Name(), n, file.Name) } // Untar the chart and add to c.Dependencies sc, err = LoadArchive(bytes.NewBuffer(file.Data)) @@ -194,7 +194,7 @@ func LoadFiles(files []*BufferedFile) (*chart.Chart, error) { } if err != nil { - return c, errors.Wrapf(err, "error unpacking subchart %s in %s", n, c.Name()) + return c, fmt.Errorf("error unpacking subchart %s in %s: %w", n, c.Name(), err) } c.AddDependency(sc) } diff --git a/pkg/chartutil/chartfile.go b/pkg/chartutil/chartfile.go index 4f537a6e7..98bfc2348 100644 --- a/pkg/chartutil/chartfile.go +++ b/pkg/chartutil/chartfile.go @@ -17,10 +17,10 @@ limitations under the License. package chartutil import ( + "fmt" "os" "path/filepath" - "github.com/pkg/errors" "sigs.k8s.io/yaml" "helm.sh/helm/v3/pkg/chart" @@ -64,17 +64,17 @@ func IsChartDir(dirName string) (bool, error) { if fi, err := os.Stat(dirName); err != nil { return false, err } else if !fi.IsDir() { - return false, errors.Errorf("%q is not a directory", dirName) + return false, fmt.Errorf("%q is not a directory", dirName) } chartYaml := filepath.Join(dirName, ChartfileName) if _, err := os.Stat(chartYaml); os.IsNotExist(err) { - return false, errors.Errorf("no %s exists in directory %q", ChartfileName, dirName) + return false, fmt.Errorf("no %s exists in directory %q", ChartfileName, dirName) } chartYamlContent, err := os.ReadFile(chartYaml) if err != nil { - return false, errors.Errorf("cannot read %s in directory %q", ChartfileName, dirName) + return false, fmt.Errorf("cannot read %s in directory %q", ChartfileName, dirName) } chartContent := new(chart.Metadata) @@ -82,10 +82,10 @@ func IsChartDir(dirName string) (bool, error) { return false, err } if chartContent == nil { - return false, errors.Errorf("chart metadata (%s) missing", ChartfileName) + return false, fmt.Errorf("chart metadata (%s) missing", ChartfileName) } if chartContent.Name == "" { - return false, errors.Errorf("invalid chart (%s): name must not be empty", ChartfileName) + return false, fmt.Errorf("invalid chart (%s): name must not be empty", ChartfileName) } return true, nil diff --git a/pkg/chartutil/coalesce.go b/pkg/chartutil/coalesce.go index f0272fd6a..c0a0ecf43 100644 --- a/pkg/chartutil/coalesce.go +++ b/pkg/chartutil/coalesce.go @@ -21,7 +21,6 @@ import ( "log" "github.com/mitchellh/copystructure" - "github.com/pkg/errors" "helm.sh/helm/v3/pkg/chart" ) @@ -108,7 +107,7 @@ func coalesceDeps(printf printFn, chrt *chart.Chart, dest map[string]interface{} // If dest doesn't already have the key, create it. dest[subchart.Name()] = make(map[string]interface{}) } else if !istable(c) { - return dest, errors.Errorf("type mismatch on %s: %t", subchart.Name(), c) + return dest, fmt.Errorf("type mismatch on %s: %t", subchart.Name(), c) } if dv, ok := dest[subchart.Name()]; ok { dvmap := dv.(map[string]interface{}) diff --git a/pkg/chartutil/create.go b/pkg/chartutil/create.go index dc70530eb..a6fab5c4d 100644 --- a/pkg/chartutil/create.go +++ b/pkg/chartutil/create.go @@ -24,7 +24,6 @@ import ( "regexp" "strings" - "github.com/pkg/errors" "sigs.k8s.io/yaml" "helm.sh/helm/v3/pkg/chart" @@ -548,7 +547,7 @@ var Stderr io.Writer = os.Stderr func CreateFrom(chartfile *chart.Metadata, dest, src string) error { schart, err := loader.Load(src) if err != nil { - return errors.Wrapf(err, "could not load %s", src) + return fmt.Errorf("could not load %s: %w", src, err) } schart.Metadata = chartfile @@ -563,12 +562,12 @@ func CreateFrom(chartfile *chart.Metadata, dest, src string) error { schart.Templates = updatedTemplates b, err := yaml.Marshal(schart.Values) if err != nil { - return errors.Wrap(err, "reading values file") + return fmt.Errorf("reading values file: %w", err) } var m map[string]interface{} if err := yaml.Unmarshal(transform(string(b), schart.Name()), &m); err != nil { - return errors.Wrap(err, "transforming values file") + return fmt.Errorf("transforming values file: %w", err) } schart.Values = m @@ -612,12 +611,12 @@ func Create(name, dir string) (string, error) { if fi, err := os.Stat(path); err != nil { return path, err } else if !fi.IsDir() { - return path, errors.Errorf("no such directory %s", path) + return path, fmt.Errorf("no such directory %s", path) } cdir := filepath.Join(path, name) if fi, err := os.Stat(cdir); err == nil && !fi.IsDir() { - return cdir, errors.Errorf("file %s already exists and is not a directory", cdir) + return cdir, fmt.Errorf("file %s already exists and is not a directory", cdir) } // Note: If adding a new template below (i.e., to `helm create`) which is disabled by default (similar to hpa and diff --git a/pkg/chartutil/expand.go b/pkg/chartutil/expand.go index 7ae1ae6fa..dda6d6364 100644 --- a/pkg/chartutil/expand.go +++ b/pkg/chartutil/expand.go @@ -17,12 +17,13 @@ limitations under the License. package chartutil import ( + "errors" + "fmt" "io" "os" "path/filepath" securejoin "github.com/cyphar/filepath-securejoin" - "github.com/pkg/errors" "sigs.k8s.io/yaml" "helm.sh/helm/v3/pkg/chart" @@ -42,7 +43,7 @@ func Expand(dir string, r io.Reader) error { if file.Name == "Chart.yaml" { ch := &chart.Metadata{} if err := yaml.Unmarshal(file.Data, ch); err != nil { - return errors.Wrap(err, "cannot load Chart.yaml") + return fmt.Errorf("cannot load Chart.yaml: %w", err) } chartName = ch.Name } diff --git a/pkg/chartutil/jsonschema.go b/pkg/chartutil/jsonschema.go index 7b9768fd3..8d5dcc103 100644 --- a/pkg/chartutil/jsonschema.go +++ b/pkg/chartutil/jsonschema.go @@ -18,10 +18,10 @@ package chartutil import ( "bytes" + "errors" "fmt" "strings" - "github.com/pkg/errors" "github.com/xeipuuv/gojsonschema" "sigs.k8s.io/yaml" diff --git a/pkg/chartutil/save.go b/pkg/chartutil/save.go index 4ee90709c..bf47cbe44 100644 --- a/pkg/chartutil/save.go +++ b/pkg/chartutil/save.go @@ -20,12 +20,12 @@ import ( "archive/tar" "compress/gzip" "encoding/json" + "errors" "fmt" "os" "path/filepath" "time" - "github.com/pkg/errors" "sigs.k8s.io/yaml" "helm.sh/helm/v3/pkg/chart" @@ -45,7 +45,7 @@ func SaveDir(c *chart.Chart, dest string) error { } outdir := filepath.Join(dest, c.Name()) if fi, err := os.Stat(outdir); err == nil && !fi.IsDir() { - return errors.Errorf("file %s already exists and is not a directory", outdir) + return fmt.Errorf("file %s already exists and is not a directory", outdir) } if err := os.MkdirAll(outdir, 0755); err != nil { return err @@ -89,7 +89,7 @@ func SaveDir(c *chart.Chart, dest string) error { for _, dep := range c.Dependencies() { // Here, we write each dependency as a tar file. if _, err := Save(dep, base); err != nil { - return errors.Wrapf(err, "saving %s", dep.ChartFullPath()) + return fmt.Errorf("saving %s: %w", dep.ChartFullPath(), err) } } return nil @@ -105,7 +105,7 @@ func SaveDir(c *chart.Chart, dest string) error { // This returns the absolute path to the chart archive file. func Save(c *chart.Chart, outDir string) (string, error) { if err := c.Validate(); err != nil { - return "", errors.Wrap(err, "chart validation") + return "", fmt.Errorf("chart validation: %w", err) } filename := fmt.Sprintf("%s-%s.tgz", c.Name(), c.Metadata.Version) @@ -117,10 +117,10 @@ func Save(c *chart.Chart, outDir string) (string, error) { return "", err2 } } else { - return "", errors.Wrapf(err, "stat %s", dir) + return "", fmt.Errorf("stat %s: %w", dir, err) } } else if !stat.IsDir() { - return "", errors.Errorf("is not a directory: %s", dir) + return "", fmt.Errorf("is not a directory: %s", dir) } f, err := os.Create(filename) diff --git a/pkg/chartutil/validate_name.go b/pkg/chartutil/validate_name.go index 05c090cb6..4f5c2efe0 100644 --- a/pkg/chartutil/validate_name.go +++ b/pkg/chartutil/validate_name.go @@ -17,10 +17,9 @@ limitations under the License. package chartutil import ( + "errors" "fmt" "regexp" - - "github.com/pkg/errors" ) // validName is a regular expression for resource names. diff --git a/pkg/chartutil/values.go b/pkg/chartutil/values.go index 61c633a6d..963ddbf1f 100644 --- a/pkg/chartutil/values.go +++ b/pkg/chartutil/values.go @@ -17,12 +17,12 @@ limitations under the License. package chartutil import ( + "errors" "fmt" "io" "os" "strings" - "github.com/pkg/errors" "sigs.k8s.io/yaml" "helm.sh/helm/v3/pkg/chart" diff --git a/pkg/cli/output/output.go b/pkg/cli/output/output.go index 01649c812..28d503741 100644 --- a/pkg/cli/output/output.go +++ b/pkg/cli/output/output.go @@ -22,7 +22,6 @@ import ( "io" "github.com/gosuri/uitable" - "github.com/pkg/errors" "sigs.k8s.io/yaml" ) @@ -107,7 +106,7 @@ func EncodeJSON(out io.Writer, obj interface{}) error { enc := json.NewEncoder(out) err := enc.Encode(obj) if err != nil { - return errors.Wrap(err, "unable to write JSON output") + return fmt.Errorf("unable to write JSON output: %w", err) } return nil } @@ -117,12 +116,12 @@ func EncodeJSON(out io.Writer, obj interface{}) error { func EncodeYAML(out io.Writer, obj interface{}) error { raw, err := yaml.Marshal(obj) if err != nil { - return errors.Wrap(err, "unable to write YAML output") + return fmt.Errorf("unable to write YAML output: %w", err) } _, err = out.Write(raw) if err != nil { - return errors.Wrap(err, "unable to write YAML output") + return fmt.Errorf("unable to write YAML output: %w", err) } return nil } @@ -134,7 +133,7 @@ func EncodeTable(out io.Writer, table *uitable.Table) error { raw = append(raw, []byte("\n")...) _, err := out.Write(raw) if err != nil { - return errors.Wrap(err, "unable to write table output") + return fmt.Errorf("unable to write table output: %w", err) } return nil } diff --git a/pkg/cli/values/options.go b/pkg/cli/values/options.go index 06631cd33..2d29a8f0d 100644 --- a/pkg/cli/values/options.go +++ b/pkg/cli/values/options.go @@ -17,12 +17,12 @@ limitations under the License. package values import ( + "fmt" "io" "net/url" "os" "strings" - "github.com/pkg/errors" "sigs.k8s.io/yaml" "helm.sh/helm/v3/pkg/getter" @@ -54,7 +54,7 @@ func (opts *Options) MergeValues(p getter.Providers) (map[string]interface{}, er } if err := yaml.Unmarshal(bytes, ¤tMap); err != nil { - return nil, errors.Wrapf(err, "failed to parse %s", filePath) + return nil, fmt.Errorf("failed to parse %s: %w", filePath, err) } // Merge with the previous map base = mergeMaps(base, currentMap) @@ -63,21 +63,21 @@ func (opts *Options) MergeValues(p getter.Providers) (map[string]interface{}, er // User specified a value via --set-json for _, value := range opts.JSONValues { if err := strvals.ParseJSON(value, base); err != nil { - return nil, errors.Errorf("failed parsing --set-json data %s", value) + return nil, fmt.Errorf("failed parsing --set-json data %s", value) } } // User specified a value via --set for _, value := range opts.Values { if err := strvals.ParseInto(value, base); err != nil { - return nil, errors.Wrap(err, "failed parsing --set data") + return nil, fmt.Errorf("failed parsing --set data: %w", err) } } // User specified a value via --set-string for _, value := range opts.StringValues { if err := strvals.ParseIntoString(value, base); err != nil { - return nil, errors.Wrap(err, "failed parsing --set-string data") + return nil, fmt.Errorf("failed parsing --set-string data: %w", err) } } @@ -91,14 +91,14 @@ func (opts *Options) MergeValues(p getter.Providers) (map[string]interface{}, er return string(bytes), err } if err := strvals.ParseIntoFile(value, base, reader); err != nil { - return nil, errors.Wrap(err, "failed parsing --set-file data") + return nil, fmt.Errorf("failed parsing --set-file data: %w", err) } } // User specified a value via --set-literal for _, value := range opts.LiteralValues { if err := strvals.ParseLiteralInto(value, base); err != nil { - return nil, errors.Wrap(err, "failed parsing --set-literal data") + return nil, fmt.Errorf("failed parsing --set-literal data: %w", err) } } diff --git a/pkg/downloader/chart_downloader.go b/pkg/downloader/chart_downloader.go index dde6a1057..0b13365c6 100644 --- a/pkg/downloader/chart_downloader.go +++ b/pkg/downloader/chart_downloader.go @@ -16,15 +16,16 @@ limitations under the License. package downloader import ( + "errors" "fmt" "io" + "io/fs" "net/url" "os" "path/filepath" "strings" "github.com/Masterminds/semver/v3" - "github.com/pkg/errors" "helm.sh/helm/v3/internal/fileutil" "helm.sh/helm/v3/internal/urlutil" @@ -121,7 +122,7 @@ func (c *ChartDownloader) DownloadTo(ref, version, dest string) (string, *proven body, err := g.Get(u.String() + ".prov") if err != nil { if c.Verify == VerifyAlways { - return destfile, ver, errors.Errorf("failed to fetch provenance %q", u.String()+".prov") + return destfile, ver, fmt.Errorf("failed to fetch provenance %q", u.String()+".prov") } fmt.Fprintf(c.Out, "WARNING: Verification not found for %s: %s\n", ref, err) return destfile, ver, nil @@ -158,7 +159,7 @@ func (c *ChartDownloader) getOciURI(ref, version string, u *url.URL) (*url.URL, return nil, err } if len(tags) == 0 { - return nil, errors.Errorf("Unable to locate any tags in provided repository: %s", ref) + return nil, fmt.Errorf("Unable to locate any tags in provided repository: %s", ref) } // Determine if version provided @@ -194,7 +195,7 @@ func (c *ChartDownloader) getOciURI(ref, version string, u *url.URL) (*url.URL, func (c *ChartDownloader) ResolveChartVersion(ref, version string) (*url.URL, error) { u, err := url.Parse(ref) if err != nil { - return nil, errors.Errorf("invalid chart URL format: %s", ref) + return nil, fmt.Errorf("invalid chart URL format: %s", ref) } if registry.IsOCI(u.String()) { @@ -247,13 +248,12 @@ func (c *ChartDownloader) ResolveChartVersion(ref, version string) (*url.URL, er // See if it's of the form: repo/path_to_chart p := strings.SplitN(u.Path, "/", 2) if len(p) < 2 { - return u, errors.Errorf("non-absolute URLs should be in form of repo_name/path_to_chart, got: %s", u) + return u, fmt.Errorf("non-absolute URLs should be in form of repo_name/path_to_chart, got: %s", u) } repoName := p[0] chartName := p[1] rc, err := pickChartRepositoryConfigByName(repoName, rf.Repositories) - if err != nil { return u, err } @@ -283,23 +283,22 @@ func (c *ChartDownloader) ResolveChartVersion(ref, version string) (*url.URL, er idxFile := filepath.Join(c.RepositoryCache, helmpath.CacheIndexFile(r.Config.Name)) i, err := repo.LoadIndexFile(idxFile) if err != nil { - return u, errors.Wrap(err, "no cached repo found. (try 'helm repo update')") + return u, fmt.Errorf("no cached repo found. (try 'helm repo update'): %w", err) } cv, err := i.Get(chartName, version) if err != nil { - return u, errors.Wrapf(err, "chart %q matching %s not found in %s index. (try 'helm repo update')", chartName, version, r.Config.Name) + return u, fmt.Errorf("chart %q matching %s not found in %s index. (try 'helm repo update'): %w", chartName, version, r.Config.Name, err) } if len(cv.URLs) == 0 { - return u, errors.Errorf("chart %q has no downloadable URLs", ref) + return u, fmt.Errorf("chart %q has no downloadable URLs", ref) } // TODO: Seems that picking first URL is not fully correct resolvedURL, err := repo.ResolveReferenceURL(rc.URL, cv.URLs[0]) - if err != nil { - return u, errors.Errorf("invalid chart URL format: %s", ref) + return u, fmt.Errorf("invalid chart URL format: %s", ref) } return url.Parse(resolvedURL) @@ -322,12 +321,12 @@ func VerifyChart(path, keyring string) (*provenance.Verification, error) { provfile := path + ".prov" if _, err := os.Stat(provfile); err != nil { - return nil, errors.Wrapf(err, "could not load provenance file %s", provfile) + return nil, fmt.Errorf("could not load provenance file %s: %w", provfile, err) } sig, err := provenance.NewFromKeyring(keyring, "") if err != nil { - return nil, errors.Wrap(err, "failed to load keyring") + return nil, fmt.Errorf("failed to load keyring: %w", err) } return sig.Verify(path, provfile) } @@ -344,12 +343,12 @@ func pickChartRepositoryConfigByName(name string, cfgs []*repo.Entry) (*repo.Ent for _, rc := range cfgs { if rc.Name == name { if rc.URL == "" { - return nil, errors.Errorf("no URL found for repository %s", name) + return nil, fmt.Errorf("no URL found for repository %s", name) } return rc, nil } } - return nil, errors.Errorf("repo %s not found", name) + return nil, fmt.Errorf("repo %s not found", name) } // scanReposForURL scans all repos to find which repo contains the given URL. @@ -382,7 +381,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) if err != nil { - return nil, errors.Wrap(err, "no cached repo found. (try 'helm repo update')") + return nil, fmt.Errorf("no cached repo found. (try 'helm repo update'): %w", err) } for _, entry := range i.Entries { @@ -401,7 +400,7 @@ func (c *ChartDownloader) scanReposForURL(u string, rf *repo.File) (*repo.Entry, func loadRepoConfig(file string) (*repo.File, error) { r, err := repo.LoadFile(file) - if err != nil && !os.IsNotExist(errors.Cause(err)) { + if err != nil && !errors.Is(err, fs.ErrNotExist) { return nil, err } return r, nil diff --git a/pkg/downloader/manager.go b/pkg/downloader/manager.go index ec4056d27..e778e9105 100644 --- a/pkg/downloader/manager.go +++ b/pkg/downloader/manager.go @@ -18,6 +18,7 @@ package downloader import ( "crypto" "encoding/hex" + "errors" "fmt" "io" "log" @@ -30,7 +31,6 @@ import ( "sync" "github.com/Masterminds/semver/v3" - "github.com/pkg/errors" "sigs.k8s.io/yaml" "helm.sh/helm/v3/internal/resolver" @@ -220,7 +220,7 @@ func (m *Manager) Update() error { func (m *Manager) loadChartDir() (*chart.Chart, error) { if fi, err := os.Stat(m.ChartPath); err != nil { - return nil, errors.Wrapf(err, "could not find %s", m.ChartPath) + return nil, fmt.Errorf("could not find %s: %w", m.ChartPath, err) } else if !fi.IsDir() { return nil, errors.New("only unpacked charts can be updated") } @@ -251,7 +251,7 @@ func (m *Manager) downloadAll(deps []*chart.Dependency) error { // Check if 'charts' directory is not actually a directory. If it does not exist, create it. if fi, err := os.Stat(destPath); err == nil { if !fi.IsDir() { - return errors.Errorf("%q is not a directory", destPath) + return fmt.Errorf("%q is not a directory", destPath) } } else if os.IsNotExist(err) { if err := os.MkdirAll(destPath, 0755); err != nil { @@ -314,7 +314,7 @@ func (m *Manager) downloadAll(deps []*chart.Dependency) error { // https://github.com/helm/helm/issues/1439 churl, username, password, insecureskiptlsverify, passcredentialsall, caFile, certFile, keyFile, err := m.findChartURL(dep.Name, dep.Version, dep.Repository, repos) if err != nil { - saveError = errors.Wrapf(err, "could not find %s", churl) + saveError = fmt.Errorf("could not find %s: %w", churl, err) break } @@ -345,7 +345,7 @@ func (m *Manager) downloadAll(deps []*chart.Dependency) error { if registry.IsOCI(churl) { churl, version, err = parseOCIRef(churl) if err != nil { - return errors.Wrapf(err, "could not parse OCI reference") + return fmt.Errorf("could not parse OCI reference: %w", err) } dl.Options = append(dl.Options, getter.WithRegistryClient(m.RegistryClient), @@ -353,7 +353,7 @@ func (m *Manager) downloadAll(deps []*chart.Dependency) error { } if _, _, err = dl.DownloadTo(churl, version, tmpPath); err != nil { - saveError = errors.Wrapf(err, "could not download %s", churl) + saveError = fmt.Errorf("could not download %s: %w", churl, err) break } @@ -377,7 +377,7 @@ func parseOCIRef(chartRef string) (string, string, error) { refTagRegexp := regexp.MustCompile(`^(oci://[^:]+(:[0-9]{1,5})?[^:]+):(.*)$`) caps := refTagRegexp.FindStringSubmatch(chartRef) if len(caps) != 4 { - return "", "", errors.Errorf("improperly formatted oci chart reference: %s", chartRef) + return "", "", fmt.Errorf("improperly formatted oci chart reference: %s", chartRef) } chartRef = caps[1] tag := caps[3] @@ -746,7 +746,7 @@ func (m *Manager) findChartURL(name, version, repoURL string, repos map[string]* if err == nil { return url, username, password, false, false, "", "", "", err } - err = errors.Errorf("chart %s not found in %s: %s", name, repoURL, err) + err = fmt.Errorf("chart %s not found in %s: %w", name, repoURL, err) return url, username, password, false, false, "", "", "", err } @@ -802,7 +802,7 @@ func normalizeURL(baseURL, urlOrPath string) (string, error) { } u2, err := url.Parse(baseURL) if err != nil { - return urlOrPath, errors.Wrap(err, "base URL failed to parse") + return urlOrPath, fmt.Errorf("base URL failed to parse: %w", err) } u2.RawPath = path.Join(u2.RawPath, urlOrPath) @@ -820,7 +820,7 @@ func (m *Manager) loadChartRepositories() (map[string]*repo.ChartRepository, err // Load repositories.yaml file rf, err := loadRepoConfig(m.RepositoryConfig) if err != nil { - return indices, errors.Wrapf(err, "failed to load %s", m.RepositoryConfig) + return indices, fmt.Errorf("failed to load %s: %w", m.RepositoryConfig, err) } for _, re := range rf.Repositories { @@ -858,7 +858,7 @@ func writeLock(chartpath string, lock *chart.Lock, legacyLockfile bool) error { // archive a dep chart from local directory and save it into destPath func tarFromLocalDir(chartpath, name, repo, version, destPath string) (string, error) { if !strings.HasPrefix(repo, "file://") { - return "", errors.Errorf("wrong format: chart %s repository %s", name, repo) + return "", fmt.Errorf("wrong format: chart %s repository %s", name, repo) } origPath, err := resolver.GetLocalPath(repo, chartpath) @@ -873,7 +873,7 @@ func tarFromLocalDir(chartpath, name, repo, version, destPath string) (string, e constraint, err := semver.NewConstraint(version) if err != nil { - return "", errors.Wrapf(err, "dependency %s has an invalid version/constraint format", name) + return "", fmt.Errorf("dependency %s has an invalid version/constraint format: %w", name, err) } v, err := semver.NewVersion(ch.Metadata.Version) @@ -886,7 +886,7 @@ func tarFromLocalDir(chartpath, name, repo, version, destPath string) (string, e return ch.Metadata.Version, err } - return "", errors.Errorf("can't get a valid version for dependency %s", name) + return "", fmt.Errorf("can't get a valid version for dependency %s", name) } // The prefix to use for cache keys created by the manager for repo names diff --git a/pkg/engine/engine.go b/pkg/engine/engine.go index df3a600a3..c48840f29 100644 --- a/pkg/engine/engine.go +++ b/pkg/engine/engine.go @@ -17,6 +17,7 @@ limitations under the License. package engine import ( + "errors" "fmt" "log" "path" @@ -26,7 +27,6 @@ import ( "strings" "text/template" - "github.com/pkg/errors" "k8s.io/client-go/rest" "helm.sh/helm/v3/pkg/chart" @@ -131,7 +131,9 @@ func includeFun(t *template.Template, includedNames map[string]int) func(string, var buf strings.Builder if v, ok := includedNames[name]; ok { if v > recursionMaxNums { - return "", errors.Wrapf(fmt.Errorf("unable to execute template"), "rendering template has a nested reference name: %s", name) + return "", fmt.Errorf( + "rendering template has a nested reference name: %s: %w", + name, errors.New("unable to execute template")) } includedNames[name]++ } else { @@ -149,7 +151,7 @@ func tplFun(parent *template.Template, includedNames map[string]int, strict bool return func(tpl string, vals interface{}) (string, error) { t, err := parent.Clone() if err != nil { - return "", errors.Wrapf(err, "cannot clone template") + return "", fmt.Errorf("cannot clone template: %w", err) } // Re-inject the missingkey option, see text/template issue https://github.com/golang/go/issues/43022 @@ -176,12 +178,12 @@ func tplFun(parent *template.Template, includedNames map[string]int, strict bool // text string. (Maybe we could use a hash appended to the name?) t, err = t.New(parent.Name()).Parse(tpl) if err != nil { - return "", errors.Wrapf(err, "cannot parse template %q", tpl) + return "", fmt.Errorf("cannot parse template %q: %w", tpl, err) } var buf strings.Builder if err := t.Execute(&buf, vals); err != nil { - return "", errors.Wrapf(err, "error during tpl function execution for %q", tpl) + return "", fmt.Errorf("error during tpl function execution for %q: %w", tpl, err) } // See comment in renderWithReferences explaining the hack. @@ -206,7 +208,7 @@ func (e Engine) initFunMap(t *template.Template) { log.Printf("[INFO] Missing required value: %s", warn) return "", nil } - return val, errors.Errorf(warnWrap(warn)) + return val, errors.New(warnWrap(warn)) } else if _, ok := val.(string); ok { if val == "" { if e.LintMode { @@ -214,7 +216,7 @@ func (e Engine) initFunMap(t *template.Template) { log.Printf("[INFO] Missing required value: %s", warn) return "", nil } - return val, errors.Errorf(warnWrap(warn)) + return val, errors.New(warnWrap(warn)) } } return val, nil @@ -258,7 +260,7 @@ func (e Engine) render(tpls map[string]renderable) (rendered map[string]string, // template engine. defer func() { if r := recover(); r != nil { - err = errors.Errorf("rendering template failed: %v", r) + err = fmt.Errorf("rendering template failed: %v", r) } }() t := template.New("gotpl") diff --git a/pkg/engine/lookup_func.go b/pkg/engine/lookup_func.go index 75e85098d..3bbc6d85b 100644 --- a/pkg/engine/lookup_func.go +++ b/pkg/engine/lookup_func.go @@ -18,10 +18,10 @@ package engine import ( "context" + "fmt" "log" "strings" - "github.com/pkg/errors" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/schema" @@ -102,7 +102,7 @@ func getDynamicClientOnKind(apiversion string, kind string, config *rest.Config) apiRes, err := getAPIResourceForGVK(gvk, config) if err != nil { log.Printf("[ERROR] unable to get apiresource from unstructured: %s , error %s", gvk.String(), err) - return nil, false, errors.Wrapf(err, "unable to get apiresource from unstructured: %s", gvk.String()) + return nil, false, fmt.Errorf("unable to get apiresource from unstructured: %s: %w", gvk.String(), err) } gvr := schema.GroupVersionResource{ Group: apiRes.Group, diff --git a/pkg/getter/getter.go b/pkg/getter/getter.go index 1acb2093d..2225d5f85 100644 --- a/pkg/getter/getter.go +++ b/pkg/getter/getter.go @@ -18,11 +18,10 @@ package getter import ( "bytes" + "fmt" "net/http" "time" - "github.com/pkg/errors" - "helm.sh/helm/v3/pkg/cli" "helm.sh/helm/v3/pkg/registry" ) @@ -184,7 +183,7 @@ func (p Providers) ByScheme(scheme string) (Getter, error) { return pp.New() } } - return nil, errors.Errorf("scheme %q not supported", scheme) + return nil, fmt.Errorf("scheme %q not supported", scheme) } const ( diff --git a/pkg/getter/httpgetter.go b/pkg/getter/httpgetter.go index df3dcd910..6eda754cd 100644 --- a/pkg/getter/httpgetter.go +++ b/pkg/getter/httpgetter.go @@ -18,13 +18,12 @@ package getter import ( "bytes" "crypto/tls" + "fmt" "io" "net/http" "net/url" "sync" - "github.com/pkg/errors" - "helm.sh/helm/v3/internal/tlsutil" "helm.sh/helm/v3/internal/urlutil" "helm.sh/helm/v3/internal/version" @@ -66,11 +65,11 @@ func (g *HTTPGetter) get(href string) (*bytes.Buffer, error) { // with the basic auth is the one being fetched. u1, err := url.Parse(g.opts.url) if err != nil { - return nil, errors.Wrap(err, "Unable to parse getter URL") + return nil, fmt.Errorf("Unable to parse getter URL: %w", err) } u2, err := url.Parse(href) if err != nil { - return nil, errors.Wrap(err, "Unable to parse URL getting from") + return nil, fmt.Errorf("Unable to parse URL getting from: %w", err) } // Host on URL (returned from url.Parse) contains the port if present. @@ -93,7 +92,7 @@ func (g *HTTPGetter) get(href string) (*bytes.Buffer, error) { } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { - return nil, errors.Errorf("failed to fetch %s : %s", href, resp.Status) + return nil, fmt.Errorf("failed to fetch %s : %s", href, resp.Status) } buf := bytes.NewBuffer(nil) @@ -130,7 +129,7 @@ func (g *HTTPGetter) httpClient() (*http.Client, error) { if (g.opts.certFile != "" && g.opts.keyFile != "") || g.opts.caFile != "" || g.opts.insecureSkipVerifyTLS { tlsConf, err := tlsutil.NewClientTLS(g.opts.certFile, g.opts.keyFile, g.opts.caFile, g.opts.insecureSkipVerifyTLS) if err != nil { - return nil, errors.Wrap(err, "can't create TLS config for client") + return nil, fmt.Errorf("can't create TLS config for client: %w", err) } sni, err := urlutil.ExtractHostname(g.opts.url) diff --git a/pkg/getter/httpgetter_test.go b/pkg/getter/httpgetter_test.go index 2c38c6154..b1755fdb4 100644 --- a/pkg/getter/httpgetter_test.go +++ b/pkg/getter/httpgetter_test.go @@ -28,8 +28,6 @@ import ( "testing" "time" - "github.com/pkg/errors" - "helm.sh/helm/v3/internal/tlsutil" "helm.sh/helm/v3/internal/version" "helm.sh/helm/v3/pkg/cli" @@ -313,7 +311,7 @@ func TestDownloadTLS(t *testing.T) { tlsSrv := httptest.NewUnstartedServer(http.HandlerFunc(func(_ http.ResponseWriter, _ *http.Request) {})) tlsConf, err := tlsutil.NewClientTLS(pub, priv, ca, insecureSkipTLSverify) if err != nil { - t.Fatal(errors.Wrap(err, "can't create TLS config for client")) + t.Fatal(fmt.Errorf("can't create TLS config for client: %w", err)) } tlsConf.ServerName = "helm.sh" tlsSrv.TLS = tlsConf diff --git a/pkg/getter/plugingetter.go b/pkg/getter/plugingetter.go index a371b52eb..86f666207 100644 --- a/pkg/getter/plugingetter.go +++ b/pkg/getter/plugingetter.go @@ -23,8 +23,6 @@ import ( "path/filepath" "strings" - "github.com/pkg/errors" - "helm.sh/helm/v3/pkg/cli" "helm.sh/helm/v3/pkg/plugin" ) @@ -86,7 +84,7 @@ func (p *pluginGetter) Get(href string, options ...Option) (*bytes.Buffer, error if err := prog.Run(); err != nil { if eerr, ok := err.(*exec.ExitError); ok { os.Stderr.Write(eerr.Stderr) - return nil, errors.Errorf("plugin %q exited with error", p.command) + return nil, fmt.Errorf("plugin %q exited with error", p.command) } return nil, err } diff --git a/pkg/ignore/rules.go b/pkg/ignore/rules.go index 88de407ad..0a5ba544d 100644 --- a/pkg/ignore/rules.go +++ b/pkg/ignore/rules.go @@ -19,13 +19,12 @@ package ignore import ( "bufio" "bytes" + "errors" "io" "log" "os" "path/filepath" "strings" - - "github.com/pkg/errors" ) // HelmIgnore default name of an ignorefile. diff --git a/pkg/kube/client.go b/pkg/kube/client.go index 4d93c91b9..69e53f5d3 100644 --- a/pkg/kube/client.go +++ b/pkg/kube/client.go @@ -20,6 +20,7 @@ import ( "bytes" "context" "encoding/json" + "errors" "fmt" "io" "os" @@ -30,7 +31,6 @@ import ( "time" jsonpatch "github.com/evanphx/json-patch" - "github.com/pkg/errors" batch "k8s.io/api/batch/v1" v1 "k8s.io/api/core/v1" apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" @@ -129,10 +129,10 @@ func (c *Client) IsReachable() error { return errors.New("Kubernetes cluster unreachable") } if err != nil { - return errors.Wrap(err, "Kubernetes cluster unreachable") + return fmt.Errorf("Kubernetes cluster unreachable: %w", err) } if _, err := client.ServerVersion(); err != nil { - return errors.Wrap(err, "Kubernetes cluster unreachable") + return fmt.Errorf("Kubernetes cluster unreachable: %w", err) } return nil } @@ -387,7 +387,7 @@ func (c *Client) BuildTable(reader io.Reader, validate bool) (ResourceList, erro // resource updates, creations, and deletions that were attempted. These can be // used for cleanup or other logging purposes. func (c *Client) Update(original, target ResourceList, force bool) (*Result, error) { - updateErrors := []string{} + updateErrors := []error{} res := &Result{} c.Log("checking %d resources for changes", len(target)) @@ -399,7 +399,7 @@ func (c *Client) Update(original, target ResourceList, force bool) (*Result, err helper := resource.NewHelper(info.Client, info.Mapping).WithFieldManager(getManagedFieldsManager()) if _, err := helper.Get(info.Namespace, info.Name); err != nil { if !apierrors.IsNotFound(err) { - return errors.Wrap(err, "could not get information about the resource") + return fmt.Errorf("could not get information about the resource: %w", err) } // Append the created resource to the results, even if something fails @@ -407,7 +407,7 @@ func (c *Client) Update(original, target ResourceList, force bool) (*Result, err // Since the resource does not exist, create it. if err := createResource(info); err != nil { - return errors.Wrap(err, "failed to create resource") + return fmt.Errorf("failed to create resource: %w", err) } kind := info.Mapping.GroupVersionKind.Kind @@ -418,12 +418,12 @@ func (c *Client) Update(original, target ResourceList, force bool) (*Result, err originalInfo := original.Get(info) if originalInfo == nil { kind := info.Mapping.GroupVersionKind.Kind - return errors.Errorf("no %s with the name %q found", kind, info.Name) + return fmt.Errorf("no %s with the name %q found", kind, info.Name) } if err := updateResource(c, info, originalInfo.Object, force); err != nil { c.Log("error updating the resource %q:\n\t %v", info.Name, err) - updateErrors = append(updateErrors, err.Error()) + updateErrors = append(updateErrors, err) } // Because we check for errors later, append the info regardless res.Updated = append(res.Updated, info) @@ -435,7 +435,7 @@ func (c *Client) Update(original, target ResourceList, force bool) (*Result, err case err != nil: return res, err case len(updateErrors) != 0: - return res, errors.Errorf(strings.Join(updateErrors, " && ")) + return res, joinErrors(updateErrors, " && ") } for _, info := range original.Difference(target) { @@ -620,24 +620,24 @@ func deleteResource(info *resource.Info, policy metav1.DeletionPropagation) erro func createPatch(target *resource.Info, current runtime.Object) ([]byte, types.PatchType, error) { oldData, err := json.Marshal(current) if err != nil { - return nil, types.StrategicMergePatchType, errors.Wrap(err, "serializing current configuration") + return nil, types.StrategicMergePatchType, fmt.Errorf("serializing current configuration: %w", err) } newData, err := json.Marshal(target.Object) if err != nil { - return nil, types.StrategicMergePatchType, errors.Wrap(err, "serializing target configuration") + return nil, types.StrategicMergePatchType, fmt.Errorf("serializing target configuration: %w", err) } // Fetch the current object for the three way merge helper := resource.NewHelper(target.Client, target.Mapping).WithFieldManager(getManagedFieldsManager()) currentObj, err := helper.Get(target.Namespace, target.Name) if err != nil && !apierrors.IsNotFound(err) { - return nil, types.StrategicMergePatchType, errors.Wrapf(err, "unable to get data for current object %s/%s", target.Namespace, target.Name) + return nil, types.StrategicMergePatchType, fmt.Errorf("unable to get data for current object %s/%s: %w", target.Namespace, target.Name, err) } // Even if currentObj is nil (because it was not found), it will marshal just fine currentData, err := json.Marshal(currentObj) if err != nil { - return nil, types.StrategicMergePatchType, errors.Wrap(err, "serializing live configuration") + return nil, types.StrategicMergePatchType, fmt.Errorf("serializing live configuration: %w", err) } // Get a versioned object @@ -660,7 +660,7 @@ func createPatch(target *resource.Info, current runtime.Object) ([]byte, types.P patchMeta, err := strategicpatch.NewPatchMetaFromStruct(versionedObject) if err != nil { - return nil, types.StrategicMergePatchType, errors.Wrap(err, "unable to create patch metadata from object") + return nil, types.StrategicMergePatchType, fmt.Errorf("unable to create patch metadata from object: %w", err) } patch, err := strategicpatch.CreateThreeWayMergePatch(oldData, newData, currentData, patchMeta, true) @@ -679,13 +679,13 @@ func updateResource(c *Client, target *resource.Info, currentObj runtime.Object, var err error obj, err = helper.Replace(target.Namespace, target.Name, true, target.Object) if err != nil { - return errors.Wrap(err, "failed to replace object") + return fmt.Errorf("failed to replace object: %w", err) } c.Log("Replaced %q with kind %s for kind %s", target.Name, currentObj.GetObjectKind().GroupVersionKind().Kind, kind) } else { patch, patchType, err := createPatch(target, currentObj) if err != nil { - return errors.Wrap(err, "failed to create patch") + return fmt.Errorf("failed to create patch: %w", err) } if patch == nil || string(patch) == "{}" { @@ -693,7 +693,7 @@ func updateResource(c *Client, target *resource.Info, currentObj runtime.Object, // This needs to happen to make sure that Helm has the latest info from the API // Otherwise there will be no labels and other functions that use labels will panic if err := target.Get(); err != nil { - return errors.Wrap(err, "failed to refresh resource information") + return fmt.Errorf("failed to refresh resource information: %w", err) } return nil } @@ -701,7 +701,7 @@ func updateResource(c *Client, target *resource.Info, currentObj runtime.Object, c.Log("Patch %s %q in namespace %s", kind, target.Name, target.Namespace) obj, err = helper.Patch(target.Namespace, target.Name, patchType, patch, nil) if err != nil { - return errors.Wrapf(err, "cannot patch %q with kind %s", target.Name, kind) + return fmt.Errorf("cannot patch %q with kind %s: %w", target.Name, kind, err) } } @@ -759,7 +759,7 @@ func (c *Client) watchUntilReady(timeout time.Duration, info *resource.Info) err case watch.Error: // Handle error and return with an error. c.Log("Error event for %s", info.Name) - return true, errors.Errorf("failed to deploy %s", info.Name) + return true, fmt.Errorf("failed to deploy %s", info.Name) default: return false, nil } @@ -773,14 +773,14 @@ func (c *Client) watchUntilReady(timeout time.Duration, info *resource.Info) err func (c *Client) waitForJob(obj runtime.Object, name string) (bool, error) { o, ok := obj.(*batch.Job) if !ok { - return true, errors.Errorf("expected %s to be a *batch.Job, got %T", name, obj) + return true, fmt.Errorf("expected %s to be a *batch.Job, got %T", name, obj) } for _, c := range o.Status.Conditions { if c.Type == batch.JobComplete && c.Status == "True" { return true, nil } else if c.Type == batch.JobFailed && c.Status == "True" { - return true, errors.Errorf("job %s failed: %s", name, c.Reason) + return true, fmt.Errorf("job %s failed: %s", name, c.Reason) } } @@ -794,7 +794,7 @@ func (c *Client) waitForJob(obj runtime.Object, name string) (bool, error) { func (c *Client) waitForPodSuccess(obj runtime.Object, name string) (bool, error) { o, ok := obj.(*v1.Pod) if !ok { - return true, errors.Errorf("expected %s to be a *v1.Pod, got %T", name, obj) + return true, fmt.Errorf("expected %s to be a *v1.Pod, got %T", name, obj) } switch o.Status.Phase { @@ -802,7 +802,7 @@ func (c *Client) waitForPodSuccess(obj runtime.Object, name string) (bool, error c.Log("Pod %s succeeded", o.Name) return true, nil case v1.PodFailed: - return true, errors.Errorf("pod %s failed", o.Name) + return true, fmt.Errorf("pod %s failed", o.Name) case v1.PodPending: c.Log("Pod %s pending", o.Name) case v1.PodRunning: @@ -856,3 +856,27 @@ func (c *Client) WaitAndGetCompletedPodPhase(name string, timeout time.Duration) return v1.PodUnknown, err } + +type joinedErrors struct { + errs []error + sep string +} + +func joinErrors(errs []error, sep string) error { + return &joinedErrors{ + errs: errs, + sep: sep, + } +} + +func (e *joinedErrors) Error() string { + errs := make([]string, 0, len(e.errs)) + for _, err := range e.errs { + errs = append(errs, err.Error()) + } + return strings.Join(errs, e.sep) +} + +func (e *joinedErrors) Unwrap() []error { + return e.errs +} diff --git a/pkg/kube/wait.go b/pkg/kube/wait.go index 36110d0de..ac2787804 100644 --- a/pkg/kube/wait.go +++ b/pkg/kube/wait.go @@ -22,7 +22,6 @@ import ( "net/http" "time" - "github.com/pkg/errors" appsv1 "k8s.io/api/apps/v1" appsv1beta1 "k8s.io/api/apps/v1beta1" appsv1beta2 "k8s.io/api/apps/v1beta2" @@ -153,7 +152,7 @@ func SelectorsForObject(object runtime.Object) (selector labels.Selector, err er case *batchv1.Job: selector, err = metav1.LabelSelectorAsSelector(t.Spec.Selector) case *corev1.Service: - if t.Spec.Selector == nil || len(t.Spec.Selector) == 0 { + if len(t.Spec.Selector) == 0 { return nil, fmt.Errorf("invalid service '%s': Service is defined without a selector", t.Name) } selector = labels.SelectorFromSet(t.Spec.Selector) @@ -162,5 +161,5 @@ func SelectorsForObject(object runtime.Object) (selector labels.Selector, err er return nil, fmt.Errorf("selector for %T not implemented", object) } - return selector, errors.Wrap(err, "invalid label selector") + return selector, fmt.Errorf("invalid label selector: %w", err) } diff --git a/pkg/lint/rules/chartfile.go b/pkg/lint/rules/chartfile.go index 910602b7d..49ab7b9bc 100644 --- a/pkg/lint/rules/chartfile.go +++ b/pkg/lint/rules/chartfile.go @@ -17,13 +17,13 @@ limitations under the License. package rules // import "helm.sh/helm/v3/pkg/lint/rules" import ( + "errors" "fmt" "os" "path/filepath" "github.com/Masterminds/semver/v3" "github.com/asaskevich/govalidator" - "github.com/pkg/errors" "sigs.k8s.io/yaml" "helm.sh/helm/v3/pkg/chart" @@ -81,7 +81,7 @@ func isStringValue(data map[string]interface{}, key string) error { } valueType := fmt.Sprintf("%T", value) if valueType != "string" { - return errors.Errorf("%s should be of type string but it's of type %s", key, valueType) + return fmt.Errorf("%s should be of type string but it's of type %s", key, valueType) } return nil } @@ -97,7 +97,7 @@ func validateChartYamlNotDirectory(chartPath string) error { func validateChartYamlFormat(chartFileError error) error { if chartFileError != nil { - return errors.Errorf("unable to parse YAML\n\t%s", chartFileError.Error()) + return fmt.Errorf("unable to parse YAML\n\t%w", chartFileError) } return nil } @@ -131,9 +131,8 @@ func validateChartVersion(cf *chart.Metadata) error { } version, err := semver.NewVersion(cf.Version) - if err != nil { - return errors.Errorf("version '%s' is not a valid SemVer", cf.Version) + return fmt.Errorf("version '%s' is not a valid SemVer", cf.Version) } c, err := semver.NewConstraint(">0.0.0-0") @@ -143,7 +142,7 @@ func validateChartVersion(cf *chart.Metadata) error { valid, msg := c.Validate(version) if !valid && len(msg) > 0 { - return errors.Errorf("version %v", msg[0]) + return fmt.Errorf("version %v", msg[0]) } return nil @@ -154,9 +153,9 @@ func validateChartMaintainer(cf *chart.Metadata) error { if maintainer.Name == "" { return errors.New("each maintainer requires a name") } else if maintainer.Email != "" && !govalidator.IsEmail(maintainer.Email) { - return errors.Errorf("invalid email '%s' for maintainer '%s'", maintainer.Email, maintainer.Name) + return fmt.Errorf("invalid email '%s' for maintainer '%s'", maintainer.Email, maintainer.Name) } else if maintainer.URL != "" && !govalidator.IsURL(maintainer.URL) { - return errors.Errorf("invalid url '%s' for maintainer '%s'", maintainer.URL, maintainer.Name) + return fmt.Errorf("invalid url '%s' for maintainer '%s'", maintainer.URL, maintainer.Name) } } return nil @@ -165,7 +164,7 @@ func validateChartMaintainer(cf *chart.Metadata) error { func validateChartSources(cf *chart.Metadata) error { for _, source := range cf.Sources { if source == "" || !govalidator.IsRequestURL(source) { - return errors.Errorf("invalid source URL '%s'", source) + return fmt.Errorf("invalid source URL '%s'", source) } } return nil @@ -180,7 +179,7 @@ func validateChartIconPresence(cf *chart.Metadata) error { func validateChartIconURL(cf *chart.Metadata) error { if cf.Icon != "" && !govalidator.IsRequestURL(cf.Icon) { - return errors.Errorf("invalid icon URL '%s'", cf.Icon) + return fmt.Errorf("invalid icon URL '%s'", cf.Icon) } return nil } diff --git a/pkg/lint/rules/chartfile_test.go b/pkg/lint/rules/chartfile_test.go index f4c836cf7..ac4a73f67 100644 --- a/pkg/lint/rules/chartfile_test.go +++ b/pkg/lint/rules/chartfile_test.go @@ -17,13 +17,12 @@ limitations under the License. package rules import ( + "errors" "os" "path/filepath" "strings" "testing" - "github.com/pkg/errors" - "helm.sh/helm/v3/pkg/chart" "helm.sh/helm/v3/pkg/chartutil" "helm.sh/helm/v3/pkg/lint/support" diff --git a/pkg/lint/rules/dependencies.go b/pkg/lint/rules/dependencies.go index f1ab1dcad..65fff649d 100644 --- a/pkg/lint/rules/dependencies.go +++ b/pkg/lint/rules/dependencies.go @@ -20,8 +20,6 @@ import ( "fmt" "strings" - "github.com/pkg/errors" - "helm.sh/helm/v3/pkg/chart" "helm.sh/helm/v3/pkg/chart/loader" "helm.sh/helm/v3/pkg/lint/support" @@ -43,7 +41,7 @@ func Dependencies(linter *support.Linter) { func validateChartFormat(chartError error) error { if chartError != nil { - return errors.Errorf("unable to load chart\n\t%s", chartError) + return fmt.Errorf("unable to load chart\n\t%w", chartError) } return nil } diff --git a/pkg/lint/rules/template.go b/pkg/lint/rules/template.go index 41d1a1bab..5358309e4 100644 --- a/pkg/lint/rules/template.go +++ b/pkg/lint/rules/template.go @@ -19,6 +19,7 @@ package rules import ( "bufio" "bytes" + "errors" "fmt" "io" "os" @@ -27,7 +28,6 @@ import ( "regexp" "strings" - "github.com/pkg/errors" "k8s.io/apimachinery/pkg/api/validation" apipath "k8s.io/apimachinery/pkg/api/validation/path" "k8s.io/apimachinery/pkg/util/validation/field" @@ -222,11 +222,14 @@ func validateAllowedExtension(fileName string) error { } } - return errors.Errorf("file extension '%s' not valid. Valid extensions are .yaml, .yml, .tpl, or .txt", ext) + return fmt.Errorf("file extension '%s' not valid. Valid extensions are .yaml, .yml, .tpl, or .txt", ext) } func validateYamlContent(err error) error { - return errors.Wrap(err, "unable to parse YAML") + if err != nil { + return fmt.Errorf("unable to parse YAML: %w", err) + } + return nil } // validateMetadataName uses the correct validation function for the object @@ -239,7 +242,7 @@ func validateMetadataName(obj *K8sYamlStruct) error { allErrs = append(allErrs, field.Invalid(field.NewPath("metadata").Child("name"), obj.Metadata.Name, msg)) } if len(allErrs) > 0 { - return errors.Wrapf(allErrs.ToAggregate(), "object name does not conform to Kubernetes naming requirements: %q", obj.Metadata.Name) + return fmt.Errorf("object name does not conform to Kubernetes naming requirements: %q: %w", obj.Metadata.Name, allErrs.ToAggregate()) } return nil } @@ -317,6 +320,7 @@ func validateMatchSelector(yamlStruct *K8sYamlStruct, manifest string) error { } return nil } + func validateListAnnotations(yamlStruct *K8sYamlStruct, manifest string) error { if yamlStruct.Kind == "List" { m := struct { diff --git a/pkg/lint/rules/values.go b/pkg/lint/rules/values.go index 538d8381b..5a051fdac 100644 --- a/pkg/lint/rules/values.go +++ b/pkg/lint/rules/values.go @@ -17,11 +17,10 @@ limitations under the License. package rules import ( + "fmt" "os" "path/filepath" - "github.com/pkg/errors" - "helm.sh/helm/v3/pkg/chartutil" "helm.sh/helm/v3/pkg/lint/support" ) @@ -54,7 +53,7 @@ func ValuesWithOverrides(linter *support.Linter, values map[string]interface{}) func validateValuesFileExistence(valuesPath string) error { _, err := os.Stat(valuesPath) if err != nil { - return errors.Errorf("file does not exist") + return fmt.Errorf("file does not exist") } return nil } @@ -62,7 +61,7 @@ func validateValuesFileExistence(valuesPath string) error { func validateValuesFile(valuesPath string, overrides map[string]interface{}) error { values, err := chartutil.ReadValuesFile(valuesPath) if err != nil { - return errors.Wrap(err, "unable to parse YAML") + return fmt.Errorf("unable to parse YAML: %w", err) } // Helm 3.0.0 carried over the values linting from Helm 2.x, which only tests the top diff --git a/pkg/lint/support/message_test.go b/pkg/lint/support/message_test.go index 9e12a638b..55675eeee 100644 --- a/pkg/lint/support/message_test.go +++ b/pkg/lint/support/message_test.go @@ -17,9 +17,8 @@ limitations under the License. package support import ( + "errors" "testing" - - "github.com/pkg/errors" ) var linter = Linter{} diff --git a/pkg/plugin/installer/http_installer.go b/pkg/plugin/installer/http_installer.go index 49274f83c..8e1eb2398 100644 --- a/pkg/plugin/installer/http_installer.go +++ b/pkg/plugin/installer/http_installer.go @@ -19,6 +19,8 @@ import ( "archive/tar" "bytes" "compress/gzip" + "errors" + "fmt" "io" "os" "path" @@ -27,7 +29,6 @@ import ( "strings" securejoin "github.com/cyphar/filepath-securejoin" - "github.com/pkg/errors" "helm.sh/helm/v3/internal/third_party/dep/fs" "helm.sh/helm/v3/pkg/cli" @@ -78,7 +79,7 @@ func NewExtractor(source string) (Extractor, error) { return extractor, nil } } - return nil, errors.Errorf("no extractor implemented yet for %s", source) + return nil, fmt.Errorf("no extractor implemented yet for %s", source) } // NewHTTPInstaller creates a new HttpInstaller. @@ -132,7 +133,7 @@ func (i *HTTPInstaller) Install() error { } if err := i.extractor.Extract(pluginData, i.CacheDir); err != nil { - return errors.Wrap(err, "extracting files from archive") + return fmt.Errorf("extracting files from archive: %w", err) } if !isPlugin(i.CacheDir) { @@ -151,7 +152,7 @@ func (i *HTTPInstaller) Install() error { // Update updates a local repository // Not implemented for now since tarball most likely will be packaged by version func (i *HTTPInstaller) Update() error { - return errors.Errorf("method Update() not implemented for HttpInstaller") + return fmt.Errorf("method Update() not implemented for HttpInstaller") } // Path is overridden because we want to join on the plugin name not the file name @@ -261,7 +262,7 @@ func (g *TarGzExtractor) Extract(buffer *bytes.Buffer, targetDir string) error { case tar.TypeXGlobalHeader, tar.TypeXHeader: continue default: - return errors.Errorf("unknown type: %b in %s", header.Typeflag, header.Name) + return fmt.Errorf("unknown type: %b in %s", header.Typeflag, header.Name) } } return nil diff --git a/pkg/plugin/installer/http_installer_test.go b/pkg/plugin/installer/http_installer_test.go index f0fe36ecd..12b6c1ef7 100644 --- a/pkg/plugin/installer/http_installer_test.go +++ b/pkg/plugin/installer/http_installer_test.go @@ -29,8 +29,6 @@ import ( "syscall" "testing" - "github.com/pkg/errors" - "helm.sh/helm/v3/internal/test/ensure" "helm.sh/helm/v3/pkg/getter" "helm.sh/helm/v3/pkg/helmpath" @@ -150,7 +148,7 @@ func TestHTTPInstallerNonExistentVersion(t *testing.T) { // inject fake http client responding with error httpInstaller.getter = &TestHTTPGetter{ - MockError: errors.Errorf("failed to download plugin for some reason"), + MockError: fmt.Errorf("failed to download plugin for some reason"), } // attempt to install the plugin diff --git a/pkg/plugin/installer/installer.go b/pkg/plugin/installer/installer.go index 6f01494e5..a738311ad 100644 --- a/pkg/plugin/installer/installer.go +++ b/pkg/plugin/installer/installer.go @@ -16,6 +16,7 @@ limitations under the License. package installer import ( + "errors" "fmt" "log" "net/http" @@ -23,8 +24,6 @@ import ( "path/filepath" "strings" - "github.com/pkg/errors" - "helm.sh/helm/v3/pkg/plugin" ) diff --git a/pkg/plugin/installer/local_installer.go b/pkg/plugin/installer/local_installer.go index 759df38be..89de204b3 100644 --- a/pkg/plugin/installer/local_installer.go +++ b/pkg/plugin/installer/local_installer.go @@ -16,10 +16,10 @@ limitations under the License. package installer // import "helm.sh/helm/v3/pkg/plugin/installer" import ( + "errors" + "fmt" "os" "path/filepath" - - "github.com/pkg/errors" ) // ErrPluginNotAFolder indicates that the plugin path is not a folder. @@ -34,7 +34,7 @@ type LocalInstaller struct { func NewLocalInstaller(source string) (*LocalInstaller, error) { src, err := filepath.Abs(source) if err != nil { - return nil, errors.Wrap(err, "unable to get absolute path to plugin") + return nil, fmt.Errorf("unable to get absolute path to plugin: %w", err) } i := &LocalInstaller{ base: newBase(src), diff --git a/pkg/plugin/installer/vcs_installer.go b/pkg/plugin/installer/vcs_installer.go index f7df5b322..96658665b 100644 --- a/pkg/plugin/installer/vcs_installer.go +++ b/pkg/plugin/installer/vcs_installer.go @@ -16,12 +16,13 @@ limitations under the License. package installer // import "helm.sh/helm/v3/pkg/plugin/installer" import ( + "errors" + "fmt" "os" "sort" "github.com/Masterminds/semver/v3" "github.com/Masterminds/vcs" - "github.com/pkg/errors" "helm.sh/helm/v3/internal/third_party/dep/fs" "helm.sh/helm/v3/pkg/helmpath" @@ -144,7 +145,7 @@ func (i *VCSInstaller) solveVersion(repo vcs.Repo) (string, error) { } } - return "", errors.Errorf("requested version %q does not exist for plugin %q", i.Version, i.Repo.Remote()) + return "", fmt.Errorf("requested version %q does not exist for plugin %q", i.Version, i.Repo.Remote()) } // setVersion attempts to checkout the version diff --git a/pkg/plugin/plugin.go b/pkg/plugin/plugin.go index 5bb743481..47d5628ba 100644 --- a/pkg/plugin/plugin.go +++ b/pkg/plugin/plugin.go @@ -24,7 +24,6 @@ import ( "strings" "unicode" - "github.com/pkg/errors" "sigs.k8s.io/yaml" "helm.sh/helm/v3/pkg/cli" @@ -224,12 +223,12 @@ func LoadDir(dirname string) (*Plugin, error) { pluginfile := filepath.Join(dirname, PluginFileName) data, err := os.ReadFile(pluginfile) if err != nil { - return nil, errors.Wrapf(err, "failed to read plugin at %q", pluginfile) + return nil, fmt.Errorf("failed to read plugin at %q: %w", pluginfile, err) } plug := &Plugin{Dir: dirname} if err := yaml.UnmarshalStrict(data, &plug.Metadata); err != nil { - return nil, errors.Wrapf(err, "failed to load plugin at %q", pluginfile) + return nil, fmt.Errorf("failed to load plugin at %q: %w", pluginfile, err) } return plug, validatePluginData(plug, pluginfile) } @@ -243,7 +242,7 @@ func LoadAll(basedir string) ([]*Plugin, error) { scanpath := filepath.Join(basedir, "*", PluginFileName) matches, err := filepath.Glob(scanpath) if err != nil { - return plugins, errors.Wrapf(err, "failed to find plugins in %q", scanpath) + return plugins, fmt.Errorf("failed to find plugins in %q: %w", scanpath, err) } if matches == nil { diff --git a/pkg/postrender/exec.go b/pkg/postrender/exec.go index 167e737d6..fcf52ffee 100644 --- a/pkg/postrender/exec.go +++ b/pkg/postrender/exec.go @@ -18,11 +18,10 @@ package postrender import ( "bytes" + "fmt" "io" "os/exec" "path/filepath" - - "github.com/pkg/errors" ) type execRender struct { @@ -61,7 +60,7 @@ func (p *execRender) Run(renderedManifests *bytes.Buffer) (*bytes.Buffer, error) }() err = cmd.Run() if err != nil { - return nil, errors.Wrapf(err, "error while running command %s. error output:\n%s", p.binaryPath, stderr.String()) + return nil, fmt.Errorf("error while running command %s. error output:\n%s: %w", p.binaryPath, stderr.String(), err) } return postRendered, nil @@ -102,7 +101,7 @@ func getFullPath(binaryPath string) (string, error) { // the path and is executable checkedPath, err := exec.LookPath(binaryPath) if err != nil { - return "", errors.Wrapf(err, "unable to find binary at %s", binaryPath) + return "", fmt.Errorf("unable to find binary at %s: %w", binaryPath, err) } return filepath.Abs(checkedPath) diff --git a/pkg/provenance/sign.go b/pkg/provenance/sign.go index 7f89ef3f5..240d54af9 100644 --- a/pkg/provenance/sign.go +++ b/pkg/provenance/sign.go @@ -19,12 +19,13 @@ import ( "bytes" "crypto" "encoding/hex" + "errors" + "fmt" "io" "os" "path/filepath" "strings" - "github.com/pkg/errors" "golang.org/x/crypto/openpgp" //nolint "golang.org/x/crypto/openpgp/clearsign" //nolint "golang.org/x/crypto/openpgp/packet" //nolint @@ -143,7 +144,7 @@ func NewFromKeyring(keyringfile, id string) (*Signatory, error) { } } if vague { - return s, errors.Errorf("more than one key contain the id %q", id) + return s, fmt.Errorf("more than one key contain the id %q", id) } s.Entity = candidate @@ -236,12 +237,12 @@ func (s *Signatory) ClearSign(chartpath string) (string, error) { // In other words, if we call Close here, there's a risk that there's an attempt to use the // private key to sign garbage data (since we know that io.Copy failed, `w` won't contain // anything useful). - return "", errors.Wrap(err, "failed to write to clearsign encoder") + return "", fmt.Errorf("failed to write to clearsign encoder: %w", err) } err = w.Close() if err != nil { - return "", errors.Wrap(err, "failed to either sign or armor message block") + return "", fmt.Errorf("failed to either sign or armor message block: %w", err) } return out.String(), nil @@ -254,14 +255,14 @@ func (s *Signatory) Verify(chartpath, sigpath string) (*Verification, error) { if fi, err := os.Stat(fname); err != nil { return ver, err } else if fi.IsDir() { - return ver, errors.Errorf("%s cannot be a directory", fname) + return ver, fmt.Errorf("%s cannot be a directory", fname) } } // First verify the signature sig, err := s.decodeSignature(sigpath) if err != nil { - return ver, errors.Wrap(err, "failed to decode signature") + return ver, fmt.Errorf("failed to decode signature: %w", err) } by, err := s.verifySignature(sig) @@ -283,9 +284,9 @@ func (s *Signatory) Verify(chartpath, sigpath string) (*Verification, error) { sum = "sha256:" + sum basename := filepath.Base(chartpath) if sha, ok := sums.Files[basename]; !ok { - return ver, errors.Errorf("provenance does not contain a SHA for a file named %q", basename) + return ver, fmt.Errorf("provenance does not contain a SHA for a file named %q", basename) } else if sha != sum { - return ver, errors.Errorf("sha256 sum does not match for %s: %q != %q", basename, sha, sum) + return ver, fmt.Errorf("sha256 sum does not match for %s: %q != %q", basename, sha, sum) } ver.FileHash = sum ver.FileName = basename diff --git a/pkg/pusher/ocipusher.go b/pkg/pusher/ocipusher.go index 33296aadd..d2066ab09 100644 --- a/pkg/pusher/ocipusher.go +++ b/pkg/pusher/ocipusher.go @@ -16,6 +16,7 @@ limitations under the License. package pusher import ( + "errors" "fmt" "net" "net/http" @@ -24,8 +25,6 @@ import ( "strings" "time" - "github.com/pkg/errors" - "helm.sh/helm/v3/internal/tlsutil" "helm.sh/helm/v3/pkg/chart/loader" "helm.sh/helm/v3/pkg/registry" @@ -49,7 +48,7 @@ func (pusher *OCIPusher) push(chartRef, href string) error { stat, err := os.Stat(chartRef) if err != nil { if os.IsNotExist(err) { - return errors.Errorf("%s: no such file", chartRef) + return fmt.Errorf("%s: no such file", chartRef) } return err } @@ -113,7 +112,7 @@ func (pusher *OCIPusher) newRegistryClient() (*registry.Client, error) { if (pusher.opts.certFile != "" && pusher.opts.keyFile != "") || pusher.opts.caFile != "" || pusher.opts.insecureSkipTLSverify { tlsConf, err := tlsutil.NewClientTLS(pusher.opts.certFile, pusher.opts.keyFile, pusher.opts.caFile, pusher.opts.insecureSkipTLSverify) if err != nil { - return nil, errors.Wrap(err, "can't create TLS config for client") + return nil, fmt.Errorf("can't create TLS config for client: %w", err) } registryClient, err := registry.NewClient( diff --git a/pkg/pusher/pusher.go b/pkg/pusher/pusher.go index 5b8a9160f..7b8b4312a 100644 --- a/pkg/pusher/pusher.go +++ b/pkg/pusher/pusher.go @@ -17,7 +17,7 @@ limitations under the License. package pusher import ( - "github.com/pkg/errors" + "fmt" "helm.sh/helm/v3/pkg/cli" "helm.sh/helm/v3/pkg/registry" @@ -106,7 +106,7 @@ func (p Providers) ByScheme(scheme string) (Pusher, error) { return pp.New() } } - return nil, errors.Errorf("scheme %q not supported", scheme) + return nil, fmt.Errorf("scheme %q not supported", scheme) } var ociProvider = Provider{ diff --git a/pkg/registry/client.go b/pkg/registry/client.go index 42f736816..309efc9cc 100644 --- a/pkg/registry/client.go +++ b/pkg/registry/client.go @@ -19,6 +19,7 @@ package registry // import "helm.sh/helm/v3/pkg/registry" import ( "context" "encoding/json" + "errors" "fmt" "io" "net/http" @@ -28,7 +29,6 @@ import ( "github.com/Masterminds/semver/v3" "github.com/containerd/containerd/remotes" ocispec "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/pkg/errors" "oras.land/oras-go/pkg/auth" dockerauth "oras.land/oras-go/pkg/auth/docker" "oras.land/oras-go/pkg/content" @@ -423,7 +423,7 @@ func (c *Client) Pull(ref string, options ...PullOption) (*PullResult, error) { } var getManifestErr error if _, manifestData, ok := memoryStore.Get(manifest); !ok { - getManifestErr = errors.Errorf("Unable to retrieve blob with digest %s", manifest.Digest) + getManifestErr = fmt.Errorf("Unable to retrieve blob with digest %s", manifest.Digest) } else { result.Manifest.Data = manifestData } @@ -432,7 +432,7 @@ func (c *Client) Pull(ref string, options ...PullOption) (*PullResult, error) { } var getConfigDescriptorErr error if _, configData, ok := memoryStore.Get(*configDescriptor); !ok { - getConfigDescriptorErr = errors.Errorf("Unable to retrieve blob with digest %s", configDescriptor.Digest) + getConfigDescriptorErr = fmt.Errorf("Unable to retrieve blob with digest %s", configDescriptor.Digest) } else { result.Config.Data = configData var meta *chart.Metadata @@ -447,7 +447,7 @@ func (c *Client) Pull(ref string, options ...PullOption) (*PullResult, error) { if operation.withChart { var getChartDescriptorErr error if _, chartData, ok := memoryStore.Get(*chartDescriptor); !ok { - getChartDescriptorErr = errors.Errorf("Unable to retrieve blob with digest %s", chartDescriptor.Digest) + getChartDescriptorErr = fmt.Errorf("Unable to retrieve blob with digest %s", chartDescriptor.Digest) } else { result.Chart.Data = chartData result.Chart.Digest = chartDescriptor.Digest.String() @@ -460,7 +460,7 @@ func (c *Client) Pull(ref string, options ...PullOption) (*PullResult, error) { if operation.withProv && !provMissing { var getProvDescriptorErr error if _, provData, ok := memoryStore.Get(*provDescriptor); !ok { - getProvDescriptorErr = errors.Errorf("Unable to retrieve blob with digest %s", provDescriptor.Digest) + getProvDescriptorErr = fmt.Errorf("Unable to retrieve blob with digest %s", provDescriptor.Digest) } else { result.Prov.Data = provData result.Prov.Digest = provDescriptor.Digest.String() diff --git a/pkg/registry/util.go b/pkg/registry/util.go index 727cdae03..4ef09567a 100644 --- a/pkg/registry/util.go +++ b/pkg/registry/util.go @@ -29,7 +29,6 @@ import ( "github.com/Masterminds/semver/v3" ocispec "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/pkg/errors" "github.com/sirupsen/logrus" orascontext "oras.land/oras-go/pkg/context" "oras.land/oras-go/pkg/registry" @@ -92,7 +91,7 @@ func GetTagMatchingVersionOrConstraint(tags []string, versionString string) (str } } - return "", errors.Errorf("Could not locate a version matching provided version string %s", versionString) + return "", fmt.Errorf("Could not locate a version matching provided version string %s", versionString) } // extractChartMeta is used to extract a chart metadata from a byte array @@ -208,7 +207,7 @@ func generateChartOCIAnnotations(meta *chart.Metadata, creationTime string) map[ chartOCIAnnotations = addToMap(chartOCIAnnotations, ocispec.AnnotationSource, meta.Sources[0]) } - if meta.Maintainers != nil && len(meta.Maintainers) > 0 { + if len(meta.Maintainers) > 0 { var maintainerSb strings.Builder for maintainerIdx, maintainer := range meta.Maintainers { diff --git a/pkg/releaseutil/manifest_sorter.go b/pkg/releaseutil/manifest_sorter.go index 4b6109929..6aff5268a 100644 --- a/pkg/releaseutil/manifest_sorter.go +++ b/pkg/releaseutil/manifest_sorter.go @@ -17,13 +17,13 @@ limitations under the License. package releaseutil import ( + "fmt" "log" "path" "sort" "strconv" "strings" - "github.com/pkg/errors" "sigs.k8s.io/yaml" "helm.sh/helm/v3/pkg/chartutil" @@ -141,7 +141,7 @@ func (file *manifestFile) sort(result *result) error { var entry SimpleHead if err := yaml.Unmarshal([]byte(m), &entry); err != nil { - return errors.Wrapf(err, "YAML parse error on %s", file.path) + return fmt.Errorf("YAML parse error on %s: %w", file.path, err) } if !hasAnyAnnotation(entry) { diff --git a/pkg/repo/chartrepo.go b/pkg/repo/chartrepo.go index 970e96da2..01748384a 100644 --- a/pkg/repo/chartrepo.go +++ b/pkg/repo/chartrepo.go @@ -28,7 +28,6 @@ import ( "path/filepath" "strings" - "github.com/pkg/errors" "sigs.k8s.io/yaml" "helm.sh/helm/v3/pkg/chart/loader" @@ -63,12 +62,12 @@ type ChartRepository struct { func NewChartRepository(cfg *Entry, getters getter.Providers) (*ChartRepository, error) { u, err := url.Parse(cfg.URL) if err != nil { - return nil, errors.Errorf("invalid chart URL format: %s", cfg.URL) + return nil, fmt.Errorf("invalid chart URL format: %s", cfg.URL) } client, err := getters.ByScheme(u.Scheme) if err != nil { - return nil, errors.Errorf("could not find protocol handler for: %s", u.Scheme) + return nil, fmt.Errorf("could not find protocol handler for: %s", u.Scheme) } return &ChartRepository{ @@ -90,7 +89,7 @@ func (r *ChartRepository) Load() error { return err } if !dirInfo.IsDir() { - return errors.Errorf("%q is not a directory", r.Config.Name) + return fmt.Errorf("%q is not a directory", r.Config.Name) } // FIXME: Why are we recursively walking directories? @@ -187,7 +186,7 @@ func (r *ChartRepository) generateIndex() error { if !r.IndexFile.Has(ch.Name(), ch.Metadata.Version) { if err := r.IndexFile.MustAdd(ch.Metadata, path, r.Config.URL, digest); err != nil { - return errors.Wrapf(err, "failed adding to %s to index", path) + return fmt.Errorf("failed adding to %s to index: %w", path, err) } } // TODO: If a chart exists, but has a different Digest, should we error? @@ -246,7 +245,7 @@ func FindChartInAuthAndTLSAndPassRepoURL(repoURL, username, password, chartName, } idx, err := r.DownloadIndexFile() if err != nil { - return "", errors.Wrapf(err, "looks like %q is not a valid chart repository or cannot be reached", repoURL) + return "", fmt.Errorf("looks like %q is not a valid chart repository or cannot be reached: %w", repoURL, err) } defer func() { os.RemoveAll(filepath.Join(r.CachePath, helmpath.CacheChartsFile(r.Config.Name))) @@ -265,18 +264,18 @@ func FindChartInAuthAndTLSAndPassRepoURL(repoURL, username, password, chartName, } cv, err := repoIndex.Get(chartName, chartVersion) if err != nil { - return "", errors.Errorf("%s not found in %s repository", errMsg, repoURL) + return "", fmt.Errorf("%s not found in %s repository", errMsg, repoURL) } if len(cv.URLs) == 0 { - return "", errors.Errorf("%s has no downloadable URLs", errMsg) + return "", fmt.Errorf("%s has no downloadable URLs", errMsg) } chartURL := cv.URLs[0] absoluteChartURL, err := ResolveReferenceURL(repoURL, chartURL) if err != nil { - return "", errors.Wrap(err, "failed to make chart URL absolute") + return "", fmt.Errorf("failed to make chart URL absolute: %w", err) } return absoluteChartURL, nil @@ -287,7 +286,7 @@ func FindChartInAuthAndTLSAndPassRepoURL(repoURL, username, password, chartName, func ResolveReferenceURL(baseURL, refURL string) (string, error) { parsedRefURL, err := url.Parse(refURL) if err != nil { - return "", errors.Wrapf(err, "failed to parse %s as URL", refURL) + return "", fmt.Errorf("failed to parse %s as URL: %w", refURL, err) } if parsedRefURL.IsAbs() { @@ -296,7 +295,7 @@ func ResolveReferenceURL(baseURL, refURL string) (string, error) { parsedBaseURL, err := url.Parse(baseURL) if err != nil { - return "", errors.Wrapf(err, "failed to parse %s as URL", baseURL) + return "", fmt.Errorf("failed to parse %s as URL: %w", baseURL, err) } // We need a trailing slash for ResolveReference to work, but make sure there isn't already one diff --git a/pkg/repo/index.go b/pkg/repo/index.go index e1ce3c62d..37ce0cc53 100644 --- a/pkg/repo/index.go +++ b/pkg/repo/index.go @@ -19,6 +19,8 @@ package repo import ( "bytes" "encoding/json" + "errors" + "fmt" "log" "os" "path" @@ -28,7 +30,6 @@ import ( "time" "github.com/Masterminds/semver/v3" - "github.com/pkg/errors" "sigs.k8s.io/yaml" "helm.sh/helm/v3/internal/fileutil" @@ -110,7 +111,7 @@ func LoadIndexFile(path string) (*IndexFile, error) { } i, err := loadIndex(b, path) if err != nil { - return nil, errors.Wrapf(err, "error loading %s", path) + return nil, fmt.Errorf("error loading %s: %w", path, err) } return i, nil } @@ -126,7 +127,7 @@ func (i IndexFile) MustAdd(md *chart.Metadata, filename, baseURL, digest string) md.APIVersion = chart.APIVersionV1 } if err := md.Validate(); err != nil { - return errors.Wrapf(err, "validate failed for %s", filename) + return fmt.Errorf("validate failed for %s: %w", filename, err) } u := filename @@ -219,7 +220,7 @@ func (i IndexFile) Get(name, version string) (*ChartVersion, error) { return ver, nil } } - return nil, errors.Errorf("no chart version found for %s-%s", name, version) + return nil, fmt.Errorf("no chart version found for %s-%s", name, version) } // WriteFile writes an index file to the given destination path. @@ -332,7 +333,7 @@ func IndexDirectory(dir, baseURL string) (*IndexFile, error) { return index, err } if err := index.MustAdd(c.Metadata, fname, parentURL, hash); err != nil { - return index, errors.Wrapf(err, "failed adding to %s to index", fname) + return index, fmt.Errorf("failed adding to %s to index: %w", fname, err) } } return index, nil diff --git a/pkg/repo/repo.go b/pkg/repo/repo.go index 834d554bd..1addb9277 100644 --- a/pkg/repo/repo.go +++ b/pkg/repo/repo.go @@ -17,11 +17,11 @@ limitations under the License. package repo // import "helm.sh/helm/v3/pkg/repo" import ( + "fmt" "os" "path/filepath" "time" - "github.com/pkg/errors" "sigs.k8s.io/yaml" ) @@ -48,7 +48,7 @@ func LoadFile(path string) (*File, error) { r := new(File) b, err := os.ReadFile(path) if err != nil { - return r, errors.Wrapf(err, "couldn't load repositories file (%s)", path) + return r, fmt.Errorf("couldn't load repositories file (%s): %w", path, err) } err = yaml.Unmarshal(b, r) diff --git a/pkg/storage/driver/cfgmaps.go b/pkg/storage/driver/cfgmaps.go index ce88c662b..de43d027b 100644 --- a/pkg/storage/driver/cfgmaps.go +++ b/pkg/storage/driver/cfgmaps.go @@ -23,7 +23,6 @@ import ( "strings" "time" - "github.com/pkg/errors" v1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -123,7 +122,7 @@ func (cfgmaps *ConfigMaps) Query(labels map[string]string) ([]*rspb.Release, err ls := kblabels.Set{} for k, v := range labels { if errs := validation.IsValidLabelValue(v); len(errs) != 0 { - return nil, errors.Errorf("invalid label value: %q: %s", v, strings.Join(errs, "; ")) + return nil, fmt.Errorf("invalid label value: %q: %s", v, strings.Join(errs, "; ")) } ls[k] = v } diff --git a/pkg/storage/driver/driver.go b/pkg/storage/driver/driver.go index 9c01f3766..3e0f9126f 100644 --- a/pkg/storage/driver/driver.go +++ b/pkg/storage/driver/driver.go @@ -17,10 +17,9 @@ limitations under the License. package driver // import "helm.sh/helm/v3/pkg/storage/driver" import ( + "errors" "fmt" - "github.com/pkg/errors" - rspb "helm.sh/helm/v3/pkg/release" ) diff --git a/pkg/storage/driver/secrets.go b/pkg/storage/driver/secrets.go index 95a7e9032..33de412bf 100644 --- a/pkg/storage/driver/secrets.go +++ b/pkg/storage/driver/secrets.go @@ -23,7 +23,6 @@ import ( "strings" "time" - "github.com/pkg/errors" v1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -69,12 +68,12 @@ func (secrets *Secrets) Get(key string) (*rspb.Release, error) { if apierrors.IsNotFound(err) { return nil, ErrReleaseNotFound } - return nil, errors.Wrapf(err, "get: failed to get %q", key) + return nil, fmt.Errorf("get: failed to get %q: %w", key, err) } // found the secret, decode the base64 data string r, err := decodeRelease(string(obj.Data["release"])) r.Labels = filterSystemLabels(obj.ObjectMeta.Labels) - return r, errors.Wrapf(err, "get: failed to decode data %q", key) + return r, fmt.Errorf("get: failed to decode data %q: %w", key, err) } // List fetches all releases and returns the list releases such @@ -86,7 +85,7 @@ func (secrets *Secrets) List(filter func(*rspb.Release) bool) ([]*rspb.Release, list, err := secrets.impl.List(context.Background(), opts) if err != nil { - return nil, errors.Wrap(err, "list: failed to list") + return nil, fmt.Errorf("list: failed to list: %w", err) } var results []*rspb.Release @@ -115,7 +114,7 @@ func (secrets *Secrets) Query(labels map[string]string) ([]*rspb.Release, error) ls := kblabels.Set{} for k, v := range labels { if errs := validation.IsValidLabelValue(v); len(errs) != 0 { - return nil, errors.Errorf("invalid label value: %q: %s", v, strings.Join(errs, "; ")) + return nil, fmt.Errorf("invalid label value: %q: %s", v, strings.Join(errs, "; ")) } ls[k] = v } @@ -124,7 +123,7 @@ func (secrets *Secrets) Query(labels map[string]string) ([]*rspb.Release, error) list, err := secrets.impl.List(context.Background(), opts) if err != nil { - return nil, errors.Wrap(err, "query: failed to query with labels") + return nil, fmt.Errorf("query: failed to query with labels: %w", err) } if len(list.Items) == 0 { @@ -157,7 +156,7 @@ func (secrets *Secrets) Create(key string, rls *rspb.Release) error { // create a new secret to hold the release obj, err := newSecretsObject(key, rls, lbs) if err != nil { - return errors.Wrapf(err, "create: failed to encode release %q", rls.Name) + return fmt.Errorf("create: failed to encode release %q: %w", rls.Name, err) } // push the secret object out into the kubiverse if _, err := secrets.impl.Create(context.Background(), obj, metav1.CreateOptions{}); err != nil { @@ -165,7 +164,7 @@ func (secrets *Secrets) Create(key string, rls *rspb.Release) error { return ErrReleaseExists } - return errors.Wrap(err, "create: failed to create") + return fmt.Errorf("create: failed to create: %w", err) } return nil } @@ -183,11 +182,11 @@ func (secrets *Secrets) Update(key string, rls *rspb.Release) error { // create a new secret object to hold the release obj, err := newSecretsObject(key, rls, lbs) if err != nil { - return errors.Wrapf(err, "update: failed to encode release %q", rls.Name) + return fmt.Errorf("update: failed to encode release %q: %w", rls.Name, err) } // push the secret object out into the kubiverse _, err = secrets.impl.Update(context.Background(), obj, metav1.UpdateOptions{}) - return errors.Wrap(err, "update: failed to update") + return fmt.Errorf("update: failed to update: %w", err) } // Delete deletes the Secret holding the release named by key. diff --git a/pkg/storage/storage.go b/pkg/storage/storage.go index 0da0688fd..32bba7c41 100644 --- a/pkg/storage/storage.go +++ b/pkg/storage/storage.go @@ -17,11 +17,10 @@ limitations under the License. package storage // import "helm.sh/helm/v3/pkg/storage" import ( + "errors" "fmt" "strings" - "github.com/pkg/errors" - rspb "helm.sh/helm/v3/pkg/release" relutil "helm.sh/helm/v3/pkg/releaseutil" "helm.sh/helm/v3/pkg/storage/driver" @@ -213,7 +212,7 @@ func (s *Storage) removeLeastRecent(name string, max int) error { case 1: return errs[0] default: - return errors.Errorf("encountered %d deletion errors. First is: %s", c, errs[0]) + return fmt.Errorf("encountered %d deletion errors. First is: %w", c, errs[0]) } } @@ -235,7 +234,7 @@ func (s *Storage) Last(name string) (*rspb.Release, error) { return nil, err } if len(h) == 0 { - return nil, errors.Errorf("no revision for release %q", name) + return nil, fmt.Errorf("no revision for release %q", name) } relutil.Reverse(h, relutil.SortByRevision) diff --git a/pkg/storage/storage_test.go b/pkg/storage/storage_test.go index d50e3fbfe..dc83a0afa 100644 --- a/pkg/storage/storage_test.go +++ b/pkg/storage/storage_test.go @@ -17,12 +17,11 @@ limitations under the License. package storage // import "helm.sh/helm/v3/pkg/storage" import ( + "errors" "fmt" "reflect" "testing" - "github.com/pkg/errors" - rspb "helm.sh/helm/v3/pkg/release" "helm.sh/helm/v3/pkg/storage/driver" ) diff --git a/pkg/strvals/literal_parser.go b/pkg/strvals/literal_parser.go index f75655811..d34e5e854 100644 --- a/pkg/strvals/literal_parser.go +++ b/pkg/strvals/literal_parser.go @@ -20,8 +20,6 @@ import ( "fmt" "io" "strconv" - - "github.com/pkg/errors" ) // ParseLiteral parses a set line interpreting the value as a literal string. @@ -102,7 +100,7 @@ func (t *literalParser) key(data map[string]interface{}, nestedNameLevel int) (r if len(key) == 0 { return err } - return errors.Errorf("key %q has no value", string(key)) + return fmt.Errorf("key %q has no value", string(key)) case lastRune == '=': // found end of key: swallow the '=' and get the value @@ -129,7 +127,7 @@ func (t *literalParser) key(data map[string]interface{}, nestedNameLevel int) (r // recurse on sub-tree with remaining data err := t.key(inner, nestedNameLevel) if err == nil && len(inner) == 0 { - return errors.Errorf("key map %q has no value", string(key)) + return fmt.Errorf("key map %q has no value", string(key)) } if len(inner) != 0 { set(data, string(key), inner) @@ -140,7 +138,7 @@ func (t *literalParser) key(data map[string]interface{}, nestedNameLevel int) (r // We are in a list index context, so we need to set an index. i, err := t.keyIndex() if err != nil { - return errors.Wrap(err, "error parsing index") + return fmt.Errorf("error parsing index: %w", err) } kk := string(key) @@ -178,7 +176,7 @@ func (t *literalParser) listItem(list []interface{}, i, nestedNameLevel int) ([] switch key, lastRune, err := runesUntilLiteral(t.sc, stop); { case len(key) > 0: - return list, errors.Errorf("unexpected data at end of array index: %q", key) + return list, fmt.Errorf("unexpected data at end of array index: %q", key) case err != nil: return list, err @@ -214,7 +212,7 @@ func (t *literalParser) listItem(list []interface{}, i, nestedNameLevel int) ([] // now we have a nested list. Read the index and handle. nextI, err := t.keyIndex() if err != nil { - return list, errors.Wrap(err, "error parsing index") + return list, fmt.Errorf("error parsing index: %w", err) } var crtList []interface{} if len(list) > i { @@ -233,7 +231,7 @@ func (t *literalParser) listItem(list []interface{}, i, nestedNameLevel int) ([] return setIndex(list, i, list2) default: - return nil, errors.Errorf("parse error: unexpected token %v", lastRune) + return nil, fmt.Errorf("parse error: unexpected token %v", lastRune) } } diff --git a/pkg/strvals/parser.go b/pkg/strvals/parser.go index a0e8d66d1..c65e98c84 100644 --- a/pkg/strvals/parser.go +++ b/pkg/strvals/parser.go @@ -18,13 +18,13 @@ package strvals import ( "bytes" "encoding/json" + "errors" "fmt" "io" "strconv" "strings" "unicode" - "github.com/pkg/errors" "sigs.k8s.io/yaml" ) @@ -189,14 +189,14 @@ func (t *parser) key(data map[string]interface{}, nestedNameLevel int) (reterr e if len(k) == 0 { return err } - return errors.Errorf("key %q has no value", string(k)) + return fmt.Errorf("key %q has no value", string(k)) //set(data, string(k), "") //return err case last == '[': // We are in a list index context, so we need to set an index. i, err := t.keyIndex() if err != nil { - return errors.Wrap(err, "error parsing index") + return fmt.Errorf("error parsing index: %w", err) } kk := string(k) // Find or create target list @@ -261,7 +261,7 @@ func (t *parser) key(data map[string]interface{}, nestedNameLevel int) (reterr e case last == ',': // No value given. Set the value to empty string. Return error. set(data, string(k), "") - return errors.Errorf("key %q has no value (cannot end with ,)", string(k)) + return fmt.Errorf("key %q has no value (cannot end with ,)", string(k)) case last == '.': // Check value name is within the maximum nested name level nestedNameLevel++ @@ -278,7 +278,7 @@ func (t *parser) key(data map[string]interface{}, nestedNameLevel int) (reterr e // Recurse e := t.key(inner, nestedNameLevel) if e == nil && len(inner) == 0 { - return errors.Errorf("key map %q has no value", string(k)) + return fmt.Errorf("key map %q has no value", string(k)) } if len(inner) != 0 { set(data, string(k), inner) @@ -332,6 +332,7 @@ func (t *parser) keyIndex() (int, error) { return strconv.Atoi(string(v)) } + func (t *parser) listItem(list []interface{}, i, nestedNameLevel int) ([]interface{}, error) { if i < 0 { return list, fmt.Errorf("negative %d index not allowed", i) @@ -339,7 +340,7 @@ func (t *parser) listItem(list []interface{}, i, nestedNameLevel int) ([]interfa stop := runeSet([]rune{'[', '.', '='}) switch k, last, err := runesUntil(t.sc, stop); { case len(k) > 0: - return list, errors.Errorf("unexpected data at end of array index: %q", k) + return list, fmt.Errorf("unexpected data at end of array index: %q", k) case err != nil: return list, err case last == '=': @@ -394,7 +395,7 @@ func (t *parser) listItem(list []interface{}, i, nestedNameLevel int) ([]interfa // now we have a nested list. Read the index and handle. nextI, err := t.keyIndex() if err != nil { - return list, errors.Wrap(err, "error parsing index") + return list, fmt.Errorf("error parsing index: %w", err) } var crtList []interface{} if len(list) > i { @@ -430,7 +431,7 @@ func (t *parser) listItem(list []interface{}, i, nestedNameLevel int) ([]interfa } return setIndex(list, i, inner) default: - return nil, errors.Errorf("parse error: unexpected token %v", last) + return nil, fmt.Errorf("parse error: unexpected token %v", last) } } diff --git a/pkg/uploader/chart_uploader.go b/pkg/uploader/chart_uploader.go index d7e940406..b1cd6e666 100644 --- a/pkg/uploader/chart_uploader.go +++ b/pkg/uploader/chart_uploader.go @@ -20,8 +20,6 @@ import ( "io" "net/url" - "github.com/pkg/errors" - "helm.sh/helm/v3/pkg/pusher" "helm.sh/helm/v3/pkg/registry" ) @@ -42,7 +40,7 @@ type ChartUploader struct { func (c *ChartUploader) UploadTo(ref, remote string) error { u, err := url.Parse(remote) if err != nil { - return errors.Errorf("invalid chart URL format: %s", remote) + return fmt.Errorf("invalid chart URL format: %s", remote) } if u.Scheme == "" {