Merge pull request #13460 from justenstall/stdlib-errors-2

fix: replace "github.com/pkg/errors" with stdlib "errors" package
pull/30786/head
George Jenkins 5 months ago committed by GitHub
commit ecf1730689
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -20,6 +20,8 @@ linters:
deny:
- pkg: github.com/hashicorp/go-multierror
desc: "use errors instead"
- pkg: github.com/pkg/errors
desc: "use errors instead"
dupl:
threshold: 400
exclusions:

@ -26,7 +26,6 @@ require (
github.com/moby/term v0.5.2
github.com/opencontainers/image-spec v1.1.1
github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5
github.com/pkg/errors v0.9.1
github.com/rubenv/sql-migrate v1.8.0
github.com/santhosh-tekuri/jsonschema/v6 v6.0.1
github.com/spf13/cobra v1.9.1
@ -120,6 +119,7 @@ require (
github.com/onsi/gomega v1.36.2 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_golang v1.20.5 // indirect
github.com/prometheus/client_model v0.6.1 // indirect

@ -18,14 +18,15 @@ package resolver
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io/fs"
"os"
"path/filepath"
"strings"
"time"
"github.com/Masterminds/semver/v3"
"github.com/pkg/errors"
chart "helm.sh/helm/v4/pkg/chart/v2"
"helm.sh/helm/v4/pkg/chart/v2/loader"
@ -60,7 +61,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 +125,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 +152,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 +193,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)
@ -252,8 +253,8 @@ func GetLocalPath(repo, chartpath string) (string, error) {
depPath = filepath.Join(chartpath, p)
}
if _, err = os.Stat(depPath); os.IsNotExist(err) {
return "", errors.Errorf("directory %s not found", depPath)
if _, err = os.Stat(depPath); errors.Is(err, fs.ErrNotExist) {
return "", fmt.Errorf("directory %s not found", depPath)
} else if err != nil {
return "", err
}

@ -21,12 +21,11 @@ limitations under the License.
package sympath
import (
"fmt"
"log/slog"
"os"
"path/filepath"
"sort"
"github.com/pkg/errors"
)
// Walk walks the file tree rooted at root, calling walkFn for each file or directory
@ -69,7 +68,7 @@ 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.
slog.Info("found symbolic link in path. Contents of linked file included and used", "path", path, "resolved", resolved)

@ -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
}

@ -32,13 +32,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package fs
import (
"errors"
"fmt"
"io"
"io/fs"
"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 +52,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 +70,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 err := os.RemoveAll(src); err != nil {
return fmt.Errorf("cannot delete %s: %w", src, err)
}
return errors.Wrapf(os.RemoveAll(src), "cannot delete %s", src)
return nil
}
var (
@ -107,7 +112,7 @@ func CopyDir(src, dst string) error {
}
_, err = os.Stat(dst)
if err != nil && !os.IsNotExist(err) {
if err != nil && !errors.Is(err, fs.ErrNotExist) {
return err
}
if err == nil {
@ -115,12 +120,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 +134,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 +154,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 +231,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
}

@ -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)

@ -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

@ -18,6 +18,7 @@ package action
import (
"bytes"
"errors"
"fmt"
"io"
"log/slog"
@ -27,7 +28,6 @@ import (
"strings"
"text/template"
"github.com/pkg/errors"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/client-go/discovery"
@ -105,7 +105,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())
}
}
@ -220,7 +220,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)
}
}
@ -241,13 +241,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.
@ -260,7 +260,7 @@ func (cfg *Configuration) getCapabilities() (*chartutil.Capabilities, error) {
slog.Warn("the kubernetes server has an orphaned API service", slog.Any("error", err))
slog.Warn("to fix this, kubectl delete apiservice <service-name>")
} else {
return nil, errors.Wrap(err, "could not get apiVersions from Kubernetes")
return nil, fmt.Errorf("could not get apiVersions from Kubernetes: %w", err)
}
}
@ -280,7 +280,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)
@ -296,7 +296,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 {
@ -310,7 +310,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
@ -399,11 +399,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

@ -19,7 +19,7 @@ package action
import (
"log/slog"
"github.com/pkg/errors"
"fmt"
chartutil "helm.sh/helm/v4/pkg/chart/v2/util"
release "helm.sh/helm/v4/pkg/release/v1"
@ -52,7 +52,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)
}
slog.Debug("getting history for release", "release", name)

