diff --git a/cmd/helm/dependency_update_test.go b/cmd/helm/dependency_update_test.go index 1a1e0468f..80b2734da 100644 --- a/cmd/helm/dependency_update_test.go +++ b/cmd/helm/dependency_update_test.go @@ -16,7 +16,9 @@ limitations under the License. package main 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") } } diff --git a/cmd/helm/install.go b/cmd/helm/install.go index 45dcf7d52..ed49bd7a5 100644 --- a/cmd/helm/install.go +++ b/cmd/helm/install.go @@ -265,7 +265,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 = 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, @@ -286,7 +285,7 @@ func runInstall(args []string, client *action.Install, valueOpts *values.Options 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) } } } diff --git a/cmd/helm/repo_add.go b/cmd/helm/repo_add.go index 967e98bea..5dc7ad0b9 100644 --- a/cmd/helm/repo_add.go +++ b/cmd/helm/repo_add.go @@ -18,8 +18,10 @@ package main import ( "context" + "errors" "fmt" "io" + "io/fs" "os" "path/filepath" "strings" @@ -138,7 +140,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 } diff --git a/cmd/helm/repo_add_test.go b/cmd/helm/repo_add_test.go index 2386bb01f..fa95ae1fa 100644 --- a/cmd/helm/repo_add_test.go +++ b/cmd/helm/repo_add_test.go @@ -17,8 +17,10 @@ limitations under the License. package main import ( + "errors" "fmt" "io" + "io/fs" "os" "path/filepath" "strings" @@ -115,11 +117,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) } diff --git a/cmd/helm/repo_index.go b/cmd/helm/repo_index.go index 06bd6b4c6..c87d2b878 100644 --- a/cmd/helm/repo_index.go +++ b/cmd/helm/repo_index.go @@ -17,8 +17,10 @@ limitations under the License. package main import ( + "errors" "fmt" "io" + "io/fs" "os" "path/filepath" @@ -97,7 +99,7 @@ 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 { diff --git a/cmd/helm/repo_remove.go b/cmd/helm/repo_remove.go index 1b6b90bfd..150f8dc2e 100644 --- a/cmd/helm/repo_remove.go +++ b/cmd/helm/repo_remove.go @@ -20,6 +20,7 @@ import ( "errors" "fmt" "io" + "io/fs" "os" "path/filepath" @@ -87,7 +88,7 @@ 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 fmt.Errorf("can't remove index file %s: %w", idx, err) diff --git a/cmd/helm/template.go b/cmd/helm/template.go index b53ed6b1c..b7c2cd13a 100644 --- a/cmd/helm/template.go +++ b/cmd/helm/template.go @@ -18,8 +18,10 @@ package main import ( "bytes" + "errors" "fmt" "io" + "io/fs" "os" "path" "path/filepath" @@ -254,7 +256,7 @@ func createOrOpenFile(filename string, append 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 } diff --git a/internal/resolver/resolver.go b/internal/resolver/resolver.go index 73a36e9bb..24d92b809 100644 --- a/internal/resolver/resolver.go +++ b/internal/resolver/resolver.go @@ -18,7 +18,9 @@ package resolver import ( "bytes" "encoding/json" + "errors" "fmt" + "io/fs" "os" "path/filepath" "strings" @@ -251,7 +253,7 @@ func GetLocalPath(repo, chartpath string) (string, error) { depPath = filepath.Join(chartpath, p) } - if _, err = os.Stat(depPath); os.IsNotExist(err) { + if _, err = os.Stat(depPath); errors.Is(err, fs.ErrNotExist) { return "", fmt.Errorf("directory %s not found", depPath) } else if err != nil { return "", err diff --git a/internal/third_party/dep/fs/fs.go b/internal/third_party/dep/fs/fs.go index 9491fed6e..793514c90 100644 --- a/internal/third_party/dep/fs/fs.go +++ b/internal/third_party/dep/fs/fs.go @@ -35,6 +35,7 @@ import ( "errors" "fmt" "io" + "io/fs" "os" "path/filepath" "runtime" @@ -111,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 { diff --git a/internal/tlsutil/cfg.go b/internal/tlsutil/cfg.go index 26da172c5..84377621c 100644 --- a/internal/tlsutil/cfg.go +++ b/internal/tlsutil/cfg.go @@ -19,8 +19,9 @@ package tlsutil import ( "crypto/tls" "crypto/x509" + "errors" "fmt" - "os" + "io/fs" ) // Options represents configurable options used to create client and server TLS configurations. @@ -40,7 +41,7 @@ func ClientConfig(opts Options) (cfg *tls.Config, err error) { if opts.CertFile != "" || opts.KeyFile != "" { if cert, err = CertFromFilePair(opts.CertFile, opts.KeyFile); err != nil { - if os.IsNotExist(err) { + if errors.Is(err, fs.ErrNotExist) { return nil, fmt.Errorf("could not load x509 key pair (cert: %q, key: %q): %w", opts.CertFile, opts.KeyFile, err) } return nil, fmt.Errorf("could not read x509 key pair (cert: %q, key: %q): %w", opts.CertFile, opts.KeyFile, err) diff --git a/pkg/action/install.go b/pkg/action/install.go index aa10dbd46..7ad7d1804 100644 --- a/pkg/action/install.go +++ b/pkg/action/install.go @@ -22,6 +22,7 @@ import ( "errors" "fmt" "io" + "io/fs" "net/url" "os" "path" @@ -634,7 +635,7 @@ func createOrOpenFile(filename string, append 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 } diff --git a/pkg/action/install_test.go b/pkg/action/install_test.go index d11b04011..c6de71191 100644 --- a/pkg/action/install_test.go +++ b/pkg/action/install_test.go @@ -18,8 +18,10 @@ package action import ( "context" + "errors" "fmt" "io" + "io/fs" "os" "path/filepath" "regexp" @@ -626,7 +628,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) { @@ -662,7 +664,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) { diff --git a/pkg/action/validate.go b/pkg/action/validate.go index cbf48acb7..f5bf75ed7 100644 --- a/pkg/action/validate.go +++ b/pkg/action/validate.go @@ -17,7 +17,6 @@ limitations under the License. package action import ( - "errors" "fmt" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -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 diff --git a/pkg/chartutil/chartfile.go b/pkg/chartutil/chartfile.go index 98bfc2348..392ef3572 100644 --- a/pkg/chartutil/chartfile.go +++ b/pkg/chartutil/chartfile.go @@ -17,7 +17,9 @@ limitations under the License. package chartutil import ( + "errors" "fmt" + "io/fs" "os" "path/filepath" @@ -68,7 +70,7 @@ func IsChartDir(dirName string) (bool, error) { } chartYaml := filepath.Join(dirName, ChartfileName) - if _, err := os.Stat(chartYaml); os.IsNotExist(err) { + if _, err := os.Stat(chartYaml); errors.Is(err, fs.ErrNotExist) { return false, fmt.Errorf("no %s exists in directory %q", ChartfileName, dirName) } diff --git a/pkg/chartutil/save.go b/pkg/chartutil/save.go index bf47cbe44..b2170ac8d 100644 --- a/pkg/chartutil/save.go +++ b/pkg/chartutil/save.go @@ -22,6 +22,7 @@ import ( "encoding/json" "errors" "fmt" + "io/fs" "os" "path/filepath" "time" @@ -112,7 +113,7 @@ func Save(c *chart.Chart, outDir string) (string, error) { 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 } diff --git a/pkg/chartutil/values.go b/pkg/chartutil/values.go index 963ddbf1f..a03d31bee 100644 --- a/pkg/chartutil/values.go +++ b/pkg/chartutil/values.go @@ -165,8 +165,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) } } diff --git a/pkg/downloader/manager.go b/pkg/downloader/manager.go index e778e9105..8d402e784 100644 --- a/pkg/downloader/manager.go +++ b/pkg/downloader/manager.go @@ -21,6 +21,7 @@ import ( "errors" "fmt" "io" + stdfs "io/fs" "log" "net/url" "os" @@ -253,7 +254,7 @@ func (m *Manager) downloadAll(deps []*chart.Dependency) error { if !fi.IsDir() { 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 } @@ -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 diff --git a/pkg/downloader/manager_test.go b/pkg/downloader/manager_test.go index db2487d16..805b78bf7 100644 --- a/pkg/downloader/manager_test.go +++ b/pkg/downloader/manager_test.go @@ -17,6 +17,8 @@ package downloader import ( "bytes" + "errors" + "io/fs" "os" "path/filepath" "reflect" @@ -259,7 +261,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) } diff --git a/pkg/plugin/installer/http_installer_test.go b/pkg/plugin/installer/http_installer_test.go index 12b6c1ef7..31d6b90e2 100644 --- a/pkg/plugin/installer/http_installer_test.go +++ b/pkg/plugin/installer/http_installer_test.go @@ -20,7 +20,9 @@ import ( "bytes" "compress/gzip" "encoding/base64" + "errors" "fmt" + "io/fs" "net/http" "net/http/httptest" "os" @@ -274,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) @@ -284,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) diff --git a/pkg/plugin/installer/vcs_installer.go b/pkg/plugin/installer/vcs_installer.go index 96658665b..23364a89a 100644 --- a/pkg/plugin/installer/vcs_installer.go +++ b/pkg/plugin/installer/vcs_installer.go @@ -18,6 +18,7 @@ package installer // import "helm.sh/helm/v3/pkg/plugin/installer" import ( "errors" "fmt" + stdfs "io/fs" "os" "sort" @@ -156,7 +157,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) { debug("cloning %s to %s", repo.Remote(), repo.LocalPath()) return repo.Get() } diff --git a/pkg/postrender/exec.go b/pkg/postrender/exec.go index fcf52ffee..90e5473f3 100644 --- a/pkg/postrender/exec.go +++ b/pkg/postrender/exec.go @@ -88,7 +88,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) diff --git a/pkg/pusher/ocipusher.go b/pkg/pusher/ocipusher.go index d2066ab09..29ffb0afb 100644 --- a/pkg/pusher/ocipusher.go +++ b/pkg/pusher/ocipusher.go @@ -18,6 +18,7 @@ package pusher import ( "errors" "fmt" + "io/fs" "net" "net/http" "os" @@ -47,7 +48,7 @@ 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) { + if errors.Is(err, fs.ErrNotExist) { return fmt.Errorf("%s: no such file", chartRef) } return err