@ -25,10 +25,8 @@ import (
"helm.sh/helm/v4/pkg/kube"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/pkg/errors"
"gopkg.in/yaml.v3"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
release "helm.sh/helm/v4/pkg/release/v1"
helmtime "helm.sh/helm/v4/pkg/time"
@ -65,7 +63,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
@ -84,12 +82,12 @@ 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)
}
waiter, err := cfg.KubeClient.GetWaiter(waitStrategy)
if err != nil {
return errors.Wrapf(err, "unable to get waiter")
return fmt.Errorf("unable to get waiter: %w", err)
}
// Watch hook resources until they have completed
err = waiter.WatchUntilReady(resources, timeout)
@ -159,11 +157,11 @@ 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, "; ")
}
waiter, err := cfg.KubeClient.GetWaiter(waitStrategy)
@ -239,7 +237,7 @@ func (cfg *Configuration) deriveNamespace(h *release.Hook, namespace string) (st
}{}
err := yaml.Unmarshal([]byte(h.Manifest), &tmp)
if err != nil {
return "", errors.Wrapf(err, "unable to parse metadata.namespace from kubernetes manifest for output logs hook %s", h.Path)
return "", fmt.Errorf("unable to parse metadata.namespace from kubernetes manifest for output logs hook %s: %w", h.Path, err)
}
if tmp.Metadata.Namespace == "" {
return namespace, nil

@ -19,8 +19,10 @@ package action
import (
"bytes"
"context"
"errors"
"fmt"
"io"
"io/fs"
"log/slog"
"net/url"
"os"
@ -32,7 +34,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"
@ -165,7 +166,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
@ -176,14 +177,14 @@ func (i *Install) installCRDs(crds []chart.CRD) error {
slog.Debug("CRD is already present. Skipping", "crd", 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...)
}
if len(totalItems) > 0 {
waiter, err := i.cfg.KubeClient.GetWaiter(i.WaitStrategy)
if err != nil {
return errors.Wrapf(err, "unable to get waiter")
return fmt.Errorf("unable to get waiter: %w", err)
}
// Give time for the CRD to be recognized.
if err := waiter.Wait(totalItems, 60*time.Second); err != nil {
@ -239,24 +240,24 @@ func (i *Install) RunWithContext(ctx context.Context, chrt *chart.Chart, vals ma
if !i.ClientOnly {
if err := i.cfg.KubeClient.IsReachable(); err != nil {
slog.Error(fmt.Sprintf("cluster reachability check failed: %v", err))
return nil, errors.Wrap(err, "cluster reachability check failed")
return nil, fmt.Errorf("cluster reachability check failed: %w", err)
}
}
// HideSecret must be used with dry run. Otherwise, return an error.
if !i.isDryRun() && i.HideSecret {
slog.Error("hiding Kubernetes secrets requires a dry-run mode")
return nil, errors.New("Hiding Kubernetes secrets requires a dry-run mode")
return nil, errors.New("hiding Kubernetes secrets requires a dry-run mode")
}
if err := i.availableName(); err != nil {
slog.Error("release name check failed", slog.Any("error", err))
return nil, errors.Wrap(err, "release name check failed")
return nil, fmt.Errorf("release name check failed: %w", err)
}
if err := chartutil.ProcessDependencies(chrt, vals); err != nil {
slog.Error("chart dependencies processing failed", slog.Any("error", err))
return nil, errors.Wrap(err, "chart dependencies processing failed")
return nil, fmt.Errorf("chart dependencies processing failed: %w", err)
}
var interactWithRemote bool
@ -342,7 +343,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.
@ -364,7 +365,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)
}
}
@ -525,9 +526,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
@ -545,7 +546,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() {
@ -653,7 +654,7 @@ func createOrOpenFile(filename string, appendData bool) (*os.File, error) {
func ensureDirectoryForFile(file string) error {
baseDir := path.Dir(file)
_, err := os.Stat(baseDir)
if err != nil && !os.IsNotExist(err) {
if err != nil && !errors.Is(err, fs.ErrNotExist) {
return err
}
@ -675,7 +676,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 {
@ -740,7 +741,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
}
@ -776,7 +777,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{

@ -19,8 +19,10 @@ package action
import (
"bytes"
"context"
"errors"
"fmt"
"io"
"io/fs"
"net/http"
"os"
"path/filepath"
@ -210,7 +212,7 @@ func TestInstallReleaseWithTakeOwnership_ResourceOwnedNoFlag(t *testing.T) {
instAction := installActionWithConfig(config)
_, err := instAction.Run(buildChart(), nil)
is.Error(err)
is.Contains(err.Error(), "Unable to continue with install")
is.Contains(err.Error(), "unable to continue with install")
}
func TestInstallReleaseWithValues(t *testing.T) {
@ -756,7 +758,7 @@ func TestInstallReleaseOutputDir(t *testing.T) {
test.AssertGoldenFile(t, filepath.Join(dir, "hello/templates/rbac"), "rbac.txt")
_, err = os.Stat(filepath.Join(dir, "hello/templates/empty"))
is.True(os.IsNotExist(err))
is.True(errors.Is(err, fs.ErrNotExist))
}
func TestInstallOutputDirWithReleaseName(t *testing.T) {
@ -792,7 +794,7 @@ func TestInstallOutputDirWithReleaseName(t *testing.T) {
test.AssertGoldenFile(t, filepath.Join(newDir, "hello/templates/rbac"), "rbac.txt")
_, err = os.Stat(filepath.Join(newDir, "hello/templates/empty"))
is.True(os.IsNotExist(err))
is.True(errors.Is(err, fs.ErrNotExist))
}
func TestNameAndChart(t *testing.T) {

@ -17,12 +17,11 @@ limitations under the License.
package action
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/pkg/errors"
chartutil "helm.sh/helm/v4/pkg/chart/v2/util"
"helm.sh/helm/v4/pkg/lint"
"helm.sh/helm/v4/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.RunAll(

@ -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/v4/pkg/chart/v2/loader"
@ -105,7 +105,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 {

@ -22,8 +22,6 @@ import (
"path/filepath"
"strings"
"github.com/pkg/errors"
chartutil "helm.sh/helm/v4/pkg/chart/v2/util"
"helm.sh/helm/v4/pkg/cli"
"helm.sh/helm/v4/pkg/downloader"
@ -111,7 +109,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)
}
@ -163,11 +161,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)

@ -24,7 +24,6 @@ import (
"sort"
"time"
"github.com/pkg/errors"
v1 "k8s.io/api/core/v1"
chartutil "helm.sh/helm/v4/pkg/chart/v2/util"
@ -64,7 +63,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
@ -113,7 +112,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...)
@ -130,14 +129,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)
}
}
}

@ -23,8 +23,6 @@ import (
"strings"
"time"
"github.com/pkg/errors"
chartutil "helm.sh/helm/v4/pkg/chart/v2/util"
"helm.sh/helm/v4/pkg/kube"
release "helm.sh/helm/v4/pkg/release/v1"
@ -95,7 +93,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 {
@ -127,7 +125,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)
}
slog.Debug("rolling back", "name", name, "currentVersion", currentRelease.Version, "targetVersion", previousVersion)
@ -169,11 +167,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
@ -188,7 +186,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)
@ -204,11 +202,9 @@ func (r *Rollback) performRollback(currentRelease, targetRelease *release.Releas
slog.Debug("cleanup on fail set, cleaning up resources", "count", 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, ", ")))
}
slog.Debug("resource cleanup complete")
}
@ -226,21 +222,21 @@ func (r *Rollback) performRollback(currentRelease, targetRelease *release.Releas
}
waiter, err := r.cfg.KubeClient.GetWaiter(r.WaitStrategy)
if err != nil {
return nil, errors.Wrap(err, "unable to set metadata visitor from target release")
return nil, fmt.Errorf("unable to set metadata visitor from target release: %w", err)
}
if r.WaitForJobs {
if err := waiter.WaitWithJobs(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)
}
} else {
if err := waiter.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)
}
}

@ -21,7 +21,6 @@ import (
"fmt"
"strings"
"github.com/pkg/errors"
"k8s.io/cli-runtime/pkg/printers"
"sigs.k8s.io/yaml"
@ -105,7 +104,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 {

@ -17,12 +17,11 @@ limitations under the License.
package action
import (
"fmt"
"log/slog"
"strings"
"time"
"github.com/pkg/errors"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
chartutil "helm.sh/helm/v4/pkg/chart/v2/util"
@ -76,7 +75,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)
@ -84,7 +83,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
@ -98,11 +97,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)
}
slog.Debug("uninstall: deleting release", "name", name)
@ -128,7 +127,7 @@ func (u *Uninstall) Run(name string) (*release.UninstallReleaseResponse, error)
deletedResources, kept, errs := u.deleteRelease(rel)
if errs != nil {
slog.Debug("uninstall: Failed to delete release", slog.Any("error", errs))
return nil, errors.Errorf("failed to delete release: %s", name)
return nil, fmt.Errorf("failed to delete release: %s", name)
}
if kept != "" {
@ -157,12 +156,12 @@ func (u *Uninstall) Run(name string) (*release.UninstallReleaseResponse, error)
slog.Debug("purge requested", "release", 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
@ -173,7 +172,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
}
@ -187,12 +186,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
@ -206,7 +221,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)
@ -222,7 +237,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 {

@ -19,13 +19,13 @@ package action
import (
"bytes"
"context"
"errors"
"fmt"
"log/slog"
"strings"
"sync"
"time"
"github.com/pkg/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/cli-runtime/pkg/resource"
@ -161,7 +161,7 @@ func (u *Upgrade) RunWithContext(ctx context.Context, name string, chart *chart.
}
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)
}
slog.Debug("preparing upgrade", "name", name)
@ -205,7 +205,7 @@ func (u *Upgrade) prepareUpgrade(name string, chart *chart.Chart, vals map[strin
// HideSecret must be used with dry run. Otherwise, return an error.
if !u.isDryRun() && u.HideSecret {
return nil, nil, errors.New("Hiding Kubernetes secrets requires a dry-run mode")
return nil, nil, errors.New("hiding Kubernetes secrets requires a dry-run mode")
}
// finds the last non-deleted release with the given name
@ -316,15 +316,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.
@ -353,7 +353,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 {
@ -496,11 +496,14 @@ func (u *Upgrade) failRelease(rel *release.Release, created kube.ResourceList, e
slog.Debug("cleanup on fail set", "cleaning_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, ", "),
),
)
}
slog.Debug("resource cleanup complete")
}
@ -512,7 +515,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
@ -522,7 +525,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)
@ -538,9 +541,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
@ -568,7 +571,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)
@ -614,21 +617,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)
}
}
}

@ -19,7 +19,6 @@ package action
import (
"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 +51,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 +75,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.
@ -113,11 +112,7 @@ func checkOwnership(obj runtime.Object, releaseName, releaseNamespace string) er
}
if len(errs) > 0 {
err := errors.New("invalid ownership metadata")
for _, e := range errs {
err = fmt.Errorf("%w; %s", err, e)
}
return err
return fmt.Errorf("invalid ownership metadata; %w", joinErrors(errs, "; "))
}
return nil

@ -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"
chart "helm.sh/helm/v4/pkg/chart/v2"
)
@ -170,7 +169,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")

@ -23,8 +23,6 @@ import (
"path/filepath"
"strings"
"github.com/pkg/errors"
"helm.sh/helm/v4/internal/sympath"
chart "helm.sh/helm/v4/pkg/chart/v2"
"helm.sh/helm/v4/pkg/ignore"
@ -107,7 +105,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)

@ -20,13 +20,14 @@ import (
"bufio"
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
"log"
"os"
"path/filepath"
"strings"
"github.com/pkg/errors"
utilyaml "k8s.io/apimachinery/pkg/util/yaml"
"sigs.k8s.io/yaml"
@ -48,7 +49,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.
@ -86,7 +86,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.
@ -104,12 +104,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":
values, err := LoadValues(bytes.NewReader(f.Data))
if err != nil {
return c, errors.Wrap(err, "cannot load values.yaml")
return c, fmt.Errorf("cannot load values.yaml: %w", err)
}
c.Values = values
case f.Name == "values.schema.json":
@ -125,7 +125,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})
@ -134,7 +134,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)
@ -163,7 +163,7 @@ func LoadFiles(files []*BufferedFile) (*chart.Chart, error) {
}
if c.Metadata == nil {
return c, errors.New("Chart.yaml file is missing")
return c, errors.New("Chart.yaml file is missing") //nolint:staticcheck
}
if err := c.Validate(); err != nil {
@ -179,7 +179,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))
@ -199,7 +199,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)
}
@ -221,13 +221,13 @@ func LoadValues(data io.Reader) (map[string]interface{}, error) {
if err == io.EOF {
break
}
return nil, errors.Wrap(err, "error reading yaml document")
return nil, fmt.Errorf("error reading yaml document: %w", err)
}
if err := yaml.Unmarshal(raw, &currentMap, func(d *json.Decoder) *json.Decoder {
d.UseNumber()
return d
}); err != nil {
return nil, errors.Wrap(err, "cannot unmarshal yaml document")
return nil, fmt.Errorf("cannot unmarshal yaml document: %w", err)
}
values = MergeMaps(values, currentMap)
}

@ -17,10 +17,12 @@ limitations under the License.
package util
import (
"errors"
"fmt"
"io/fs"
"os"
"path/filepath"
"github.com/pkg/errors"
"sigs.k8s.io/yaml"
chart "helm.sh/helm/v4/pkg/chart/v2"
@ -75,17 +77,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)
if _, err := os.Stat(chartYaml); errors.Is(err, fs.ErrNotExist) {
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)
@ -93,10 +95,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

@ -21,7 +21,6 @@ import (
"log"
"github.com/mitchellh/copystructure"
"github.com/pkg/errors"
chart "helm.sh/helm/v4/pkg/chart/v2"
)
@ -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{})

@ -24,7 +24,6 @@ import (
"regexp"
"strings"
"github.com/pkg/errors"
"sigs.k8s.io/yaml"
chart "helm.sh/helm/v4/pkg/chart/v2"
@ -651,7 +650,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
@ -666,12 +665,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
@ -715,12 +714,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

@ -17,12 +17,13 @@ limitations under the License.
package util
import (
"errors"
"fmt"
"io"
"os"
"path/filepath"
securejoin "github.com/cyphar/filepath-securejoin"
"github.com/pkg/errors"
"sigs.k8s.io/yaml"
chart "helm.sh/helm/v4/pkg/chart/v2"
@ -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
}

@ -18,11 +18,11 @@ package util
import (
"bytes"
"errors"
"fmt"
"log/slog"
"strings"
"github.com/pkg/errors"
"github.com/santhosh-tekuri/jsonschema/v6"
chart "helm.sh/helm/v4/pkg/chart/v2"

@ -20,12 +20,13 @@ import (
"archive/tar"
"compress/gzip"
"encoding/json"
"errors"
"fmt"
"io/fs"
"os"
"path/filepath"
"time"
"github.com/pkg/errors"
"sigs.k8s.io/yaml"
chart "helm.sh/helm/v4/pkg/chart/v2"
@ -45,7 +46,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 +90,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,22 +106,22 @@ 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)
filename = filepath.Join(outDir, filename)
dir := filepath.Dir(filename)
if stat, err := os.Stat(dir); err != nil {
if os.IsNotExist(err) {
if errors.Is(err, fs.ErrNotExist) {
if err2 := os.MkdirAll(dir, 0755); err2 != nil {
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)
@ -203,7 +204,7 @@ func writeTarContents(out *tar.Writer, c *chart.Chart, prefix string) error {
// Save values.schema.json if it exists
if c.Schema != nil {
if !json.Valid(c.Schema) {
return errors.New("Invalid JSON in " + SchemafileName)
return errors.New("invalid JSON in " + SchemafileName)
}
if err := writeToTar(out, filepath.Join(base, SchemafileName), c.Schema); err != nil {
return err

@ -17,10 +17,9 @@ limitations under the License.
package util
import (
"errors"
"fmt"
"regexp"
"github.com/pkg/errors"
)
// validName is a regular expression for resource names.

@ -18,12 +18,12 @@ package util
import (
"encoding/json"
"errors"
"fmt"
"io"
"os"
"strings"
"github.com/pkg/errors"
"sigs.k8s.io/yaml"
chart "helm.sh/helm/v4/pkg/chart/v2"
@ -169,8 +169,7 @@ func ToRenderValuesWithSchemaValidation(chrt *chart.Chart, chrtVals map[string]i
if !skipSchemaValidation {
if err := ValidateAgainstSchema(chrt, vals); err != nil {
errFmt := "values don't meet the specifications of the schema(s) in the following chart(s):\n%s"
return top, fmt.Errorf(errFmt, err.Error())
return top, fmt.Errorf("values don't meet the specifications of the schema(s) in the following chart(s):\n%w", err)
}
}

@ -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
}

@ -19,13 +19,12 @@ package values
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/url"
"os"
"strings"
"github.com/pkg/errors"
"helm.sh/helm/v4/pkg/chart/v2/loader"
"helm.sh/helm/v4/pkg/getter"
"helm.sh/helm/v4/pkg/strvals"
@ -54,7 +53,7 @@ func (opts *Options) MergeValues(p getter.Providers) (map[string]interface{}, er
}
currentMap, err := loader.LoadValues(bytes.NewReader(raw))
if 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 = loader.MergeMaps(base, currentMap)
@ -67,13 +66,13 @@ func (opts *Options) MergeValues(p getter.Providers) (map[string]interface{}, er
// If value is JSON object format, parse it as map
var jsonMap map[string]interface{}
if err := json.Unmarshal([]byte(trimmedValue), &jsonMap); err != nil {
return nil, errors.Errorf("failed parsing --set-json data JSON: %s", value)
return nil, fmt.Errorf("failed parsing --set-json data JSON: %s", value)
}
base = loader.MergeMaps(base, jsonMap)
} else {
// Otherwise, parse it as key=value format
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)
}
}
}
@ -81,14 +80,14 @@ func (opts *Options) MergeValues(p getter.Providers) (map[string]interface{}, er
// 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)
}
}
@ -102,14 +101,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)
}
}

@ -16,7 +16,9 @@ limitations under the License.
package cmd
import (
"errors"
"fmt"
"io/fs"
"os"
"path/filepath"
"strings"
@ -202,7 +204,7 @@ func TestDependencyUpdateCmd_DoNotDeleteOldChartsOnError(t *testing.T) {
// Make sure tmpcharts-x is deleted
tmpPath := filepath.Join(dir(chartname), fmt.Sprintf("tmpcharts-%d", os.Getpid()))
if _, err := os.Stat(tmpPath); !os.IsNotExist(err) {
if _, err := os.Stat(tmpPath); !errors.Is(err, fs.ErrNotExist) {
t.Fatalf("tmpcharts dir still exists")
}
}

@ -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)
}
}

@ -18,6 +18,7 @@ package cmd
import (
"context"
"errors"
"fmt"
"io"
"log"
@ -27,7 +28,6 @@ import (
"syscall"
"time"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
@ -159,7 +159,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{
@ -274,7 +274,6 @@ 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")
if client.DependencyUpdate {
man := &downloader.Manager{
Out: out,
@ -292,10 +291,10 @@ 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
return nil, fmt.Errorf("an error occurred while checking for chart dependencies. You may need to run `helm dependency build` to fetch missing dependencies: %w", err)
}
}
}
@ -333,7 +332,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
@ -359,7 +358,7 @@ func validateDryRunOptionFlag(dryRunOptionFlagValue string) error {
}
}
if !isAllowed {
return errors.New("Invalid dry-run flag. Flag must one of the following: false, true, none, client, server")
return errors.New("invalid dry-run flag. Flag must one of the following: false, true, none, client, server")
}
return nil
}

@ -17,13 +17,13 @@ limitations under the License.
package cmd
import (
"errors"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"helm.sh/helm/v4/pkg/action"

@ -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(),
}
}

@ -17,12 +17,12 @@ limitations under the License.
package cmd
import (
"errors"
"fmt"
"io"
"os"
"path/filepath"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"helm.sh/helm/v4/pkg/action"
@ -57,7 +57,7 @@ func newPackageCmd(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 == "" {

@ -16,12 +16,12 @@ limitations under the License.
package cmd
import (
"fmt"
"io"
"log/slog"
"os"
"os/exec"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"helm.sh/helm/v4/pkg/plugin"
@ -73,7 +73,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
}

@ -20,7 +20,6 @@ import (
"io"
"log/slog"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"helm.sh/helm/v4/pkg/cmd/require"
@ -83,7 +82,7 @@ func (o *pluginInstallOptions) run(out io.Writer) error {
slog.Debug("loading plugin", "path", 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 {

@ -16,13 +16,12 @@ limitations under the License.
package cmd
import (
"errors"
"fmt"
"io"
"log/slog"
"os"
"strings"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"helm.sh/helm/v4/pkg/plugin"
@ -66,20 +65,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.New(strings.Join(errorPlugins, "\n"))
return errors.Join(errorPlugins...)
}
return nil
}

@ -16,13 +16,12 @@ limitations under the License.
package cmd
import (
"errors"
"fmt"
"io"
"log/slog"
"path/filepath"
"strings"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"helm.sh/helm/v4/pkg/plugin"
@ -68,21 +67,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.New(strings.Join(errorPlugins, "\n"))
return errors.Join(errorPlugins...)
}
return nil
}

@ -17,10 +17,10 @@ limitations under the License.
package cmd
import (
"errors"
"io"
"os"
"io/fs"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"helm.sh/helm/v4/pkg/cmd/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)
}

@ -18,15 +18,16 @@ package cmd
import (
"context"
"errors"
"fmt"
"io"
"io/fs"
"os"
"path/filepath"
"strings"
"time"
"github.com/gofrs/flock"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"golang.org/x/term"
"sigs.k8s.io/yaml"
@ -135,7 +136,7 @@ func (o *repoAddOptions) run(out io.Writer) error {
}
b, err := os.ReadFile(o.repoFile)
if err != nil && !os.IsNotExist(err) {
if err != nil && !errors.Is(err, fs.ErrNotExist) {
return err
}
@ -179,7 +180,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:
@ -188,10 +189,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
@ -208,12 +208,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)

@ -17,8 +17,10 @@ limitations under the License.
package cmd
import (
"errors"
"fmt"
"io"
"io/fs"
"os"
"path/filepath"
"strings"
@ -113,11 +115,11 @@ func TestRepoAdd(t *testing.T) {
}
idx := filepath.Join(helmpath.CachePath("repository"), helmpath.CacheIndexFile(testRepoName))
if _, err := os.Stat(idx); os.IsNotExist(err) {
if _, err := os.Stat(idx); errors.Is(err, fs.ErrNotExist) {
t.Errorf("Error cache index file was not created for repository %s", testRepoName)
}
idx = filepath.Join(helmpath.CachePath("repository"), helmpath.CacheChartsFile(testRepoName))
if _, err := os.Stat(idx); os.IsNotExist(err) {
if _, err := os.Stat(idx); errors.Is(err, fs.ErrNotExist) {
t.Errorf("Error cache charts file was not created for repository %s", testRepoName)
}

@ -17,11 +17,13 @@ limitations under the License.
package cmd
import (
"errors"
"fmt"
"io"
"io/fs"
"os"
"path/filepath"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"helm.sh/helm/v4/pkg/cmd/require"
@ -97,13 +99,13 @@ func index(dir, url, mergeTo string, json bool) error {
if mergeTo != "" {
// if index.yaml is missing then create an empty one to merge into
var i2 *repo.IndexFile
if _, err := os.Stat(mergeTo); os.IsNotExist(err) {
if _, err := os.Stat(mergeTo); errors.Is(err, fs.ErrNotExist) {
i2 = repo.NewIndexFile()
writeIndexFile(i2, mergeTo, json)
} 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 +116,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)
}

@ -17,11 +17,11 @@ limitations under the License.
package cmd
import (
"errors"
"fmt"
"io"
"github.com/gosuri/uitable"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"helm.sh/helm/v4/pkg/cli/output"

@ -17,12 +17,13 @@ limitations under the License.
package cmd
import (
"errors"
"fmt"
"io"
"io/fs"
"os"
"path/filepath"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"helm.sh/helm/v4/pkg/cmd/require"
@ -65,7 +66,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
@ -87,10 +88,10 @@ func removeRepoCache(root, name string) error {
}
idx = filepath.Join(root, helmpath.CacheIndexFile(name))
if _, err := os.Stat(idx); os.IsNotExist(err) {
if _, err := os.Stat(idx); errors.Is(err, fs.ErrNotExist) {
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)
}

@ -17,12 +17,12 @@ limitations under the License.
package cmd
import (
"errors"
"fmt"
"io"
"slices"
"sync"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"helm.sh/helm/v4/pkg/cmd/require"
@ -77,7 +77,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
}
@ -155,7 +155,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

@ -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,

@ -23,7 +23,6 @@ import (
"strings"
"github.com/gosuri/uitable"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"helm.sh/helm/v4/internal/monocular"
@ -84,7 +83,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, " ")

@ -19,6 +19,7 @@ package cmd
import (
"bufio"
"bytes"
"errors"
"fmt"
"io"
"log/slog"
@ -28,7 +29,6 @@ import (
"github.com/Masterminds/semver/v3"
"github.com/gosuri/uitable"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"helm.sh/helm/v4/pkg/cli/output"
@ -153,7 +153,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]

@ -18,8 +18,10 @@ package cmd
import (
"bytes"
"errors"
"fmt"
"io"
"io/fs"
"os"
"path"
"path/filepath"
@ -250,7 +252,7 @@ func createOrOpenFile(filename string, appendData bool) (*os.File, error) {
func ensureDirectoryForFile(file string) error {
baseDir := path.Dir(file)
_, err := os.Stat(baseDir)
if err != nil && !os.IsNotExist(err) {
if err != nil && !errors.Is(err, fs.ErrNotExist) {
return err
}

@ -1 +1 @@
Error: INSTALLATION FAILED: Hiding Kubernetes secrets requires a dry-run mode
Error: INSTALLATION FAILED: hiding Kubernetes secrets requires a dry-run mode

@ -1 +1 @@
Error: An error occurred while checking for chart dependencies. You may need to run `helm dependency build` to fetch missing dependencies: found in Chart.yaml, but missing in charts/ directory: reqsubchart2
Error: an error occurred while checking for chart dependencies. You may need to run `helm dependency build` to fetch missing dependencies: found in Chart.yaml, but missing in charts/ directory: reqsubchart2

@ -27,7 +27,6 @@ import (
"syscall"
"time"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"helm.sh/helm/v4/pkg/action"
@ -200,7 +199,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,
@ -217,7 +216,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
@ -246,7 +245,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 {

@ -16,15 +16,15 @@ limitations under the License.
package downloader
import (
"errors"
"fmt"
"io"
"io/fs"
"net/url"
"os"
"path/filepath"
"strings"
"github.com/pkg/errors"
"helm.sh/helm/v4/internal/fileutil"
"helm.sh/helm/v4/internal/urlutil"
"helm.sh/helm/v4/pkg/getter"
@ -120,7 +120,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
@ -160,7 +160,7 @@ func (c *ChartDownloader) DownloadTo(ref, version, dest string) (string, *proven
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()) {
@ -213,13 +213,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
}
@ -249,23 +248,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)
@ -288,12 +286,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)
}
@ -310,12 +308,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.
@ -348,7 +346,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 {
@ -367,7 +365,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

@ -18,8 +18,10 @@ package downloader
import (
"crypto"
"encoding/hex"
"errors"
"fmt"
"io"
stdfs "io/fs"
"log"
"net/url"
"os"
@ -30,7 +32,6 @@ import (
"sync"
"github.com/Masterminds/semver/v3"
"github.com/pkg/errors"
"sigs.k8s.io/yaml"
"helm.sh/helm/v4/internal/resolver"
@ -220,7 +221,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,9 +252,9 @@ 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) {
} else if errors.Is(err, stdfs.ErrNotExist) {
if err := os.MkdirAll(destPath, 0755); err != nil {
return err
}
@ -314,7 +315,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 +346,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 +354,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 +378,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]
@ -559,7 +560,7 @@ func (m *Manager) ensureMissingRepos(repoNames map[string]string, deps []*chart.
func (m *Manager) resolveRepoNames(deps []*chart.Dependency) (map[string]string, error) {
rf, err := loadRepoConfig(m.RepositoryConfig)
if err != nil {
if os.IsNotExist(err) {
if errors.Is(err, stdfs.ErrNotExist) {
return make(map[string]string), nil
}
return nil, err
@ -764,7 +765,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
}
@ -820,7 +821,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)
@ -838,7 +839,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 {
@ -876,7 +877,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)
@ -891,7 +892,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)
@ -904,7 +905,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

@ -17,6 +17,8 @@ package downloader
import (
"bytes"
"errors"
"io/fs"
"os"
"path/filepath"
"reflect"
@ -262,7 +264,7 @@ func TestDownloadAll(t *testing.T) {
t.Error(err)
}
if _, err := os.Stat(filepath.Join(chartPath, "charts", "signtest-0.1.0.tgz")); os.IsNotExist(err) {
if _, err := os.Stat(filepath.Join(chartPath, "charts", "signtest-0.1.0.tgz")); errors.Is(err, fs.ErrNotExist) {
t.Error(err)
}

@ -17,6 +17,7 @@ limitations under the License.
package engine
import (
"errors"
"fmt"
"log/slog"
"path"
@ -26,7 +27,6 @@ import (
"strings"
"text/template"
"github.com/pkg/errors"
"k8s.io/client-go/rest"
chart "helm.sh/helm/v4/pkg/chart/v2"
@ -133,7 +133,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 {
@ -151,7 +153,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
@ -178,12 +180,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 <no value> hack.
@ -265,7 +267,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")

@ -18,10 +18,10 @@ package engine
import (
"context"
"fmt"
"log/slog"
"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"
@ -99,7 +99,7 @@ func getDynamicClientOnKind(apiversion string, kind string, config *rest.Config)
apiRes, err := getAPIResourceForGVK(gvk, config)
if err != nil {
slog.Error("unable to get apiresource", "groupVersionKind", gvk.String(), slog.Any("error", 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,

@ -18,11 +18,10 @@ package getter
import (
"bytes"
"fmt"
"net/http"
"time"
"github.com/pkg/errors"
"helm.sh/helm/v4/pkg/cli"
"helm.sh/helm/v4/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 (

@ -18,13 +18,12 @@ package getter
import (
"bytes"
"crypto/tls"
"fmt"
"io"
"net/http"
"net/url"
"sync"
"github.com/pkg/errors"
"helm.sh/helm/v4/internal/tlsutil"
"helm.sh/helm/v4/internal/version"
)
@ -65,11 +64,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.
@ -92,7 +91,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)
@ -133,7 +132,7 @@ func (g *HTTPGetter) httpClient() (*http.Client, error) {
tlsutil.WithCAFile(g.opts.caFile),
)
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)
}
g.transport.TLSClientConfig = tlsConf

@ -28,8 +28,6 @@ import (
"testing"
"time"
"github.com/pkg/errors"
"helm.sh/helm/v4/internal/tlsutil"
"helm.sh/helm/v4/internal/version"
"helm.sh/helm/v4/pkg/cli"
@ -317,7 +315,7 @@ func TestDownloadTLS(t *testing.T) {
tlsutil.WithCAFile(ca),
)
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
@ -372,7 +370,7 @@ func TestDownloadTLSWithRedirect(t *testing.T) {
)
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))
}
tlsSrv2 := httptest.NewUnstartedServer(http.HandlerFunc(func(rw http.ResponseWriter, _ *http.Request) {
@ -393,7 +391,7 @@ func TestDownloadTLSWithRedirect(t *testing.T) {
)
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))
}
tlsSrv1 := httptest.NewUnstartedServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {

@ -23,8 +23,6 @@ import (
"path/filepath"
"strings"
"github.com/pkg/errors"
"helm.sh/helm/v4/pkg/cli"
"helm.sh/helm/v4/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
}

@ -19,13 +19,12 @@ package ignore
import (
"bufio"
"bytes"
"errors"
"io"
"log/slog"
"os"
"path/filepath"
"strings"
"github.com/pkg/errors"
)
// HelmIgnore default name of an ignorefile.

@ -20,6 +20,7 @@ import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"io"
"log/slog"
@ -30,7 +31,6 @@ import (
"sync"
jsonpatch "github.com/evanphx/json-patch"
"github.com/pkg/errors"
v1 "k8s.io/api/core/v1"
apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apiextv1beta1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
@ -183,13 +183,13 @@ func (c *Client) IsReachable() error {
if err == genericclioptions.ErrEmptyConfig {
// re-replace kubernetes ErrEmptyConfig error with a friendly error
// moar workarounds for Kubernetes API breaking.
return errors.New("Kubernetes cluster unreachable")
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.Discovery().ServerVersion(); err != nil {
return errors.Wrap(err, "Kubernetes cluster unreachable")
return fmt.Errorf("kubernetes cluster unreachable: %w", err)
}
return nil
}
@ -398,7 +398,7 @@ func (c *Client) BuildTable(reader io.Reader, validate bool) (ResourceList, erro
}
func (c *Client) update(original, target ResourceList, force, threeWayMerge bool) (*Result, error) {
updateErrors := []string{}
updateErrors := []error{}
res := &Result{}
slog.Debug("checking resources for changes", "resources", len(target))
@ -410,7 +410,7 @@ func (c *Client) update(original, target ResourceList, force, threeWayMerge bool
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
@ -418,7 +418,7 @@ func (c *Client) update(original, target ResourceList, force, threeWayMerge bool
// 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
@ -429,12 +429,12 @@ func (c *Client) update(original, target ResourceList, force, threeWayMerge bool
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, threeWayMerge); err != nil {
slog.Debug("error updating the resource", "namespace", info.Namespace, "name", info.Name, "kind", info.Mapping.GroupVersionKind.Kind, slog.Any("error", 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)
@ -446,7 +446,7 @@ func (c *Client) update(original, target ResourceList, force, threeWayMerge bool
case err != nil:
return res, err
case len(updateErrors) != 0:
return res, errors.New(strings.Join(updateErrors, " && "))
return res, joinErrors(updateErrors, " && ")
}
for _, info := range original.Difference(target) {
@ -610,24 +610,24 @@ func deleteResource(info *resource.Info, policy metav1.DeletionPropagation) erro
func createPatch(target *resource.Info, current runtime.Object, threeWayMergeForUnstructured bool) ([]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
@ -663,7 +663,7 @@ func createPatch(target *resource.Info, current runtime.Object, threeWayMergeFor
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)
@ -682,13 +682,13 @@ func updateResource(_ *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)
}
slog.Debug("replace succeeded", "name", target.Name, "initialKind", currentObj.GetObjectKind().GroupVersionKind().Kind, "kind", kind)
} else {
patch, patchType, err := createPatch(target, currentObj, threeWayMergeForUnstructured)
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) == "{}" {
@ -696,7 +696,7 @@ func updateResource(_ *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
}
@ -704,7 +704,7 @@ func updateResource(_ *Client, target *resource.Info, currentObj runtime.Object,
slog.Debug("patching resource", "kind", kind, "name", target.Name, "namespace", 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)
}
}
@ -741,12 +741,12 @@ func (c *Client) OutputContainerLogsForPodList(podList *v1.PodList, namespace st
func copyRequestStreamToWriter(request *rest.Request, podName, containerName string, writer io.Writer) error {
readCloser, err := request.Stream(context.Background())
if err != nil {
return errors.Errorf("Failed to stream pod logs for pod: %s, container: %s", podName, containerName)
return fmt.Errorf("failed to stream pod logs for pod: %s, container: %s", podName, containerName)
}
defer readCloser.Close()
_, err = io.Copy(writer, readCloser)
if err != nil {
return errors.Errorf("Failed to copy IO from logs for pod: %s, container: %s", podName, containerName)
return fmt.Errorf("failed to copy IO from logs for pod: %s, container: %s", podName, containerName)
}
return nil
}
@ -763,3 +763,27 @@ func scrubValidationError(err error) error {
}
return 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
}

@ -18,13 +18,12 @@ package kube // import "helm.sh/helm/v4/pkg/kube"
import (
"context"
stderrors "errors"
"errors"
"fmt"
"log/slog"
"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"
@ -191,7 +190,11 @@ 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")
if err != nil {
return selector, fmt.Errorf("invalid label selector: %w", err)
}
return selector, nil
}
func (hw *legacyWaiter) watchTimeout(t time.Duration) func(*resource.Info) error {
@ -233,7 +236,7 @@ func perform(infos ResourceList, fn func(*resource.Info) error) error {
for range infos {
err := <-errs
if err != nil {
result = stderrors.Join(result, err)
result = errors.Join(result, err)
}
}
@ -291,7 +294,7 @@ func (hw *legacyWaiter) watchUntilReady(timeout time.Duration, info *resource.In
case watch.Error:
// Handle error and return with an error.
slog.Error("error event received", "resource", 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
}
@ -305,7 +308,7 @@ func (hw *legacyWaiter) watchUntilReady(timeout time.Duration, info *resource.In
func (hw *legacyWaiter) waitForJob(obj runtime.Object, name string) (bool, error) {
o, ok := obj.(*batchv1.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 {
@ -313,7 +316,7 @@ func (hw *legacyWaiter) waitForJob(obj runtime.Object, name string) (bool, error
return true, nil
} else if c.Type == batchv1.JobFailed && c.Status == "True" {
slog.Error("job failed", "job", name, "reason", c.Reason)
return true, errors.Errorf("job %s failed: %s", name, c.Reason)
return true, fmt.Errorf("job %s failed: %s", name, c.Reason)
}
}
@ -327,7 +330,7 @@ func (hw *legacyWaiter) waitForJob(obj runtime.Object, name string) (bool, error
func (hw *legacyWaiter) waitForPodSuccess(obj runtime.Object, name string) (bool, error) {
o, ok := obj.(*corev1.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 {
@ -336,7 +339,7 @@ func (hw *legacyWaiter) waitForPodSuccess(obj runtime.Object, name string) (bool
return true, nil
case corev1.PodFailed:
slog.Error("pod failed", "pod", o.Name)
return true, errors.Errorf("pod %s failed", o.Name)
return true, fmt.Errorf("pod %s failed", o.Name)
case corev1.PodPending:
slog.Debug("pod pending", "pod", o.Name)
case corev1.PodRunning:

@ -17,13 +17,13 @@ limitations under the License.
package rules // import "helm.sh/helm/v4/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"
chart "helm.sh/helm/v4/pkg/chart/v2"
@ -84,7 +84,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
}
@ -100,14 +100,14 @@ 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
}
func validateChartYamlStrictFormat(chartFileError error) error {
if chartFileError != nil {
return errors.Errorf("failed to strictly parse chart metadata file\n\t%s", chartFileError.Error())
return fmt.Errorf("failed to strictly parse chart metadata file\n\t%w", chartFileError)
}
return nil
}
@ -141,9 +141,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")
@ -153,7 +152,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
@ -164,9 +163,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
@ -175,7 +174,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
@ -190,7 +189,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
}

@ -17,13 +17,12 @@ limitations under the License.
package rules
import (
"errors"
"os"
"path/filepath"
"strings"
"testing"
"github.com/pkg/errors"
chart "helm.sh/helm/v4/pkg/chart/v2"
chartutil "helm.sh/helm/v4/pkg/chart/v2/util"
"helm.sh/helm/v4/pkg/lint/support"

@ -20,8 +20,6 @@ import (
"fmt"
"strings"
"github.com/pkg/errors"
chart "helm.sh/helm/v4/pkg/chart/v2"
"helm.sh/helm/v4/pkg/chart/v2/loader"
"helm.sh/helm/v4/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
}

@ -19,6 +19,7 @@ package rules
import (
"bufio"
"bytes"
"errors"
"fmt"
"io"
"os"
@ -26,7 +27,6 @@ import (
"path/filepath"
"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"
@ -212,11 +212,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
@ -229,7 +232,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
}
@ -293,6 +296,7 @@ func validateMatchSelector(yamlStruct *K8sYamlStruct, manifest string) error {
}
return nil
}
func validateListAnnotations(yamlStruct *K8sYamlStruct, manifest string) error {
if yamlStruct.Kind == "List" {
m := struct {
@ -309,7 +313,7 @@ func validateListAnnotations(yamlStruct *K8sYamlStruct, manifest string) error {
for _, i := range m.Items {
if _, ok := i.Metadata.Annotations["helm.sh/resource-policy"]; ok {
return errors.New("Annotation 'helm.sh/resource-policy' within List objects are ignored")
return errors.New("annotation 'helm.sh/resource-policy' within List objects are ignored")
}
}
}

@ -17,11 +17,10 @@ limitations under the License.
package rules
import (
"fmt"
"os"
"path/filepath"
"github.com/pkg/errors"
chartutil "helm.sh/helm/v4/pkg/chart/v2/util"
"helm.sh/helm/v4/pkg/lint/support"
)
@ -47,7 +46,7 @@ func ValuesWithOverrides(linter *support.Linter, valueOverrides map[string]inter
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
}
@ -55,7 +54,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

@ -17,9 +17,8 @@ limitations under the License.
package support
import (
"errors"
"testing"
"github.com/pkg/errors"
)
var linter = Linter{}

@ -19,6 +19,8 @@ import (
"archive/tar"
"bytes"
"compress/gzip"
"errors"
"fmt"
"io"
"log/slog"
"os"
@ -28,7 +30,6 @@ import (
"strings"
securejoin "github.com/cyphar/filepath-securejoin"
"github.com/pkg/errors"
"helm.sh/helm/v4/internal/third_party/dep/fs"
"helm.sh/helm/v4/pkg/cli"
@ -79,7 +80,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.
@ -133,7 +134,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) {
@ -152,7 +153,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
@ -265,7 +266,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

@ -20,7 +20,9 @@ import (
"bytes"
"compress/gzip"
"encoding/base64"
"errors"
"fmt"
"io/fs"
"net/http"
"net/http/httptest"
"os"
@ -29,8 +31,6 @@ import (
"syscall"
"testing"
"github.com/pkg/errors"
"helm.sh/helm/v4/internal/test/ensure"
"helm.sh/helm/v4/pkg/getter"
"helm.sh/helm/v4/pkg/helmpath"
@ -150,7 +150,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
@ -276,7 +276,7 @@ func TestExtract(t *testing.T) {
pluginYAMLFullPath := filepath.Join(tempDir, "plugin.yaml")
if info, err := os.Stat(pluginYAMLFullPath); err != nil {
if os.IsNotExist(err) {
if errors.Is(err, fs.ErrNotExist) {
t.Fatalf("Expected %s to exist but doesn't", pluginYAMLFullPath)
}
t.Fatal(err)
@ -286,7 +286,7 @@ func TestExtract(t *testing.T) {
readmeFullPath := filepath.Join(tempDir, "README.md")
if info, err := os.Stat(readmeFullPath); err != nil {
if os.IsNotExist(err) {
if errors.Is(err, fs.ErrNotExist) {
t.Fatalf("Expected %s to exist but doesn't", readmeFullPath)
}
t.Fatal(err)

@ -16,13 +16,12 @@ limitations under the License.
package installer
import (
"errors"
"net/http"
"os"
"path/filepath"
"strings"
"github.com/pkg/errors"
"helm.sh/helm/v4/pkg/plugin"
)

@ -16,11 +16,11 @@ limitations under the License.
package installer // import "helm.sh/helm/v4/pkg/plugin/installer"
import (
"errors"
"fmt"
"log/slog"
"os"
"path/filepath"
"github.com/pkg/errors"
)
// ErrPluginNotAFolder indicates that the plugin path is not a folder.
@ -35,7 +35,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),

@ -16,13 +16,15 @@ limitations under the License.
package installer // import "helm.sh/helm/v4/pkg/plugin/installer"
import (
"errors"
"fmt"
stdfs "io/fs"
"log/slog"
"os"
"sort"
"github.com/Masterminds/semver/v3"
"github.com/Masterminds/vcs"
"github.com/pkg/errors"
"helm.sh/helm/v4/internal/third_party/dep/fs"
"helm.sh/helm/v4/pkg/helmpath"
@ -145,7 +147,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
@ -156,7 +158,7 @@ func (i *VCSInstaller) setVersion(repo vcs.Repo, ref string) error {
// sync will clone or update a remote repo.
func (i *VCSInstaller) sync(repo vcs.Repo) error {
if _, err := os.Stat(repo.LocalPath()); os.IsNotExist(err) {
if _, err := os.Stat(repo.LocalPath()); errors.Is(err, stdfs.ErrNotExist) {
slog.Debug("cloning", "source", repo.Remote(), "destination", repo.LocalPath())
return repo.Get()
}

@ -24,7 +24,6 @@ import (
"strings"
"unicode"
"github.com/pkg/errors"
"sigs.k8s.io/yaml"
"helm.sh/helm/v4/pkg/cli"
@ -313,12 +312,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)
}
@ -332,7 +331,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 {

@ -18,11 +18,10 @@ package postrender
import (
"bytes"
"fmt"
"io"
"os/exec"
"path/filepath"
"github.com/pkg/errors"
)
type execRender struct {
@ -61,13 +60,13 @@ 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)
}
// If the binary returned almost nothing, it's likely that it didn't
// successfully render anything
if len(bytes.TrimSpace(postRendered.Bytes())) == 0 {
return nil, errors.Errorf("post-renderer %q produced empty output", p.binaryPath)
return nil, fmt.Errorf("post-renderer %q produced empty output", p.binaryPath)
}
return postRendered, nil
@ -95,7 +94,7 @@ func getFullPath(binaryPath string) (string, error) {
// // The plugins variable can actually contain multiple paths, so loop through those
// for _, p := range filepath.SplitList(pluginDir) {
// _, err := os.Stat(filepath.Join(p, binaryPath))
// if err != nil && !os.IsNotExist(err) {
// if err != nil && !errors.Is(err, fs.ErrNotExist) {
// return "", err
// } else if err == nil {
// binaryPath = filepath.Join(p, binaryPath)
@ -108,7 +107,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)

@ -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

@ -16,7 +16,9 @@ limitations under the License.
package pusher
import (
"errors"
"fmt"
"io/fs"
"net"
"net/http"
"os"
@ -24,8 +26,6 @@ import (
"strings"
"time"
"github.com/pkg/errors"
"helm.sh/helm/v4/internal/tlsutil"
"helm.sh/helm/v4/pkg/chart/v2/loader"
"helm.sh/helm/v4/pkg/registry"
@ -48,8 +48,8 @@ func (pusher *OCIPusher) Push(chartRef, href string, options ...Option) error {
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)
if errors.Is(err, fs.ErrNotExist) {
return fmt.Errorf("%s: no such file", chartRef)
}
return err
}
@ -117,7 +117,7 @@ func (pusher *OCIPusher) newRegistryClient() (*registry.Client, error) {
tlsutil.WithCAFile(pusher.opts.caFile),
)
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(

@ -17,7 +17,7 @@ limitations under the License.
package pusher
import (
"github.com/pkg/errors"
"fmt"
"helm.sh/helm/v4/pkg/cli"
"helm.sh/helm/v4/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{

@ -21,6 +21,7 @@ import (
"crypto/tls"
"crypto/x509"
"encoding/json"
"errors"
"fmt"
"io"
"net/http"
@ -33,7 +34,6 @@ import (
"github.com/Masterminds/semver/v3"
"github.com/opencontainers/image-spec/specs-go"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"oras.land/oras-go/v2"
"oras.land/oras-go/v2/content"
"oras.land/oras-go/v2/content/memory"
@ -463,7 +463,7 @@ func (c *Client) Pull(ref string, options ...PullOption) (*PullResult, error) {
PreCopy: func(_ context.Context, desc ocispec.Descriptor) error {
mediaType := desc.MediaType
if i := sort.SearchStrings(allowedMediaTypes, mediaType); i >= len(allowedMediaTypes) || allowedMediaTypes[i] != mediaType {
return errors.Errorf("media type %q is not allowed, found in descriptor with digest: %q", mediaType, desc.Digest)
return fmt.Errorf("media type %q is not allowed, found in descriptor with digest: %q", mediaType, desc.Digest)
}
mu.Lock()
@ -846,7 +846,7 @@ func (c *Client) ValidateReference(ref, version string, u *url.URL) (*url.URL, e
version = registryReference.Tag
} else {
if registryReference.Tag != "" && registryReference.Tag != version {
return nil, errors.Errorf("chart reference and version mismatch: %s is not %s", version, registryReference.Tag)
return nil, fmt.Errorf("chart reference and version mismatch: %s is not %s", version, registryReference.Tag)
}
}
@ -865,7 +865,7 @@ func (c *Client) ValidateReference(ref, version string, u *url.URL) (*url.URL, e
return u, nil
}
if desc.Digest.String() != registryReference.Digest {
return nil, errors.Errorf("chart reference digest mismatch: %s is not %s", desc.Digest.String(), registryReference.Digest)
return nil, fmt.Errorf("chart reference digest mismatch: %s is not %s", desc.Digest.String(), registryReference.Digest)
}
return u, nil
}
@ -881,7 +881,7 @@ func (c *Client) ValidateReference(ref, version string, u *url.URL) (*url.URL, e
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

@ -31,7 +31,6 @@ import (
"github.com/Masterminds/semver/v3"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
)
var immutableOciAnnotations = []string{
@ -87,7 +86,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

@ -17,13 +17,13 @@ limitations under the License.
package util
import (
"fmt"
"log/slog"
"path"
"sort"
"strconv"
"strings"
"github.com/pkg/errors"
"sigs.k8s.io/yaml"
chartutil "helm.sh/helm/v4/pkg/chart/v2/util"
@ -149,7 +149,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) {

@ -28,8 +28,6 @@ import (
"path/filepath"
"strings"
"github.com/pkg/errors"
"helm.sh/helm/v4/pkg/getter"
"helm.sh/helm/v4/pkg/helmpath"
)
@ -59,12 +57,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{
@ -200,7 +198,7 @@ func FindChartInRepoURL(repoURL string, chartName string, getters getter.Provide
}
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)))
@ -226,14 +224,14 @@ func FindChartInRepoURL(repoURL string, chartName string, getters getter.Provide
}
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
@ -244,7 +242,7 @@ func FindChartInRepoURL(repoURL string, chartName string, getters getter.Provide
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() {
@ -253,7 +251,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

@ -19,6 +19,8 @@ package repo
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"log/slog"
"os"
"path"
@ -28,7 +30,6 @@ import (
"time"
"github.com/Masterminds/semver/v3"
"github.com/pkg/errors"
"sigs.k8s.io/yaml"
"helm.sh/helm/v4/internal/fileutil"
@ -108,7 +109,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
}
@ -124,7 +125,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
@ -217,7 +218,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.
@ -330,7 +331,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

@ -17,11 +17,11 @@ limitations under the License.
package repo // import "helm.sh/helm/v4/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)

@ -24,7 +24,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"
@ -122,7 +121,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
}

@ -17,10 +17,9 @@ limitations under the License.
package driver // import "helm.sh/helm/v4/pkg/storage/driver"
import (
"errors"
"fmt"
"github.com/pkg/errors"
rspb "helm.sh/helm/v4/pkg/release/v1"
)

@ -24,7 +24,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"
@ -68,12 +67,15 @@ 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"]))
if err != nil {
return r, fmt.Errorf("get: failed to decode data %q: %w", key, err)
}
r.Labels = filterSystemLabels(obj.Labels)
return r, errors.Wrapf(err, "get: failed to decode data %q", key)
return r, nil
}
// List fetches all releases and returns the list releases such
@ -85,7 +87,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
@ -114,7 +116,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
}
@ -123,7 +125,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 {
@ -156,7 +158,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 {
@ -164,7 +166,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
}
@ -182,11 +184,14 @@ 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")
if err != nil {
return fmt.Errorf("update: failed to update: %w", err)
}
return nil
}
// Delete deletes the Secret holding the release named by key.
@ -197,7 +202,10 @@ func (secrets *Secrets) Delete(key string) (rls *rspb.Release, err error) {
}
// delete the release
err = secrets.impl.Delete(context.Background(), key, metav1.DeleteOptions{})
return rls, err
if err != nil {
return nil, err
}
return rls, nil
}
// newSecretsObject constructs a kubernetes Secret object

@ -17,12 +17,11 @@ limitations under the License.
package storage // import "helm.sh/helm/v4/pkg/storage"
import (
"errors"
"fmt"
"log/slog"
"strings"
"github.com/pkg/errors"
relutil "helm.sh/helm/v4/pkg/release/util"
rspb "helm.sh/helm/v4/pkg/release/v1"
"helm.sh/helm/v4/pkg/storage/driver"
@ -212,7 +211,7 @@ func (s *Storage) removeLeastRecent(name string, maximum 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])
}
}
@ -234,7 +233,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)

@ -17,12 +17,11 @@ limitations under the License.
package storage // import "helm.sh/helm/v4/pkg/storage"
import (
"errors"
"fmt"
"reflect"
"testing"
"github.com/pkg/errors"
rspb "helm.sh/helm/v4/pkg/release/v1"
"helm.sh/helm/v4/pkg/storage/driver"
)

@ -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)
}
}

@ -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)
}
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save