diff --git a/cmd/helm/completion.go b/cmd/helm/completion.go index b1cd04140..3685c42cc 100644 --- a/cmd/helm/completion.go +++ b/cmd/helm/completion.go @@ -17,9 +17,9 @@ package main import ( "bytes" - "fmt" "io" + "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -63,14 +63,14 @@ func newCompletionCmd(out io.Writer) *cobra.Command { func runCompletion(out io.Writer, cmd *cobra.Command, args []string) error { if len(args) == 0 { - return fmt.Errorf("shell not specified") + return errors.New("shell not specified") } if len(args) > 1 { - return fmt.Errorf("too many arguments, expected only the shell type") + return errors.New("too many arguments, expected only the shell type") } run, found := completionShells[args[0]] if !found { - return fmt.Errorf("unsupported shell type %q", args[0]) + return errors.Errorf("unsupported shell type %q", args[0]) } return run(out, cmd) diff --git a/cmd/helm/create.go b/cmd/helm/create.go index 4d4dc153d..39ec211aa 100644 --- a/cmd/helm/create.go +++ b/cmd/helm/create.go @@ -17,11 +17,11 @@ limitations under the License. package main import ( - "errors" "fmt" "io" "path/filepath" + "github.com/pkg/errors" "github.com/spf13/cobra" "k8s.io/helm/pkg/chartutil" diff --git a/cmd/helm/delete.go b/cmd/helm/delete.go index 1ed7edddc..49911257a 100644 --- a/cmd/helm/delete.go +++ b/cmd/helm/delete.go @@ -17,10 +17,10 @@ limitations under the License. package main import ( - "errors" "fmt" "io" + "github.com/pkg/errors" "github.com/spf13/cobra" "k8s.io/helm/pkg/helm" diff --git a/cmd/helm/docs.go b/cmd/helm/docs.go index 443d2b09f..4139bbc32 100644 --- a/cmd/helm/docs.go +++ b/cmd/helm/docs.go @@ -16,10 +16,10 @@ limitations under the License. package main import ( - "fmt" "io" "path/filepath" + "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/cobra/doc" ) @@ -74,6 +74,6 @@ func (o *docsOptions) run(out io.Writer) error { case "bash": return o.topCmd.GenBashCompletionFile(filepath.Join(o.dest, "completions.bash")) default: - return fmt.Errorf("unknown doc type %q. Try 'markdown' or 'man'", o.docTypeString) + return errors.Errorf("unknown doc type %q. Try 'markdown' or 'man'", o.docTypeString) } } diff --git a/cmd/helm/fetch.go b/cmd/helm/fetch.go index df39b91f4..284851085 100644 --- a/cmd/helm/fetch.go +++ b/cmd/helm/fetch.go @@ -23,6 +23,7 @@ import ( "os" "path/filepath" + "github.com/pkg/errors" "github.com/spf13/cobra" "k8s.io/helm/pkg/chartutil" @@ -74,7 +75,7 @@ func newFetchCmd(out io.Writer) *cobra.Command { Long: fetchDesc, RunE: func(cmd *cobra.Command, args []string) error { if len(args) == 0 { - return fmt.Errorf("need at least one argument, url or repo/name of the chart") + return errors.Errorf("need at least one argument, url or repo/name of the chart") } if o.version == "" && o.devel { @@ -135,7 +136,7 @@ func (o *fetchOptions) run(out io.Writer) error { var err error dest, err = ioutil.TempDir("", "helm-") if err != nil { - return fmt.Errorf("Failed to untar: %s", err) + return errors.Wrap(err, "failed to untar") } defer os.RemoveAll(dest) } @@ -165,11 +166,11 @@ func (o *fetchOptions) run(out io.Writer) error { } if fi, err := os.Stat(ud); err != nil { if err := os.MkdirAll(ud, 0755); err != nil { - return fmt.Errorf("Failed to untar (mkdir): %s", err) + return errors.Wrap(err, "failed to untar (mkdir)") } } else if !fi.IsDir() { - return fmt.Errorf("Failed to untar: %s is not a directory", ud) + return errors.Errorf("failed to untar: %s is not a directory", ud) } return chartutil.ExpandFile(ud, saved) diff --git a/cmd/helm/get.go b/cmd/helm/get.go index b15ca8d90..4c666d34c 100644 --- a/cmd/helm/get.go +++ b/cmd/helm/get.go @@ -17,9 +17,9 @@ limitations under the License. package main import ( - "errors" "io" + "github.com/pkg/errors" "github.com/spf13/cobra" "k8s.io/helm/pkg/helm" diff --git a/cmd/helm/helm.go b/cmd/helm/helm.go index c40516059..1451fac37 100644 --- a/cmd/helm/helm.go +++ b/cmd/helm/helm.go @@ -24,6 +24,7 @@ import ( "strings" "sync" + "github.com/pkg/errors" "github.com/spf13/cobra" // Import to initialize client auth plugins. _ "k8s.io/client-go/plugin/pkg/client/auth" @@ -132,6 +133,7 @@ func logf(format string, v ...interface{}) { func main() { cmd := newRootCmd(nil, os.Stdout, os.Args[1:]) if err := cmd.Execute(); err != nil { + logf("%+v", err) os.Exit(1) } } @@ -143,7 +145,7 @@ func checkArgsLength(argsReceived int, requiredArgs ...string) error { if expectedNum == 1 { arg = "argument" } - return fmt.Errorf("This command needs %v %s: %s", expectedNum, arg, strings.Join(requiredArgs, ", ")) + return errors.Errorf("this command needs %v %s: %s", expectedNum, arg, strings.Join(requiredArgs, ", ")) } return nil } diff --git a/cmd/helm/helm_test.go b/cmd/helm/helm_test.go index 102e4054b..46cfeddb8 100644 --- a/cmd/helm/helm_test.go +++ b/cmd/helm/helm_test.go @@ -18,7 +18,6 @@ package main import ( "bytes" - "fmt" "io/ioutil" "os" "path/filepath" @@ -26,6 +25,7 @@ import ( "testing" shellwords "github.com/mattn/go-shellwords" + "github.com/pkg/errors" "github.com/spf13/cobra" "k8s.io/helm/internal/test" @@ -117,7 +117,7 @@ func ensureTestHome(t *testing.T, home helmpath.Home) error { home.Starters(), } { if err := os.MkdirAll(p, 0755); err != nil { - return fmt.Errorf("Could not create %s: %s", p, err) + return errors.Wrapf(err, "could not create %s", p) } } diff --git a/cmd/helm/history.go b/cmd/helm/history.go index a4e894075..4e0ae16e8 100644 --- a/cmd/helm/history.go +++ b/cmd/helm/history.go @@ -23,6 +23,7 @@ import ( "github.com/ghodss/yaml" "github.com/gosuri/uitable" + "github.com/pkg/errors" "github.com/spf13/cobra" "k8s.io/helm/pkg/hapi/chart" @@ -114,7 +115,7 @@ func (o *historyOptions) run(out io.Writer) error { case "table": history = formatAsTable(releaseHistory, o.colWidth) default: - return fmt.Errorf("unknown output format %q", o.outputFormat) + return errors.Errorf("unknown output format %q", o.outputFormat) } if formattingError != nil { diff --git a/cmd/helm/init.go b/cmd/helm/init.go index a19db0d31..d70da0eea 100644 --- a/cmd/helm/init.go +++ b/cmd/helm/init.go @@ -17,11 +17,11 @@ limitations under the License. package main import ( - "errors" "fmt" "io" "os" + "github.com/pkg/errors" "github.com/spf13/cobra" "k8s.io/helm/pkg/getter" @@ -54,7 +54,7 @@ func newInitCmd(out io.Writer) *cobra.Command { Long: initDesc, RunE: func(cmd *cobra.Command, args []string) error { if len(args) != 0 { - return errors.New("This command does not accept arguments") + return errors.New("this command does not accept arguments") } o.home = settings.Home return o.run(out) @@ -100,10 +100,10 @@ func ensureDirectories(home helmpath.Home, out io.Writer) error { if fi, err := os.Stat(p); err != nil { fmt.Fprintf(out, "Creating %s \n", p) if err := os.MkdirAll(p, 0755); err != nil { - return fmt.Errorf("Could not create %s: %s", p, err) + return errors.Wrapf(err, "could not create %s", p) } } else if !fi.IsDir() { - return fmt.Errorf("%s must be a directory", p) + return errors.Errorf("%s must be a directory", p) } } @@ -124,7 +124,7 @@ func ensureDefaultRepos(home helmpath.Home, out io.Writer, skipRefresh bool, url return err } } else if fi.IsDir() { - return fmt.Errorf("%s must be a file, not a directory", repoFile) + return errors.Errorf("%s must be a file, not a directory", repoFile) } return nil } @@ -148,7 +148,7 @@ func initRepo(url, cacheFile string, out io.Writer, skipRefresh bool, home helmp // In this case, the cacheFile is always absolute. So passing empty string // is safe. if err := r.DownloadIndexFile(""); err != nil { - return nil, fmt.Errorf("Looks like %q is not a valid chart repository or cannot be reached: %s", url, err.Error()) + return nil, errors.Wrapf(err, "looks like %q is not a valid chart repository or cannot be reached: %s", url) } return &c, nil diff --git a/cmd/helm/install.go b/cmd/helm/install.go index 0bec126a2..032285b24 100644 --- a/cmd/helm/install.go +++ b/cmd/helm/install.go @@ -18,7 +18,6 @@ package main import ( "bytes" - "errors" "fmt" "io" "io/ioutil" @@ -30,6 +29,7 @@ import ( "github.com/Masterminds/sprig" "github.com/ghodss/yaml" + "github.com/pkg/errors" "github.com/spf13/cobra" "k8s.io/helm/pkg/chartutil" @@ -250,7 +250,7 @@ func (o *installOptions) run(out io.Writer) error { } } else if err != chartutil.ErrRequirementsNotFound { - return fmt.Errorf("cannot load requirements: %v", err) + return errors.Wrap(err, "cannot load requirements") } rel, err := o.client.InstallReleaseFromChart( @@ -315,7 +315,7 @@ func mergeValues(dest, src map[string]interface{}) map[string]interface{} { // vals merges values from files specified via -f/--values and // directly via --set or --set-string, marshaling them to YAML -func vals(valueFiles valueFiles, values []string, stringValues []string) ([]byte, error) { +func vals(valueFiles valueFiles, values, stringValues []string) ([]byte, error) { base := map[string]interface{}{} // User specified a values files via -f/--values @@ -335,7 +335,7 @@ func vals(valueFiles valueFiles, values []string, stringValues []string) ([]byte } if err := yaml.Unmarshal(bytes, ¤tMap); err != nil { - return []byte{}, fmt.Errorf("failed to parse %s: %s", filePath, err) + return []byte{}, errors.Wrapf(err, "failed to parse %s", filePath) } // Merge with the previous map base = mergeValues(base, currentMap) @@ -344,14 +344,14 @@ func vals(valueFiles valueFiles, values []string, stringValues []string) ([]byte // User specified a value via --set for _, value := range values { if err := strvals.ParseInto(value, base); err != nil { - return []byte{}, fmt.Errorf("failed parsing --set data: %s", err) + return []byte{}, errors.Wrap(err, "failed parsing --set data") } } // User specified a value via --set-string for _, value := range stringValues { if err := strvals.ParseIntoString(value, base); err != nil { - return []byte{}, fmt.Errorf("failed parsing --set-string data: %s", err) + return []byte{}, errors.Wrap(err, "failed parsing --set-string data") } } @@ -401,7 +401,7 @@ func locateChartPath(repoURL, username, password, name, version string, verify b return abs, nil } if filepath.IsAbs(name) || strings.HasPrefix(name, ".") { - return name, fmt.Errorf("path %q not found", name) + return name, errors.Errorf("path %q not found", name) } crepo := filepath.Join(settings.Home.Repository(), name) @@ -445,7 +445,7 @@ func locateChartPath(repoURL, username, password, name, version string, verify b return filename, err } - return filename, fmt.Errorf("failed to download %q (hint: running `helm repo update` may help)", name) + return filename, errors.Errorf("failed to download %q (hint: running `helm repo update` may help)", name) } func generateName(nameTemplate string) (string, error) { @@ -479,7 +479,7 @@ func checkDependencies(ch *chart.Chart, reqs *chartutil.Requirements) error { } if len(missing) > 0 { - return fmt.Errorf("found in requirements.yaml, but missing in charts/ directory: %s", strings.Join(missing, ", ")) + return errors.Errorf("found in requirements.yaml, but missing in charts/ directory: %s", strings.Join(missing, ", ")) } return nil } diff --git a/cmd/helm/lint.go b/cmd/helm/lint.go index ae7e533d6..f2ba0ef9f 100644 --- a/cmd/helm/lint.go +++ b/cmd/helm/lint.go @@ -17,7 +17,6 @@ limitations under the License. package main import ( - "errors" "fmt" "io" "io/ioutil" @@ -26,6 +25,7 @@ import ( "strings" "github.com/ghodss/yaml" + "github.com/pkg/errors" "github.com/spf13/cobra" "k8s.io/helm/pkg/chartutil" @@ -74,7 +74,7 @@ func newLintCmd(out io.Writer) *cobra.Command { return cmd } -var errLintNoChart = errors.New("No chart found for linting (missing Chart.yaml)") +var errLintNoChart = errors.New("no chart found for linting (missing Chart.yaml)") func (o *lintOptions) run(out io.Writer) error { var lowestTolerance int @@ -120,7 +120,7 @@ func (o *lintOptions) run(out io.Writer) error { msg := fmt.Sprintf("%d chart(s) linted", total) if failures > 0 { - return fmt.Errorf("%s, %d chart(s) failed", msg, failures) + return errors.Errorf("%s, %d chart(s) failed", msg, failures) } fmt.Fprintf(out, "%s, no failures\n", msg) @@ -151,7 +151,7 @@ func lintChart(path string, vals []byte, namespace string, strict bool) (support lastHyphenIndex := strings.LastIndex(filepath.Base(path), "-") if lastHyphenIndex <= 0 { - return linter, fmt.Errorf("unable to parse chart archive %q, missing '-'", filepath.Base(path)) + return linter, errors.Errorf("unable to parse chart archive %q, missing '-'", filepath.Base(path)) } base := filepath.Base(path)[:lastHyphenIndex] chartPath = filepath.Join(tempDir, base) @@ -179,7 +179,7 @@ func (o *lintOptions) vals() ([]byte, error) { } if err := yaml.Unmarshal(bytes, ¤tMap); err != nil { - return []byte{}, fmt.Errorf("failed to parse %s: %s", filePath, err) + return []byte{}, errors.Wrapf(err, "failed to parse %s", filePath) } // Merge with the previous map base = mergeValues(base, currentMap) @@ -188,14 +188,14 @@ func (o *lintOptions) vals() ([]byte, error) { // User specified a value via --set for _, value := range o.values { if err := strvals.ParseInto(value, base); err != nil { - return []byte{}, fmt.Errorf("failed parsing --set data: %s", err) + return []byte{}, errors.Wrap(err, "failed parsing --set data") } } // User specified a value via --set-string for _, value := range o.sValues { if err := strvals.ParseIntoString(value, base); err != nil { - return []byte{}, fmt.Errorf("failed parsing --set-string data: %s", err) + return []byte{}, errors.Wrap(err, "failed parsing --set-string data") } } diff --git a/cmd/helm/lint_test.go b/cmd/helm/lint_test.go index 973af9b63..d4fca66a8 100644 --- a/cmd/helm/lint_test.go +++ b/cmd/helm/lint_test.go @@ -33,22 +33,18 @@ var ( func TestLintChart(t *testing.T) { if _, err := lintChart(chartDirPath, values, namespace, strict); err != nil { - t.Errorf("%s", err) + t.Error(err) } - if _, err := lintChart(archivedChartPath, values, namespace, strict); err != nil { - t.Errorf("%s", err) + t.Error(err) } - if _, err := lintChart(archivedChartPathWithHyphens, values, namespace, strict); err != nil { - t.Errorf("%s", err) + t.Error(err) } - if _, err := lintChart(invalidArchivedChartPath, values, namespace, strict); err == nil { - t.Errorf("Expected a chart parsing error") + t.Error("Expected a chart parsing error") } - if _, err := lintChart(chartMissingManifest, values, namespace, strict); err == nil { - t.Errorf("Expected a chart parsing error") + t.Error("Expected a chart parsing error") } } diff --git a/cmd/helm/load_plugins.go b/cmd/helm/load_plugins.go index 73b76ec61..129ffcb1b 100644 --- a/cmd/helm/load_plugins.go +++ b/cmd/helm/load_plugins.go @@ -23,6 +23,7 @@ import ( "path/filepath" "strings" + "github.com/pkg/errors" "github.com/spf13/cobra" "k8s.io/helm/pkg/plugin" @@ -87,7 +88,7 @@ func loadPlugins(baseCmd *cobra.Command, out io.Writer) { if err := prog.Run(); err != nil { if eerr, ok := err.(*exec.ExitError); ok { os.Stderr.Write(eerr.Stderr) - return fmt.Errorf("plugin %q exited with error", md.Name) + return errors.Errorf("plugin %q exited with error", md.Name) } return err } diff --git a/cmd/helm/package.go b/cmd/helm/package.go index d82421372..1181afab4 100644 --- a/cmd/helm/package.go +++ b/cmd/helm/package.go @@ -17,7 +17,6 @@ limitations under the License. package main import ( - "errors" "fmt" "io" "io/ioutil" @@ -27,6 +26,7 @@ import ( "github.com/Masterminds/semver" "github.com/ghodss/yaml" + "github.com/pkg/errors" "github.com/spf13/cobra" "golang.org/x/crypto/ssh/terminal" @@ -77,7 +77,7 @@ func newPackageCmd(out io.Writer) *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { o.home = settings.Home if len(args) == 0 { - return fmt.Errorf("need at least one argument, the path to the chart") + return errors.Errorf("need at least one argument, the path to the chart") } if o.sign { if o.key == "" { @@ -166,7 +166,7 @@ func (o *packageOptions) run(out io.Writer) error { } if filepath.Base(path) != ch.Metadata.Name { - return fmt.Errorf("directory name (%s) and Chart.yaml name (%s) must match", filepath.Base(path), ch.Metadata.Name) + return errors.Errorf("directory name (%s) and Chart.yaml name (%s) must match", filepath.Base(path), ch.Metadata.Name) } if reqs, err := chartutil.LoadRequirements(ch); err == nil { @@ -195,7 +195,7 @@ func (o *packageOptions) run(out io.Writer) error { if err == nil { fmt.Fprintf(out, "Successfully packaged chart and saved it to: %s\n", name) } else { - return fmt.Errorf("Failed to save: %s", err) + return errors.Wrap(err, "failed to save") } if o.sign { diff --git a/cmd/helm/plugin.go b/cmd/helm/plugin.go index 08cbcbfb4..16b859fcb 100644 --- a/cmd/helm/plugin.go +++ b/cmd/helm/plugin.go @@ -16,13 +16,13 @@ limitations under the License. package main import ( - "fmt" "io" "os" "os/exec" "k8s.io/helm/pkg/plugin" + "github.com/pkg/errors" "github.com/spf13/cobra" ) @@ -64,7 +64,7 @@ func runHook(p *plugin.Plugin, event string) error { if err := prog.Run(); err != nil { if eerr, ok := err.(*exec.ExitError); ok { os.Stderr.Write(eerr.Stderr) - return fmt.Errorf("plugin %s hook for %q exited with error", event, p.Metadata.Name) + return errors.Errorf("plugin %s hook for %q exited with error", event, p.Metadata.Name) } return err } diff --git a/cmd/helm/plugin_remove.go b/cmd/helm/plugin_remove.go index f52430479..104b5fda8 100644 --- a/cmd/helm/plugin_remove.go +++ b/cmd/helm/plugin_remove.go @@ -16,16 +16,16 @@ limitations under the License. package main import ( - "errors" "fmt" "io" "os" "strings" + "github.com/pkg/errors" + "github.com/spf13/cobra" + "k8s.io/helm/pkg/helm/helmpath" "k8s.io/helm/pkg/plugin" - - "github.com/spf13/cobra" ) type pluginRemoveOptions struct { @@ -76,7 +76,7 @@ func (o *pluginRemoveOptions) run(out io.Writer) error { } } if len(errorPlugins) > 0 { - return fmt.Errorf(strings.Join(errorPlugins, "\n")) + return errors.Errorf(strings.Join(errorPlugins, "\n")) } return nil } diff --git a/cmd/helm/plugin_update.go b/cmd/helm/plugin_update.go index d91a5aa3e..67817de8e 100644 --- a/cmd/helm/plugin_update.go +++ b/cmd/helm/plugin_update.go @@ -16,17 +16,17 @@ limitations under the License. package main import ( - "errors" "fmt" "io" "path/filepath" "strings" + "github.com/pkg/errors" + "github.com/spf13/cobra" + "k8s.io/helm/pkg/helm/helmpath" "k8s.io/helm/pkg/plugin" "k8s.io/helm/pkg/plugin/installer" - - "github.com/spf13/cobra" ) type pluginUpdateOptions struct { @@ -79,7 +79,7 @@ func (o *pluginUpdateOptions) run(out io.Writer) error { } } if len(errorPlugins) > 0 { - return fmt.Errorf(strings.Join(errorPlugins, "\n")) + return errors.Errorf(strings.Join(errorPlugins, "\n")) } return nil } diff --git a/cmd/helm/release_testing.go b/cmd/helm/release_testing.go index 63f277fc0..51dfffe63 100644 --- a/cmd/helm/release_testing.go +++ b/cmd/helm/release_testing.go @@ -20,6 +20,7 @@ import ( "fmt" "io" + "github.com/pkg/errors" "github.com/spf13/cobra" "k8s.io/helm/pkg/hapi/release" @@ -98,5 +99,5 @@ type testErr struct { } func (err *testErr) Error() error { - return fmt.Errorf("%v test(s) failed", err.failed) + return errors.Errorf("%v test(s) failed", err.failed) } diff --git a/cmd/helm/repo_add.go b/cmd/helm/repo_add.go index f615ceffe..dad3b8df3 100644 --- a/cmd/helm/repo_add.go +++ b/cmd/helm/repo_add.go @@ -20,6 +20,7 @@ import ( "fmt" "io" + "github.com/pkg/errors" "github.com/spf13/cobra" "k8s.io/helm/pkg/getter" @@ -85,7 +86,7 @@ func addRepository(name, url, username, password string, home helmpath.Home, cer } if noUpdate && f.Has(name) { - return fmt.Errorf("repository name (%s) already exists, please specify a different name", name) + return errors.Errorf("repository name (%s) already exists, please specify a different name", name) } cif := home.CacheIndex(name) @@ -106,7 +107,7 @@ func addRepository(name, url, username, password string, home helmpath.Home, cer } if err := r.DownloadIndexFile(home.Cache()); err != nil { - return fmt.Errorf("Looks like %q is not a valid chart repository or cannot be reached: %s", url, err.Error()) + return errors.Wrapf(err, "looks like %q is not a valid chart repository or cannot be reached", url) } f.Update(&c) diff --git a/cmd/helm/repo_index.go b/cmd/helm/repo_index.go index 82758ebc5..499d3ea22 100644 --- a/cmd/helm/repo_index.go +++ b/cmd/helm/repo_index.go @@ -17,11 +17,11 @@ limitations under the License. package main import ( - "fmt" "io" "os" "path/filepath" + "github.com/pkg/errors" "github.com/spf13/cobra" "k8s.io/helm/pkg/repo" @@ -94,7 +94,7 @@ func index(dir, url, mergeTo string) error { } else { i2, err = repo.LoadIndexFile(mergeTo) if err != nil { - return fmt.Errorf("Merge failed: %s", err) + return errors.Wrap(err, "merge failed") } } i.Merge(i2) diff --git a/cmd/helm/repo_list.go b/cmd/helm/repo_list.go index 9a34b96bd..4275c2fcf 100644 --- a/cmd/helm/repo_list.go +++ b/cmd/helm/repo_list.go @@ -17,11 +17,11 @@ limitations under the License. package main import ( - "errors" "fmt" "io" "github.com/gosuri/uitable" + "github.com/pkg/errors" "github.com/spf13/cobra" "k8s.io/helm/pkg/helm/helmpath" diff --git a/cmd/helm/repo_remove.go b/cmd/helm/repo_remove.go index fceb75f7c..a27bee307 100644 --- a/cmd/helm/repo_remove.go +++ b/cmd/helm/repo_remove.go @@ -21,6 +21,7 @@ import ( "io" "os" + "github.com/pkg/errors" "github.com/spf13/cobra" "k8s.io/helm/pkg/helm/helmpath" @@ -65,7 +66,7 @@ func removeRepoLine(out io.Writer, name string, home helmpath.Home) error { } if !r.Remove(name) { - return fmt.Errorf("no repo named %q found", name) + return errors.Errorf("no repo named %q found", name) } if err := r.WriteFile(repoFile, 0644); err != nil { return err diff --git a/cmd/helm/repo_update.go b/cmd/helm/repo_update.go index 7bf63f514..d6b89f9bd 100644 --- a/cmd/helm/repo_update.go +++ b/cmd/helm/repo_update.go @@ -17,11 +17,11 @@ limitations under the License. package main import ( - "errors" "fmt" "io" "sync" + "github.com/pkg/errors" "github.com/spf13/cobra" "k8s.io/helm/pkg/getter" diff --git a/cmd/helm/rollback.go b/cmd/helm/rollback.go index 429b6aaef..5dd002909 100644 --- a/cmd/helm/rollback.go +++ b/cmd/helm/rollback.go @@ -21,6 +21,7 @@ import ( "io" "strconv" + "github.com/pkg/errors" "github.com/spf13/cobra" "k8s.io/helm/pkg/helm" @@ -62,7 +63,7 @@ func newRollbackCmd(c helm.Interface, out io.Writer) *cobra.Command { v64, err := strconv.ParseInt(args[1], 10, 32) if err != nil { - return fmt.Errorf("invalid revision number '%q': %s", args[1], err) + return errors.Wrapf(err, "invalid revision number '%q'", args[1]) } o.revision = int(v64) diff --git a/cmd/helm/search.go b/cmd/helm/search.go index 2200f0016..10c895b4d 100644 --- a/cmd/helm/search.go +++ b/cmd/helm/search.go @@ -23,6 +23,7 @@ import ( "github.com/Masterminds/semver" "github.com/gosuri/uitable" + "github.com/pkg/errors" "github.com/spf13/cobra" "k8s.io/helm/cmd/helm/search" @@ -104,7 +105,7 @@ func (o *searchOptions) applyConstraint(res []*search.Result) ([]*search.Result, constraint, err := semver.NewConstraint(o.version) if err != nil { - return res, fmt.Errorf("an invalid version/constraint format: %s", err) + return res, errors.Wrap(err, "an invalid version/constraint format") } data := res[:0] diff --git a/cmd/helm/search/search.go b/cmd/helm/search/search.go index 6c4cb4aa4..baccdaf56 100644 --- a/cmd/helm/search/search.go +++ b/cmd/helm/search/search.go @@ -23,13 +23,14 @@ to find matches. package search import ( - "errors" "path" "regexp" "sort" "strings" "github.com/Masterminds/semver" + "github.com/pkg/errors" + "k8s.io/helm/pkg/repo" ) diff --git a/cmd/helm/status.go b/cmd/helm/status.go index ab30cddb5..f16b66bcf 100644 --- a/cmd/helm/status.go +++ b/cmd/helm/status.go @@ -26,6 +26,7 @@ import ( "github.com/ghodss/yaml" "github.com/gosuri/uitable" "github.com/gosuri/uitable/util/strutil" + "github.com/pkg/errors" "github.com/spf13/cobra" "k8s.io/helm/pkg/hapi" @@ -87,20 +88,20 @@ func (o *statusOptions) run(out io.Writer) error { case "json": data, err := json.Marshal(res) if err != nil { - return fmt.Errorf("Failed to Marshal JSON output: %s", err) + return errors.Wrap(err, "failed to Marshal JSON output") } out.Write(data) return nil case "yaml": data, err := yaml.Marshal(res) if err != nil { - return fmt.Errorf("Failed to Marshal YAML output: %s", err) + return errors.Wrap(err, "failed to Marshal YAML output") } out.Write(data) return nil } - return fmt.Errorf("Unknown output format %q", o.outfmt) + return errors.Errorf("unknown output format %q", o.outfmt) } // PrintStatus prints out the status of a release. Shared because also used by diff --git a/cmd/helm/template.go b/cmd/helm/template.go index 83966bfe9..2c8fb1284 100644 --- a/cmd/helm/template.go +++ b/cmd/helm/template.go @@ -17,7 +17,6 @@ limitations under the License. package main import ( - "errors" "fmt" "io" "os" @@ -28,6 +27,7 @@ import ( "time" "github.com/Masterminds/semver" + "github.com/pkg/errors" "github.com/spf13/cobra" "k8s.io/helm/pkg/chartutil" @@ -120,7 +120,7 @@ func (o *templateOptions) run(out io.Writer) error { if !filepath.IsAbs(f) { af, err = filepath.Abs(filepath.Join(o.chartPath, f)) if err != nil { - return fmt.Errorf("could not resolve template path: %s", err) + return errors.Wrap(err, "could not resolve template path") } } else { af = f @@ -128,7 +128,7 @@ func (o *templateOptions) run(out io.Writer) error { rf = append(rf, af) if _, err := os.Stat(af); err != nil { - return fmt.Errorf("could not resolve template path: %s", err) + return errors.Wrap(err, "could not resolve template path") } } } @@ -137,7 +137,7 @@ func (o *templateOptions) run(out io.Writer) error { if o.outputDir != "" { _, err = os.Stat(o.outputDir) if os.IsNotExist(err) { - return fmt.Errorf("output-dir '%s' does not exist", o.outputDir) + return errors.Errorf("output-dir '%s' does not exist", o.outputDir) } } @@ -166,7 +166,7 @@ func (o *templateOptions) run(out io.Writer) error { return err } } else if err != chartutil.ErrRequirementsNotFound { - return fmt.Errorf("cannot load requirements: %v", err) + return errors.Wrap(err, "cannot load requirements") } options := chartutil.ReleaseOptions{ Name: o.releaseName, @@ -195,7 +195,7 @@ func (o *templateOptions) run(out io.Writer) error { // kubernetes version kv, err := semver.NewVersion(o.kubeVersion) if err != nil { - return fmt.Errorf("could not parse a kubernetes version: %v", err) + return errors.Wrap(err, "could not parse a kubernetes version") } caps.KubeVersion.Major = fmt.Sprint(kv.Major()) caps.KubeVersion.Minor = fmt.Sprint(kv.Minor()) @@ -277,7 +277,7 @@ func (o *templateOptions) run(out io.Writer) error { } // write the to / -func writeToFile(outputDir string, name string, data string) error { +func writeToFile(outputDir, name, data string) error { outfileName := strings.Join([]string{outputDir, name}, string(filepath.Separator)) err := ensureDirectoryForFile(outfileName) diff --git a/cmd/helm/testdata/output/install-no-args.txt b/cmd/helm/testdata/output/install-no-args.txt index 6e40280f9..7a4172b64 100644 --- a/cmd/helm/testdata/output/install-no-args.txt +++ b/cmd/helm/testdata/output/install-no-args.txt @@ -1 +1 @@ -Error: This command needs 1 argument: chart name +Error: this command needs 1 argument: chart name diff --git a/cmd/helm/testdata/output/rollback-no-args.txt b/cmd/helm/testdata/output/rollback-no-args.txt index 7d36e31af..bee077279 100644 --- a/cmd/helm/testdata/output/rollback-no-args.txt +++ b/cmd/helm/testdata/output/rollback-no-args.txt @@ -1 +1 @@ -Error: This command needs 2 arguments: release name, revision number +Error: this command needs 2 arguments: release name, revision number diff --git a/cmd/helm/testdata/output/upgrade-with-missing-dependencies.txt b/cmd/helm/testdata/output/upgrade-with-missing-dependencies.txt index 4325478d7..f5fea53ed 100644 --- a/cmd/helm/testdata/output/upgrade-with-missing-dependencies.txt +++ b/cmd/helm/testdata/output/upgrade-with-missing-dependencies.txt @@ -1 +1 @@ -Error: This command needs 2 arguments: release name, chart path +Error: this command needs 2 arguments: release name, chart path diff --git a/cmd/helm/upgrade.go b/cmd/helm/upgrade.go index 4e2a2efc0..38feb91f3 100644 --- a/cmd/helm/upgrade.go +++ b/cmd/helm/upgrade.go @@ -21,6 +21,7 @@ import ( "io" "strings" + "github.com/pkg/errors" "github.com/spf13/cobra" "k8s.io/helm/pkg/chartutil" @@ -132,8 +133,6 @@ func newUpgradeCmd(client helm.Interface, out io.Writer) *cobra.Command { f.StringVar(&o.caFile, "ca-file", "", "verify certificates of HTTPS-enabled servers using this CA bundle") f.BoolVar(&o.devel, "devel", false, "use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored.") - f.MarkDeprecated("disable-hooks", "use --no-hooks instead") - return cmd } @@ -180,7 +179,7 @@ func (o *upgradeOptions) run(out io.Writer) error { return err } } else if err != chartutil.ErrRequirementsNotFound { - return fmt.Errorf("cannot load requirements: %v", err) + return errors.Wrap(err, "cannot load requirements") } } else { return err @@ -199,7 +198,7 @@ func (o *upgradeOptions) run(out io.Writer) error { helm.ReuseValues(o.reuseValues), helm.UpgradeWait(o.wait)) if err != nil { - return fmt.Errorf("UPGRADE FAILED: %v", err) + return errors.Wrap(err, "UPGRADE FAILED") } if settings.Debug { diff --git a/cmd/helm/verify.go b/cmd/helm/verify.go index c1a1e975d..4c96e5434 100644 --- a/cmd/helm/verify.go +++ b/cmd/helm/verify.go @@ -16,9 +16,9 @@ limitations under the License. package main import ( - "errors" "io" + "github.com/pkg/errors" "github.com/spf13/cobra" "k8s.io/helm/pkg/downloader" diff --git a/pkg/chartutil/chartfile.go b/pkg/chartutil/chartfile.go index fcee815b6..461e47357 100644 --- a/pkg/chartutil/chartfile.go +++ b/pkg/chartutil/chartfile.go @@ -17,13 +17,12 @@ limitations under the License. package chartutil import ( - "errors" - "fmt" "io/ioutil" "os" "path/filepath" "github.com/ghodss/yaml" + "github.com/pkg/errors" "k8s.io/helm/pkg/hapi/chart" ) @@ -68,17 +67,17 @@ func IsChartDir(dirName string) (bool, error) { if fi, err := os.Stat(dirName); err != nil { return false, err } else if !fi.IsDir() { - return false, fmt.Errorf("%q is not a directory", dirName) + return false, errors.Errorf("%q is not a directory", dirName) } chartYaml := filepath.Join(dirName, "Chart.yaml") if _, err := os.Stat(chartYaml); os.IsNotExist(err) { - return false, fmt.Errorf("no Chart.yaml exists in directory %q", dirName) + return false, errors.Errorf("no Chart.yaml exists in directory %q", dirName) } chartYamlContent, err := ioutil.ReadFile(chartYaml) if err != nil { - return false, fmt.Errorf("cannot read Chart.Yaml in directory %q", dirName) + return false, errors.Errorf("cannot read Chart.Yaml in directory %q", dirName) } chartContent, err := UnmarshalChartfile(chartYamlContent) diff --git a/pkg/chartutil/create.go b/pkg/chartutil/create.go index c6b148d4e..de0cceb18 100644 --- a/pkg/chartutil/create.go +++ b/pkg/chartutil/create.go @@ -22,6 +22,8 @@ import ( "os" "path/filepath" + "github.com/pkg/errors" + "k8s.io/helm/pkg/hapi/chart" ) @@ -291,10 +293,10 @@ Create chart name and version as used by the chart label. ` // CreateFrom creates a new chart, but scaffolds it from the src chart. -func CreateFrom(chartfile *chart.Metadata, dest string, src string) error { +func CreateFrom(chartfile *chart.Metadata, dest, src string) error { schart, err := Load(src) if err != nil { - return fmt.Errorf("could not load %s: %s", src, err) + return errors.Wrapf(err, "could not load %s", src) } schart.Metadata = chartfile @@ -334,13 +336,13 @@ func Create(chartfile *chart.Metadata, dir string) (string, error) { if fi, err := os.Stat(path); err != nil { return path, err } else if !fi.IsDir() { - return path, fmt.Errorf("no such directory %s", path) + return path, errors.Errorf("no such directory %s", path) } n := chartfile.Name cdir := filepath.Join(path, n) if fi, err := os.Stat(cdir); err == nil && !fi.IsDir() { - return cdir, fmt.Errorf("file %s already exists and is not a directory", cdir) + return cdir, errors.Errorf("file %s already exists and is not a directory", cdir) } if err := os.MkdirAll(cdir, 0755); err != nil { return cdir, err diff --git a/pkg/chartutil/load.go b/pkg/chartutil/load.go index b3ea63510..44bcbde03 100644 --- a/pkg/chartutil/load.go +++ b/pkg/chartutil/load.go @@ -20,14 +20,14 @@ import ( "archive/tar" "bytes" "compress/gzip" - "errors" - "fmt" "io" "io/ioutil" "os" "path/filepath" "strings" + "github.com/pkg/errors" + "k8s.io/helm/pkg/hapi/chart" "k8s.io/helm/pkg/ignore" "k8s.io/helm/pkg/sympath" @@ -169,7 +169,7 @@ func LoadFiles(files []*BufferedFile) (*chart.Chart, error) { } else if filepath.Ext(n) == ".tgz" { file := files[0] if file.Name != n { - return c, fmt.Errorf("error unpacking tar in %s: expected %s, got %s", c.Metadata.Name, n, file.Name) + return c, errors.Errorf("error unpacking tar in %s: expected %s, got %s", c.Metadata.Name, n, file.Name) } // Untar the chart and add to c.Dependencies b := bytes.NewBuffer(file.Data) @@ -190,7 +190,7 @@ func LoadFiles(files []*BufferedFile) (*chart.Chart, error) { } if err != nil { - return c, fmt.Errorf("error unpacking %s in %s: %s", n, c.Metadata.Name, err) + return c, errors.Wrapf(err, "error unpacking %s in %s", n, c.Metadata.Name) } c.Dependencies = append(c.Dependencies, sc) @@ -272,7 +272,7 @@ func LoadDir(dir string) (*chart.Chart, error) { data, err := ioutil.ReadFile(name) if err != nil { - return fmt.Errorf("error reading %s: %s", n, err) + return errors.Wrapf(err, "error reading %s", n) } files = append(files, &BufferedFile{Name: n, Data: data}) diff --git a/pkg/chartutil/requirements.go b/pkg/chartutil/requirements.go index e91eddfca..e43c44e13 100644 --- a/pkg/chartutil/requirements.go +++ b/pkg/chartutil/requirements.go @@ -16,12 +16,12 @@ limitations under the License. package chartutil import ( - "errors" "log" "strings" "time" "github.com/ghodss/yaml" + "github.com/pkg/errors" "k8s.io/helm/pkg/hapi/chart" "k8s.io/helm/pkg/version" diff --git a/pkg/chartutil/save.go b/pkg/chartutil/save.go index d4884fff6..610f0aca0 100644 --- a/pkg/chartutil/save.go +++ b/pkg/chartutil/save.go @@ -19,13 +19,13 @@ package chartutil import ( "archive/tar" "compress/gzip" - "errors" "fmt" "io/ioutil" "os" "path/filepath" "github.com/ghodss/yaml" + "github.com/pkg/errors" "k8s.io/helm/pkg/hapi/chart" ) @@ -105,7 +105,7 @@ func Save(c *chart.Chart, outDir string) (string, error) { if fi, err := os.Stat(outDir); err != nil { return "", err } else if !fi.IsDir() { - return "", fmt.Errorf("location %s is not a directory", outDir) + return "", errors.Errorf("location %s is not a directory", outDir) } if c.Metadata == nil { @@ -126,7 +126,7 @@ func Save(c *chart.Chart, outDir string) (string, error) { return "", err } } else if !stat.IsDir() { - return "", fmt.Errorf("is not a directory: %s", filepath.Dir(filename)) + return "", errors.Errorf("is not a directory: %s", filepath.Dir(filename)) } f, err := os.Create(filename) diff --git a/pkg/chartutil/transform.go b/pkg/chartutil/transform.go index 7cbb754fb..f360e4fad 100644 --- a/pkg/chartutil/transform.go +++ b/pkg/chartutil/transform.go @@ -20,6 +20,6 @@ import "strings" // Transform performs a string replacement of the specified source for // a given key with the replacement string -func Transform(src string, key string, replacement string) []byte { +func Transform(src, key, replacement string) []byte { return []byte(strings.Replace(src, key, replacement, -1)) } diff --git a/pkg/chartutil/values.go b/pkg/chartutil/values.go index 49a849c0e..edd87fc2b 100644 --- a/pkg/chartutil/values.go +++ b/pkg/chartutil/values.go @@ -17,8 +17,6 @@ limitations under the License. package chartutil import ( - "errors" - "fmt" "io" "io/ioutil" "log" @@ -26,6 +24,7 @@ import ( "time" "github.com/ghodss/yaml" + "github.com/pkg/errors" "k8s.io/helm/pkg/hapi/chart" ) @@ -98,7 +97,7 @@ func (v Values) Encode(w io.Writer) error { func tableLookup(v Values, simple string) (Values, error) { v2, ok := v[simple] if !ok { - return v, ErrNoTable(fmt.Errorf("no table named %q (%v)", simple, v)) + return v, ErrNoTable(errors.Errorf("no table named %q (%v)", simple, v)) } if vv, ok := v2.(map[string]interface{}); ok { return vv, nil @@ -111,7 +110,7 @@ func tableLookup(v Values, simple string) (Values, error) { return vv, nil } - var e ErrNoTable = fmt.Errorf("no table named %q", simple) + var e ErrNoTable = errors.Errorf("no table named %q", simple) return map[string]interface{}{}, e } @@ -182,7 +181,7 @@ func coalesceDeps(chrt *chart.Chart, dest map[string]interface{}) (map[string]in // If dest doesn't already have the key, create it. dest[subchart.Metadata.Name] = map[string]interface{}{} } else if !istable(c) { - return dest, fmt.Errorf("type mismatch on %s: %t", subchart.Metadata.Name, c) + return dest, errors.Errorf("type mismatch on %s: %t", subchart.Metadata.Name, c) } if dv, ok := dest[subchart.Metadata.Name]; ok { dvmap := dv.(map[string]interface{}) @@ -276,7 +275,7 @@ func coalesceValues(c *chart.Chart, v map[string]interface{}) (map[string]interf // On error, we return just the overridden values. // FIXME: We should log this error. It indicates that the YAML data // did not parse. - return v, fmt.Errorf("error reading default values (%s): %s", c.Values, err) + return v, errors.Wrapf(err, "error reading default values (%s)", c.Values) } for key, val := range nv { @@ -410,7 +409,7 @@ func (v Values) PathValue(ypath string) (interface{}, error) { return vals[yps[0]], nil } // key not found - return nil, ErrNoValue(fmt.Errorf("%v is not a value", k)) + return nil, ErrNoValue(errors.Errorf("%v is not a value", k)) } // join all elements of YAML path except last to get string table path ypsLen := len(yps) @@ -422,7 +421,7 @@ func (v Values) PathValue(ypath string) (interface{}, error) { t, err := v.Table(st) if err != nil { //no table - return nil, ErrNoValue(fmt.Errorf("%v is not a value", sk)) + return nil, ErrNoValue(errors.Errorf("%v is not a value", sk)) } // check table for key and ensure value is not a table if k, ok := t[sk]; ok && !istable(k) { @@ -431,5 +430,5 @@ func (v Values) PathValue(ypath string) (interface{}, error) { } // key not found - return nil, ErrNoValue(fmt.Errorf("key not found: %s", sk)) + return nil, ErrNoValue(errors.Errorf("key not found: %s", sk)) } diff --git a/pkg/downloader/chart_downloader.go b/pkg/downloader/chart_downloader.go index fe2f3ce92..ce7c397df 100644 --- a/pkg/downloader/chart_downloader.go +++ b/pkg/downloader/chart_downloader.go @@ -16,7 +16,6 @@ limitations under the License. package downloader import ( - "errors" "fmt" "io" "io/ioutil" @@ -25,6 +24,8 @@ import ( "path/filepath" "strings" + "github.com/pkg/errors" + "k8s.io/helm/pkg/getter" "k8s.io/helm/pkg/helm/helmpath" "k8s.io/helm/pkg/provenance" @@ -107,7 +108,7 @@ func (c *ChartDownloader) DownloadTo(ref, version, dest string) (string, *proven body, err := r.Client.Get(u.String() + ".prov") if err != nil { if c.Verify == VerifyAlways { - return destfile, ver, fmt.Errorf("Failed to fetch provenance %q", u.String()+".prov") + return destfile, ver, errors.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 @@ -155,7 +156,7 @@ func (c *ChartDownloader) ResolveChartVersion(ref, version string) (*url.URL, ge func (c *ChartDownloader) ResolveChartVersionAndGetRepo(ref, version string) (*url.URL, *repo.ChartRepository, *getter.HttpGetter, error) { u, err := url.Parse(ref) if err != nil { - return nil, nil, nil, fmt.Errorf("invalid chart URL format: %s", ref) + return nil, nil, nil, errors.Errorf("invalid chart URL format: %s", ref) } rf, err := repo.LoadRepositoriesFile(c.HelmHome.RepositoryFile()) @@ -196,7 +197,7 @@ func (c *ChartDownloader) ResolveChartVersionAndGetRepo(ref, version string) (*u // See if it's of the form: repo/path_to_chart p := strings.SplitN(u.Path, "/", 2) if len(p) < 2 { - return u, nil, nil, fmt.Errorf("Non-absolute URLs should be in form of repo_name/path_to_chart, got: %s", u) + return u, nil, nil, errors.Errorf("non-absolute URLs should be in form of repo_name/path_to_chart, got: %s", u) } repoName := p[0] @@ -216,22 +217,22 @@ func (c *ChartDownloader) ResolveChartVersionAndGetRepo(ref, version string) (*u // Next, we need to load the index, and actually look up the chart. i, err := repo.LoadIndexFile(c.HelmHome.CacheIndex(r.Config.Name)) if err != nil { - return u, r, g, fmt.Errorf("no cached repo found. (try 'helm repo update'). %s", err) + return u, r, g, errors.Wrap(err, "no cached repo found. (try 'helm repo update')") } cv, err := i.Get(chartName, version) if err != nil { - return u, r, g, fmt.Errorf("chart %q matching %s not found in %s index. (try 'helm repo update'). %s", chartName, version, r.Config.Name, err) + return u, r, g, errors.Wrapf(err, "chart %q matching %s not found in %s index. (try 'helm repo update')", chartName, version, r.Config.Name) } if len(cv.URLs) == 0 { - return u, r, g, fmt.Errorf("chart %q has no downloadable URLs", ref) + return u, r, g, errors.Errorf("chart %q has no downloadable URLs", ref) } // TODO: Seems that picking first URL is not fully correct u, err = url.Parse(cv.URLs[0]) if err != nil { - return u, r, g, fmt.Errorf("invalid chart URL format: %s", ref) + return u, r, g, errors.Errorf("invalid chart URL format: %s", ref) } // If the URL is relative (no scheme), prepend the chart repo's base URL @@ -277,7 +278,7 @@ func (c *ChartDownloader) getRepoCredentials(r *repo.ChartRepository) (username, // // It assumes that a chart archive file is accompanied by a provenance file whose // name is the archive file name plus the ".prov" extension. -func VerifyChart(path string, keyring string) (*provenance.Verification, error) { +func VerifyChart(path, keyring string) (*provenance.Verification, error) { // For now, error out if it's not a tar file. if fi, err := os.Stat(path); err != nil { return nil, err @@ -289,12 +290,12 @@ func VerifyChart(path string, keyring string) (*provenance.Verification, error) provfile := path + ".prov" if _, err := os.Stat(provfile); err != nil { - return nil, fmt.Errorf("could not load provenance file %s: %s", provfile, err) + return nil, errors.Wrapf(err, "could not load provenance file %s", provfile) } sig, err := provenance.NewFromKeyring(keyring, "") if err != nil { - return nil, fmt.Errorf("failed to load keyring: %s", err) + return nil, errors.Wrap(err, "failed to load keyring") } return sig.Verify(path, provfile) } @@ -311,12 +312,12 @@ func pickChartRepositoryConfigByName(name string, cfgs []*repo.Entry) (*repo.Ent for _, rc := range cfgs { if rc.Name == name { if rc.URL == "" { - return nil, fmt.Errorf("no URL found for repository %s", name) + return nil, errors.Errorf("no URL found for repository %s", name) } return rc, nil } } - return nil, fmt.Errorf("repo %s not found", name) + return nil, errors.Errorf("repo %s not found", name) } // scanReposForURL scans all repos to find which repo contains the given URL. @@ -348,7 +349,7 @@ func (c *ChartDownloader) scanReposForURL(u string, rf *repo.RepoFile) (*repo.En i, err := repo.LoadIndexFile(c.HelmHome.CacheIndex(r.Config.Name)) if err != nil { - return nil, fmt.Errorf("no cached repo found. (try 'helm repo update'). %s", err) + return nil, errors.Wrap(err, "no cached repo found. (try 'helm repo update')") } for _, entry := range i.Entries { diff --git a/pkg/downloader/manager.go b/pkg/downloader/manager.go index a1fe276cd..a59e7dc0d 100644 --- a/pkg/downloader/manager.go +++ b/pkg/downloader/manager.go @@ -16,7 +16,6 @@ limitations under the License. package downloader import ( - "errors" "fmt" "io" "io/ioutil" @@ -29,6 +28,7 @@ import ( "github.com/Masterminds/semver" "github.com/ghodss/yaml" + "github.com/pkg/errors" "k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/getter" @@ -80,10 +80,10 @@ func (m *Manager) Build() error { // A lock must accompany a requirements.yaml file. req, err := chartutil.LoadRequirements(c) if err != nil { - return fmt.Errorf("requirements.yaml cannot be opened: %s", err) + return errors.Wrap(err, "requirements.yaml cannot be opened") } if sum, err := resolver.HashReq(req); err != nil || sum != lock.Digest { - return fmt.Errorf("requirements.lock is out of sync with requirements.yaml") + return errors.New("requirements.lock is out of sync with requirements.yaml") } // Check that all of the repos we're dependent on actually exist. @@ -172,7 +172,7 @@ func (m *Manager) Update() error { func (m *Manager) loadChartDir() (*chart.Chart, error) { if fi, err := os.Stat(m.ChartPath); err != nil { - return nil, fmt.Errorf("could not find %s: %s", m.ChartPath, err) + return nil, errors.Wrapf(err, "could not find %s", m.ChartPath) } else if !fi.IsDir() { return nil, errors.New("only unpacked charts can be updated") } @@ -206,11 +206,11 @@ func (m *Manager) downloadAll(deps []*chartutil.Dependency) error { return err } } else if !fi.IsDir() { - return fmt.Errorf("%q is not a directory", destPath) + return errors.Errorf("%q is not a directory", destPath) } if err := os.Rename(destPath, tmpPath); err != nil { - return fmt.Errorf("Unable to move current charts to tmp dir: %v", err) + return errors.Wrap(err, "unable to move current charts to tmp dir") } if err := os.MkdirAll(destPath, 0755); err != nil { @@ -239,7 +239,7 @@ func (m *Manager) downloadAll(deps []*chartutil.Dependency) error { // https://github.com/kubernetes/helm/issues/1439 churl, username, password, err := findChartURL(dep.Name, dep.Version, dep.Repository, repos) if err != nil { - saveError = fmt.Errorf("could not find %s: %s", churl, err) + saveError = errors.Wrapf(err, "could not find %s", churl) break } @@ -254,7 +254,7 @@ func (m *Manager) downloadAll(deps []*chartutil.Dependency) error { } if _, _, err := dl.DownloadTo(churl, "", destPath); err != nil { - saveError = fmt.Errorf("could not download %s: %s", churl, err) + saveError = errors.Wrapf(err, "could not download %s", churl) break } } @@ -270,7 +270,7 @@ func (m *Manager) downloadAll(deps []*chartutil.Dependency) error { return err } if err := os.RemoveAll(tmpPath); err != nil { - return fmt.Errorf("Failed to remove %v: %v", tmpPath, err) + return errors.Wrapf(err, "failed to remove %v", tmpPath) } } else { fmt.Fprintln(m.Out, "Save error occurred: ", saveError) @@ -281,10 +281,10 @@ func (m *Manager) downloadAll(deps []*chartutil.Dependency) error { } } if err := os.RemoveAll(destPath); err != nil { - return fmt.Errorf("Failed to remove %v: %v", destPath, err) + return errors.Wrapf(err, "failed to remove %v", destPath) } if err := os.Rename(tmpPath, destPath); err != nil { - return fmt.Errorf("Unable to move current charts to tmp dir: %v", err) + return errors.Wrap(err, "unable to move current charts to tmp dir") } return saveError } @@ -356,7 +356,7 @@ func (m *Manager) hasAllRepos(deps []*chartutil.Dependency) error { } } if len(missing) > 0 { - return fmt.Errorf("no repository definition for %s. Please add the missing repos via 'helm repo add'", strings.Join(missing, ", ")) + return errors.Errorf("no repository definition for %s. Please add the missing repos via 'helm repo add'", strings.Join(missing, ", ")) } return nil } @@ -500,7 +500,7 @@ func findChartURL(name, version, repoURL string, repos map[string]*repo.ChartRep return } } - err = fmt.Errorf("chart %s not found in %s", name, repoURL) + err = errors.Errorf("chart %s not found in %s", name, repoURL) return } @@ -556,7 +556,7 @@ func normalizeURL(baseURL, urlOrPath string) (string, error) { } u2, err := url.Parse(baseURL) if err != nil { - return urlOrPath, fmt.Errorf("Base URL failed to parse: %s", err) + return urlOrPath, errors.Wrap(err, "base URL failed to parse") } u2.Path = path.Join(u2.Path, urlOrPath) @@ -574,7 +574,7 @@ func (m *Manager) loadChartRepositories() (map[string]*repo.ChartRepository, err // Load repositories.yaml file rf, err := repo.LoadRepositoriesFile(repoyaml) if err != nil { - return indices, fmt.Errorf("failed to load %s: %s", repoyaml, err) + return indices, errors.Wrapf(err, "failed to load %s", repoyaml) } for _, re := range rf.Repositories { @@ -606,11 +606,11 @@ func writeLock(chartpath string, lock *chartutil.RequirementsLock) error { } // archive a dep chart from local directory and save it into charts/ -func tarFromLocalDir(chartpath string, name string, repo string, version string) (string, error) { +func tarFromLocalDir(chartpath, name, repo, version string) (string, error) { destPath := filepath.Join(chartpath, "charts") if !strings.HasPrefix(repo, "file://") { - return "", fmt.Errorf("wrong format: chart %s repository %s", name, repo) + return "", errors.Errorf("wrong format: chart %s repository %s", name, repo) } origPath, err := resolver.GetLocalPath(repo, chartpath) @@ -625,7 +625,7 @@ func tarFromLocalDir(chartpath string, name string, repo string, version string) constraint, err := semver.NewConstraint(version) if err != nil { - return "", fmt.Errorf("dependency %s has an invalid version/constraint format: %s", name, err) + return "", errors.Wrapf(err, "dependency %s has an invalid version/constraint format", name) } v, err := semver.NewVersion(ch.Metadata.Version) @@ -638,7 +638,7 @@ func tarFromLocalDir(chartpath string, name string, repo string, version string) return ch.Metadata.Version, err } - return "", fmt.Errorf("can't get a valid version for dependency %s", name) + return "", errors.Errorf("can't get a valid version for dependency %s", name) } // move files from tmppath to destpath @@ -649,7 +649,7 @@ func move(tmpPath, destPath string) error { tmpfile := filepath.Join(tmpPath, filename) destfile := filepath.Join(destPath, filename) if err := os.Rename(tmpfile, destfile); err != nil { - return fmt.Errorf("Unable to move local charts to charts dir: %v", err) + return errors.Wrap(err, "unable to move local charts to charts dir") } } return nil diff --git a/pkg/engine/engine.go b/pkg/engine/engine.go index b29e63707..f09a8ec7c 100644 --- a/pkg/engine/engine.go +++ b/pkg/engine/engine.go @@ -18,13 +18,13 @@ package engine import ( "bytes" - "fmt" "path" "sort" "strings" "text/template" "github.com/Masterminds/sprig" + "github.com/pkg/errors" "k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/hapi/chart" @@ -155,10 +155,10 @@ func (e *Engine) alterFuncMap(t *template.Template) template.FuncMap { // Add the 'required' function here funcMap["required"] = func(warn string, val interface{}) (interface{}, error) { if val == nil { - return val, fmt.Errorf(warn) + return val, errors.Errorf(warn) } else if _, ok := val.(string); ok { if val == "" { - return val, fmt.Errorf(warn) + return val, errors.Errorf(warn) } } return val, nil @@ -168,7 +168,7 @@ func (e *Engine) alterFuncMap(t *template.Template) template.FuncMap { funcMap["tpl"] = func(tpl string, vals chartutil.Values) (string, error) { basePath, err := vals.PathValue("Template.BasePath") if err != nil { - return "", fmt.Errorf("Cannot retrieve Template.Basepath from values inside tpl function: %s (%s)", tpl, err.Error()) + return "", errors.Wrapf(err, "cannot retrieve Template.Basepath from values inside tpl function: %s", tpl) } r := renderable{ @@ -180,14 +180,14 @@ func (e *Engine) alterFuncMap(t *template.Template) template.FuncMap { templates := map[string]renderable{} templateName, err := vals.PathValue("Template.Name") if err != nil { - return "", fmt.Errorf("Cannot retrieve Template.Name from values inside tpl function: %s (%s)", tpl, err.Error()) + return "", errors.Wrapf(err, "cannot retrieve Template.Name from values inside tpl function: %s", tpl) } templates[templateName.(string)] = r result, err := e.render(templates) if err != nil { - return "", fmt.Errorf("Error during tpl function execution for %q: %s", tpl, err.Error()) + return "", errors.Wrapf(err, "error during tpl function execution for %q", tpl) } return result[templateName.(string)], nil } @@ -206,7 +206,7 @@ func (e *Engine) render(tpls map[string]renderable) (rendered map[string]string, // template engine. defer func() { if r := recover(); r != nil { - err = fmt.Errorf("rendering template failed: %v", r) + err = errors.Errorf("rendering template failed: %v", r) } }() t := template.New("gotpl") @@ -230,7 +230,7 @@ func (e *Engine) render(tpls map[string]renderable) (rendered map[string]string, r := tpls[fname] t = t.New(fname).Funcs(funcMap) if _, err := t.Parse(r.tpl); err != nil { - return map[string]string{}, fmt.Errorf("parse error in %q: %s", fname, err) + return map[string]string{}, errors.Wrapf(err, "parse error in %q", fname) } files = append(files, fname) } @@ -241,7 +241,7 @@ func (e *Engine) render(tpls map[string]renderable) (rendered map[string]string, if t.Lookup(fname) == nil { t = t.New(fname).Funcs(funcMap) if _, err := t.Parse(r.tpl); err != nil { - return map[string]string{}, fmt.Errorf("parse error in %q: %s", fname, err) + return map[string]string{}, errors.Wrapf(err, "parse error in %q", fname) } } } @@ -258,7 +258,7 @@ func (e *Engine) render(tpls map[string]renderable) (rendered map[string]string, vals := tpls[file].vals vals["Template"] = map[string]interface{}{"Name": file, "BasePath": tpls[file].basePath} if err := t.ExecuteTemplate(&buf, file, vals); err != nil { - return map[string]string{}, fmt.Errorf("render error in %q: %s", file, err) + return map[string]string{}, errors.Wrapf(err, "render error in %q", file) } // Work around the issue where Go will emit "" even if Options(missing=zero) diff --git a/pkg/getter/getter.go b/pkg/getter/getter.go index ca018884a..3456ba33a 100644 --- a/pkg/getter/getter.go +++ b/pkg/getter/getter.go @@ -18,7 +18,8 @@ package getter import ( "bytes" - "fmt" + + "github.com/pkg/errors" "k8s.io/helm/pkg/helm/environment" ) @@ -64,7 +65,7 @@ func (p Providers) ByScheme(scheme string) (Constructor, error) { return pp.New, nil } } - return nil, fmt.Errorf("scheme %q not supported", scheme) + return nil, errors.Errorf("scheme %q not supported", scheme) } // All finds all of the registered getters as a list of Provider instances. @@ -94,5 +95,5 @@ func ByScheme(scheme string, settings environment.EnvSettings) (Provider, error) return p, nil } } - return Provider{}, fmt.Errorf("scheme %q not supported", scheme) + return Provider{}, errors.Errorf("scheme %q not supported", scheme) } diff --git a/pkg/getter/httpgetter.go b/pkg/getter/httpgetter.go index 3c20e35e1..b66a5c9b8 100644 --- a/pkg/getter/httpgetter.go +++ b/pkg/getter/httpgetter.go @@ -17,11 +17,12 @@ package getter import ( "bytes" - "fmt" "io" "net/http" "strings" + "github.com/pkg/errors" + "k8s.io/helm/pkg/tlsutil" "k8s.io/helm/pkg/urlutil" "k8s.io/helm/pkg/version" @@ -66,7 +67,7 @@ func (g *HttpGetter) get(href string) (*bytes.Buffer, error) { return buf, err } if resp.StatusCode != 200 { - return buf, fmt.Errorf("Failed to fetch %s : %s", href, resp.Status) + return buf, errors.Errorf("failed to fetch %s : %s", href, resp.Status) } _, err = io.Copy(buf, resp.Body) @@ -85,7 +86,7 @@ func NewHTTPGetter(URL, CertFile, KeyFile, CAFile string) (*HttpGetter, error) { if CertFile != "" && KeyFile != "" { tlsConf, err := tlsutil.NewClientTLS(CertFile, KeyFile, CAFile) if err != nil { - return &client, fmt.Errorf("can't create TLS config for client: %s", err.Error()) + return &client, errors.Wrap(err, "can't create TLS config for client") } tlsConf.BuildNameToCertificate() diff --git a/pkg/getter/plugingetter.go b/pkg/getter/plugingetter.go index c747eef7f..2ff813f06 100644 --- a/pkg/getter/plugingetter.go +++ b/pkg/getter/plugingetter.go @@ -17,11 +17,12 @@ package getter import ( "bytes" - "fmt" "os" "os/exec" "path/filepath" + "github.com/pkg/errors" + "k8s.io/helm/pkg/helm/environment" "k8s.io/helm/pkg/plugin" ) @@ -72,7 +73,7 @@ func (p *pluginGetter) Get(href string) (*bytes.Buffer, error) { if err := prog.Run(); err != nil { if eerr, ok := err.(*exec.ExitError); ok { os.Stderr.Write(eerr.Stderr) - return nil, fmt.Errorf("plugin %q exited with error", p.command) + return nil, errors.Errorf("plugin %q exited with error", p.command) } return nil, err } diff --git a/pkg/helm/client.go b/pkg/helm/client.go index 7a2a8d247..7ce4e912d 100644 --- a/pkg/helm/client.go +++ b/pkg/helm/client.go @@ -134,7 +134,7 @@ func (c *Client) DeleteRelease(rlsName string, opts ...DeleteOption) (*hapi.Unin } // UpdateRelease loads a chart from chstr and updates a release to a new/different chart. -func (c *Client) UpdateRelease(rlsName string, chstr string, opts ...UpdateOption) (*release.Release, error) { +func (c *Client) UpdateRelease(rlsName, chstr string, opts ...UpdateOption) (*release.Release, error) { // load the chart to update chart, err := chartutil.Load(chstr) if err != nil { diff --git a/pkg/helm/fake.go b/pkg/helm/fake.go index c5c399aa6..c3409225f 100644 --- a/pkg/helm/fake.go +++ b/pkg/helm/fake.go @@ -17,12 +17,12 @@ limitations under the License. package helm // import "k8s.io/helm/pkg/helm" import ( - "errors" - "fmt" "math/rand" "sync" "time" + "github.com/pkg/errors" + "k8s.io/helm/pkg/hapi" "k8s.io/helm/pkg/hapi/chart" "k8s.io/helm/pkg/hapi/release" @@ -88,11 +88,11 @@ func (c *FakeClient) DeleteRelease(rlsName string, opts ...DeleteOption) (*hapi. } } - return nil, fmt.Errorf("No such release: %s", rlsName) + return nil, errors.Errorf("no such release: %s", rlsName) } // UpdateRelease returns the updated release, if it exists -func (c *FakeClient) UpdateRelease(rlsName string, chStr string, opts ...UpdateOption) (*release.Release, error) { +func (c *FakeClient) UpdateRelease(rlsName, chStr string, opts ...UpdateOption) (*release.Release, error) { return c.UpdateReleaseFromChart(rlsName, &chart.Chart{}, opts...) } @@ -118,7 +118,7 @@ func (c *FakeClient) ReleaseStatus(rlsName string, version int) (*hapi.GetReleas }, nil } } - return nil, fmt.Errorf("No such release: %s", rlsName) + return nil, errors.Errorf("no such release: %s", rlsName) } // ReleaseContent returns the configuration for the matching release name in the fake release client. @@ -128,7 +128,7 @@ func (c *FakeClient) ReleaseContent(rlsName string, version int) (*release.Relea return rel, nil } } - return nil, fmt.Errorf("No such release: %s", rlsName) + return nil, errors.Errorf("no such release: %s", rlsName) } // ReleaseHistory returns a release's revision history. diff --git a/pkg/helm/helm_test.go b/pkg/helm/helm_test.go index a2d44c610..16fa2fd9c 100644 --- a/pkg/helm/helm_test.go +++ b/pkg/helm/helm_test.go @@ -17,11 +17,12 @@ limitations under the License. package helm // import "k8s.io/helm/pkg/helm" import ( - "errors" "path/filepath" "reflect" "testing" + "github.com/pkg/errors" + "k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/hapi" cpb "k8s.io/helm/pkg/hapi/chart" diff --git a/pkg/ignore/rules.go b/pkg/ignore/rules.go index 76f45fc7a..a4ac55c47 100644 --- a/pkg/ignore/rules.go +++ b/pkg/ignore/rules.go @@ -18,12 +18,13 @@ package ignore import ( "bufio" - "errors" "io" "log" "os" "path/filepath" "strings" + + "github.com/pkg/errors" ) // HelmIgnore default name of an ignorefile. diff --git a/pkg/kube/client.go b/pkg/kube/client.go index 950472666..bf530408e 100644 --- a/pkg/kube/client.go +++ b/pkg/kube/client.go @@ -19,7 +19,6 @@ package kube // import "k8s.io/helm/pkg/kube" import ( "bytes" "encoding/json" - goerrors "errors" "fmt" "io" "log" @@ -27,6 +26,7 @@ import ( "time" jsonpatch "github.com/evanphx/json-patch" + goerrors "github.com/pkg/errors" appsv1 "k8s.io/api/apps/v1" appsv1beta1 "k8s.io/api/apps/v1beta1" appsv1beta2 "k8s.io/api/apps/v1beta2" @@ -213,8 +213,7 @@ func (c *Client) Get(namespace string, reader io.Reader) (string, error) { } for _, o := range ot { if err := p.PrintObj(o, buf); err != nil { - c.Log("failed to print object type %s, object: %q :\n %v", t, o, err) - return "", err + return "", goerrors.Wrapf(err, "failed to print object type %s, object: %q", t, o) } } if _, err := buf.WriteString("\n"); err != nil { @@ -236,16 +235,16 @@ func (c *Client) Get(namespace string, reader io.Reader) (string, error) { // not present in the target configuration. // // Namespace will set the namespaces. -func (c *Client) Update(namespace string, originalReader, targetReader io.Reader, force bool, recreate bool, timeout int64, shouldWait bool) error { +func (c *Client) Update(namespace string, originalReader, targetReader io.Reader, force, recreate bool, timeout int64, shouldWait bool) error { original, err := c.BuildUnstructured(namespace, originalReader) if err != nil { - return fmt.Errorf("failed decoding reader into objects: %s", err) + return goerrors.Wrap(err, "failed decoding reader into objects") } c.Log("building resources from updated manifest") target, err := c.BuildUnstructured(namespace, targetReader) if err != nil { - return fmt.Errorf("failed decoding reader into objects: %s", err) + return goerrors.Wrap(err, "failed decoding reader into objects") } updateErrors := []string{} @@ -259,12 +258,12 @@ func (c *Client) Update(namespace string, originalReader, targetReader io.Reader helper := resource.NewHelper(info.Client, info.Mapping) if _, err := helper.Get(info.Namespace, info.Name, info.Export); err != nil { if !errors.IsNotFound(err) { - return fmt.Errorf("Could not get information about the resource: %s", err) + return goerrors.Wrap(err, "could not get information about the resource") } // Since the resource does not exist, create it. if err := createResource(info); err != nil { - return fmt.Errorf("failed to create resource: %s", err) + return goerrors.Wrap(err, "failed to create resource") } kind := info.Mapping.GroupVersionKind.Kind @@ -275,7 +274,7 @@ func (c *Client) Update(namespace string, originalReader, targetReader io.Reader originalInfo := original.Get(info) if originalInfo == nil { kind := info.Mapping.GroupVersionKind.Kind - return fmt.Errorf("no %s with the name %q found", kind, info.Name) + return goerrors.Errorf("no %s with the name %q found", kind, info.Name) } if err := updateResource(c, info, originalInfo.Object, force, recreate); err != nil { @@ -290,7 +289,7 @@ func (c *Client) Update(namespace string, originalReader, targetReader io.Reader case err != nil: return err case len(updateErrors) != 0: - return fmt.Errorf(strings.Join(updateErrors, " && ")) + return goerrors.Errorf(strings.Join(updateErrors, " && ")) } for _, info := range original.Difference(target) { @@ -393,11 +392,11 @@ func deleteResource(c *Client, info *resource.Info) error { func createPatch(target *resource.Info, current runtime.Object) ([]byte, types.PatchType, error) { oldData, err := json.Marshal(current) if err != nil { - return nil, types.StrategicMergePatchType, fmt.Errorf("serializing current configuration: %s", err) + return nil, types.StrategicMergePatchType, goerrors.Wrap(err, "serializing current configuration") } newData, err := json.Marshal(target.Object) if err != nil { - return nil, types.StrategicMergePatchType, fmt.Errorf("serializing target configuration: %s", err) + return nil, types.StrategicMergePatchType, goerrors.Wrap(err, "serializing target configuration") } // While different objects need different merge types, the parent function @@ -423,24 +422,24 @@ func createPatch(target *resource.Info, current runtime.Object) ([]byte, types.P patch, err := jsonpatch.CreateMergePatch(oldData, newData) return patch, types.MergePatchType, err case err != nil: - return nil, types.StrategicMergePatchType, fmt.Errorf("failed to get versionedObject: %s", err) + return nil, types.StrategicMergePatchType, goerrors.Wrap(err, "failed to get versionedObject") default: patch, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, versionedObject) return patch, types.StrategicMergePatchType, err } } -func updateResource(c *Client, target *resource.Info, currentObj runtime.Object, force bool, recreate bool) error { +func updateResource(c *Client, target *resource.Info, currentObj runtime.Object, force, recreate bool) error { patch, patchType, err := createPatch(target, currentObj) if err != nil { - return fmt.Errorf("failed to create patch: %s", err) + return goerrors.Wrap(err, "failed to create patch") } if patch == nil { c.Log("Looks like there are no changes for %s %q", target.Mapping.GroupVersionKind.Kind, target.Name) // This needs to happen to make sure that tiller 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 fmt.Errorf("error trying to refresh resource information: %v", err) + return goerrors.Wrap(err, "error trying to refresh resource information") } } else { // send patch to server @@ -460,7 +459,7 @@ func updateResource(c *Client, target *resource.Info, currentObj runtime.Object, // ... and recreate if err := createResource(target); err != nil { - return fmt.Errorf("Failed to recreate resource: %s", err) + return goerrors.Wrap(err, "failed to recreate resource") } log.Printf("Created a new %s called %q\n", kind, target.Name) @@ -557,7 +556,7 @@ func getSelectorFromObject(obj runtime.Object) (map[string]string, error) { return typed.Spec.Selector.MatchLabels, nil default: - return nil, fmt.Errorf("Unsupported kind when getting selector: %v", obj) + return nil, goerrors.Errorf("unsupported kind when getting selector: %v", obj) } } @@ -594,7 +593,7 @@ func (c *Client) watchUntilReady(timeout time.Duration, info *resource.Info) err case watch.Error: // Handle error and return with an error. c.Log("Error event for %s", info.Name) - return true, fmt.Errorf("Failed to deploy %s", info.Name) + return true, goerrors.Errorf("failed to deploy %s", info.Name) default: return false, nil } @@ -608,14 +607,14 @@ func (c *Client) watchUntilReady(timeout time.Duration, info *resource.Info) err func (c *Client) waitForJob(e watch.Event, name string) (bool, error) { o, ok := e.Object.(*batchinternal.Job) if !ok { - return true, fmt.Errorf("Expected %s to be a *batch.Job, got %T", name, e.Object) + return true, goerrors.Errorf("expected %s to be a *batch.Job, got %T", name, e.Object) } for _, c := range o.Status.Conditions { if c.Type == batchinternal.JobComplete && c.Status == core.ConditionTrue { return true, nil } else if c.Type == batchinternal.JobFailed && c.Status == core.ConditionTrue { - return true, fmt.Errorf("Job failed: %s", c.Reason) + return true, goerrors.Errorf("job failed: %s", c.Reason) } } @@ -647,7 +646,7 @@ func (c *Client) WaitAndGetCompletedPodPhase(namespace string, reader io.Reader, kind := info.Mapping.GroupVersionKind.Kind if kind != "Pod" { - return core.PodUnknown, fmt.Errorf("%s is not a Pod", info.Name) + return core.PodUnknown, goerrors.Errorf("%s is not a Pod", info.Name) } if err := c.watchPodUntilComplete(timeout, info); err != nil { diff --git a/pkg/lint/rules/chartfile.go b/pkg/lint/rules/chartfile.go index da50d0bee..30691c500 100644 --- a/pkg/lint/rules/chartfile.go +++ b/pkg/lint/rules/chartfile.go @@ -17,14 +17,12 @@ limitations under the License. package rules // import "k8s.io/helm/pkg/lint/rules" import ( - "errors" - "fmt" "os" "path/filepath" "github.com/Masterminds/semver" - "github.com/asaskevich/govalidator" + "github.com/pkg/errors" "k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/hapi/chart" @@ -68,7 +66,7 @@ func validateChartYamlNotDirectory(chartPath string) error { func validateChartYamlFormat(chartFileError error) error { if chartFileError != nil { - return fmt.Errorf("unable to parse YAML\n\t%s", chartFileError.Error()) + return errors.Errorf("unable to parse YAML\n\t%s", chartFileError.Error()) } return nil } @@ -82,7 +80,7 @@ func validateChartName(cf *chart.Metadata) error { func validateChartNameDirMatch(chartDir string, cf *chart.Metadata) error { if cf.Name != filepath.Base(chartDir) { - return fmt.Errorf("directory name (%s) and chart name (%s) must be the same", filepath.Base(chartDir), cf.Name) + return errors.Errorf("directory name (%s) and chart name (%s) must be the same", filepath.Base(chartDir), cf.Name) } return nil } @@ -95,7 +93,7 @@ func validateChartVersion(cf *chart.Metadata) error { version, err := semver.NewVersion(cf.Version) if err != nil { - return fmt.Errorf("version '%s' is not a valid SemVer", cf.Version) + return errors.Errorf("version '%s' is not a valid SemVer", cf.Version) } c, err := semver.NewConstraint("> 0") @@ -105,7 +103,7 @@ func validateChartVersion(cf *chart.Metadata) error { valid, msg := c.Validate(version) if !valid && len(msg) > 0 { - return fmt.Errorf("version %v", msg[0]) + return errors.Errorf("version %v", msg[0]) } return nil @@ -116,9 +114,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 fmt.Errorf("invalid email '%s' for maintainer '%s'", maintainer.Email, maintainer.Name) + return errors.Errorf("invalid email '%s' for maintainer '%s'", maintainer.Email, maintainer.Name) } else if maintainer.URL != "" && !govalidator.IsURL(maintainer.URL) { - return fmt.Errorf("invalid url '%s' for maintainer '%s'", maintainer.URL, maintainer.Name) + return errors.Errorf("invalid url '%s' for maintainer '%s'", maintainer.URL, maintainer.Name) } } return nil @@ -127,7 +125,7 @@ func validateChartMaintainer(cf *chart.Metadata) error { func validateChartSources(cf *chart.Metadata) error { for _, source := range cf.Sources { if source == "" || !govalidator.IsRequestURL(source) { - return fmt.Errorf("invalid source URL '%s'", source) + return errors.Errorf("invalid source URL '%s'", source) } } return nil @@ -142,7 +140,7 @@ func validateChartIconPresence(cf *chart.Metadata) error { func validateChartIconURL(cf *chart.Metadata) error { if cf.Icon != "" && !govalidator.IsRequestURL(cf.Icon) { - return fmt.Errorf("invalid icon URL '%s'", cf.Icon) + return errors.Errorf("invalid icon URL '%s'", cf.Icon) } return nil } diff --git a/pkg/lint/rules/chartfile_test.go b/pkg/lint/rules/chartfile_test.go index acc506eb7..4af73422e 100644 --- a/pkg/lint/rules/chartfile_test.go +++ b/pkg/lint/rules/chartfile_test.go @@ -17,12 +17,13 @@ limitations under the License. package rules import ( - "errors" "os" "path/filepath" "strings" "testing" + "github.com/pkg/errors" + "k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/hapi/chart" "k8s.io/helm/pkg/lint/support" diff --git a/pkg/lint/rules/template.go b/pkg/lint/rules/template.go index e4d640cd0..6405d9ab2 100644 --- a/pkg/lint/rules/template.go +++ b/pkg/lint/rules/template.go @@ -17,13 +17,12 @@ limitations under the License. package rules import ( - "errors" - "fmt" "os" "path/filepath" "time" "github.com/ghodss/yaml" + "github.com/pkg/errors" "k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/engine" @@ -145,14 +144,11 @@ func validateAllowedExtension(fileName string) error { } } - return fmt.Errorf("file extension '%s' not valid. Valid extensions are .yaml, .yml, .tpl, or .txt", ext) + return errors.Errorf("file extension '%s' not valid. Valid extensions are .yaml, .yml, .tpl, or .txt", ext) } func validateYamlContent(err error) error { - if err != nil { - return fmt.Errorf("unable to parse YAML\n\t%s", err) - } - return nil + return errors.Wrap(err, "unable to parse YAML") } // K8sYamlStruct stubs a Kubernetes YAML file. diff --git a/pkg/lint/rules/values.go b/pkg/lint/rules/values.go index 20ed41115..6404dca1e 100644 --- a/pkg/lint/rules/values.go +++ b/pkg/lint/rules/values.go @@ -17,10 +17,11 @@ limitations under the License. package rules import ( - "fmt" "os" "path/filepath" + "github.com/pkg/errors" + "k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/lint/support" ) @@ -41,15 +42,12 @@ func Values(linter *support.Linter) { func validateValuesFileExistence(valuesPath string) error { _, err := os.Stat(valuesPath) if err != nil { - return fmt.Errorf("file does not exist") + return errors.Errorf("file does not exist") } return nil } func validateValuesFile(valuesPath string) error { _, err := chartutil.ReadValuesFile(valuesPath) - if err != nil { - return fmt.Errorf("unable to parse YAML\n\t%s", err) - } - return nil + return errors.Wrap(err, "unable to parse YAML") } diff --git a/pkg/lint/support/message_test.go b/pkg/lint/support/message_test.go index 4a9c33c34..782642099 100644 --- a/pkg/lint/support/message_test.go +++ b/pkg/lint/support/message_test.go @@ -17,8 +17,9 @@ limitations under the License. package support import ( - "errors" "testing" + + "github.com/pkg/errors" ) var linter = Linter{} diff --git a/pkg/plugin/installer/http_installer.go b/pkg/plugin/installer/http_installer.go index 59c5454d5..80c560147 100644 --- a/pkg/plugin/installer/http_installer.go +++ b/pkg/plugin/installer/http_installer.go @@ -19,13 +19,14 @@ import ( "archive/tar" "bytes" "compress/gzip" - "fmt" "io" "os" "path/filepath" "regexp" "strings" + "github.com/pkg/errors" + "k8s.io/helm/pkg/getter" "k8s.io/helm/pkg/helm/environment" "k8s.io/helm/pkg/helm/helmpath" @@ -62,7 +63,7 @@ func NewExtractor(source string) (Extractor, error) { return extractor, nil } } - return nil, fmt.Errorf("no extractor implemented yet for %s", source) + return nil, errors.Errorf("no extractor implemented yet for %s", source) } // NewHTTPInstaller creates a new HttpInstaller. @@ -141,7 +142,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 fmt.Errorf("method Update() not implemented for HttpInstaller") + return errors.Errorf("method Update() not implemented for HttpInstaller") } // Override link because we want to use HttpInstaller.Path() not base.Path() @@ -200,7 +201,7 @@ func (g *TarGzExtractor) Extract(buffer *bytes.Buffer, targetDir string) error { } outFile.Close() default: - return fmt.Errorf("unknown type: %b in %s", header.Typeflag, header.Name) + return errors.Errorf("unknown type: %b in %s", header.Typeflag, header.Name) } } diff --git a/pkg/plugin/installer/http_installer_test.go b/pkg/plugin/installer/http_installer_test.go index 7756c0091..0020487b5 100644 --- a/pkg/plugin/installer/http_installer_test.go +++ b/pkg/plugin/installer/http_installer_test.go @@ -18,11 +18,12 @@ package installer // import "k8s.io/helm/pkg/plugin/installer" import ( "bytes" "encoding/base64" - "fmt" "io/ioutil" "os" "testing" + "github.com/pkg/errors" + "k8s.io/helm/pkg/helm/helmpath" ) @@ -131,7 +132,7 @@ func TestHTTPInstallerNonExistentVersion(t *testing.T) { // inject fake http client responding with error httpInstaller.getter = &TestHTTPGetter{ - MockError: fmt.Errorf("failed to download plugin for some reason"), + MockError: errors.Errorf("failed to download plugin for some reason"), } // attempt to install the plugin diff --git a/pkg/plugin/installer/installer.go b/pkg/plugin/installer/installer.go index 02aee9f46..a377ab28f 100644 --- a/pkg/plugin/installer/installer.go +++ b/pkg/plugin/installer/installer.go @@ -16,13 +16,14 @@ limitations under the License. package installer import ( - "errors" "fmt" "os" "path" "path/filepath" "strings" + "github.com/pkg/errors" + "k8s.io/helm/pkg/helm/helmpath" ) diff --git a/pkg/plugin/installer/local_installer.go b/pkg/plugin/installer/local_installer.go index 3cf6bb422..bc6266981 100644 --- a/pkg/plugin/installer/local_installer.go +++ b/pkg/plugin/installer/local_installer.go @@ -16,9 +16,10 @@ limitations under the License. package installer // import "k8s.io/helm/pkg/plugin/installer" import ( - "fmt" "path/filepath" + "github.com/pkg/errors" + "k8s.io/helm/pkg/helm/helmpath" ) @@ -31,7 +32,7 @@ type LocalInstaller struct { func NewLocalInstaller(source string, home helmpath.Home) (*LocalInstaller, error) { src, err := filepath.Abs(source) if err != nil { - return nil, fmt.Errorf("unable to get absolute path to plugin: %v", err) + return nil, errors.Wrap(err, "unable to get absolute path to plugin") } i := &LocalInstaller{ base: newBase(src, home), diff --git a/pkg/plugin/installer/vcs_installer.go b/pkg/plugin/installer/vcs_installer.go index 0a373a971..e57ba1224 100644 --- a/pkg/plugin/installer/vcs_installer.go +++ b/pkg/plugin/installer/vcs_installer.go @@ -16,13 +16,12 @@ limitations under the License. package installer // import "k8s.io/helm/pkg/plugin/installer" import ( - "errors" - "fmt" "os" "sort" "github.com/Masterminds/semver" "github.com/Masterminds/vcs" + "github.com/pkg/errors" "k8s.io/helm/pkg/helm/helmpath" "k8s.io/helm/pkg/plugin/cache" @@ -143,7 +142,7 @@ func (i *VCSInstaller) solveVersion(repo vcs.Repo) (string, error) { } } - return "", fmt.Errorf("requested version %q does not exist for plugin %q", i.Version, i.Repo.Remote()) + return "", errors.Errorf("requested version %q does not exist for plugin %q", i.Version, i.Repo.Remote()) } // setVersion attempts to checkout the version diff --git a/pkg/provenance/sign.go b/pkg/provenance/sign.go index 7bbd96cae..4d1803454 100644 --- a/pkg/provenance/sign.go +++ b/pkg/provenance/sign.go @@ -19,8 +19,6 @@ import ( "bytes" "crypto" "encoding/hex" - "errors" - "fmt" "io" "io/ioutil" "os" @@ -28,7 +26,7 @@ import ( "strings" "github.com/ghodss/yaml" - + "github.com/pkg/errors" "golang.org/x/crypto/openpgp" "golang.org/x/crypto/openpgp/clearsign" "golang.org/x/crypto/openpgp/packet" @@ -142,7 +140,7 @@ func NewFromKeyring(keyringfile, id string) (*Signatory, error) { } } if vague { - return s, fmt.Errorf("more than one key contain the id %q", id) + return s, errors.Errorf("more than one key contain the id %q", id) } s.Entity = candidate @@ -238,14 +236,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, fmt.Errorf("%s cannot be a directory", fname) + return ver, errors.Errorf("%s cannot be a directory", fname) } } // First verify the signature sig, err := s.decodeSignature(sigpath) if err != nil { - return ver, fmt.Errorf("failed to decode signature: %s", err) + return ver, errors.Wrap(err, "failed to decode signature") } by, err := s.verifySignature(sig) @@ -267,9 +265,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, fmt.Errorf("provenance does not contain a SHA for a file named %q", basename) + return ver, errors.Errorf("provenance does not contain a SHA for a file named %q", basename) } else if sha != sum { - return ver, fmt.Errorf("sha256 sum does not match for %s: %q != %q", basename, sha, sum) + return ver, errors.Errorf("sha256 sum does not match for %s: %q != %q", basename, sha, sum) } ver.FileHash = sum ver.FileName = basename diff --git a/pkg/releasetesting/environment_test.go b/pkg/releasetesting/environment_test.go index 5a2080587..ee290f5c7 100644 --- a/pkg/releasetesting/environment_test.go +++ b/pkg/releasetesting/environment_test.go @@ -17,9 +17,10 @@ limitations under the License. package releasetesting import ( - "errors" "testing" + "github.com/pkg/errors" + "k8s.io/helm/pkg/hapi/release" ) diff --git a/pkg/releasetesting/test_suite.go b/pkg/releasetesting/test_suite.go index fb66785e4..b8a7fc8a1 100644 --- a/pkg/releasetesting/test_suite.go +++ b/pkg/releasetesting/test_suite.go @@ -17,11 +17,11 @@ limitations under the License. package releasetesting import ( - "fmt" "strings" "time" "github.com/ghodss/yaml" + "github.com/pkg/errors" "k8s.io/kubernetes/pkg/apis/core" "k8s.io/helm/pkg/hapi/release" @@ -141,7 +141,7 @@ func expectedSuccess(hookTypes []string) (bool, error) { return false, nil } } - return false, fmt.Errorf("No %s or %s hook found", hooks.ReleaseTestSuccess, hooks.ReleaseTestFailure) + return false, errors.Errorf("no %s or %s hook found", hooks.ReleaseTestSuccess, hooks.ReleaseTestFailure) } func extractTestManifestsFromHooks(h []*release.Hook) []string { @@ -165,7 +165,7 @@ func newTest(testManifest string) (*test, error) { } if sh.Kind != "Pod" { - return nil, fmt.Errorf("%s is not a pod", sh.Metadata.Name) + return nil, errors.Errorf("%s is not a pod", sh.Metadata.Name) } hookTypes := sh.Metadata.Annotations[hooks.HookAnno] diff --git a/pkg/repo/chartrepo.go b/pkg/repo/chartrepo.go index bf03a68bb..708b15043 100644 --- a/pkg/repo/chartrepo.go +++ b/pkg/repo/chartrepo.go @@ -25,6 +25,7 @@ import ( "strings" "github.com/ghodss/yaml" + "github.com/pkg/errors" "k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/getter" @@ -55,16 +56,16 @@ type ChartRepository struct { func NewChartRepository(cfg *Entry, getters getter.Providers) (*ChartRepository, error) { u, err := url.Parse(cfg.URL) if err != nil { - return nil, fmt.Errorf("invalid chart URL format: %s", cfg.URL) + return nil, errors.Errorf("invalid chart URL format: %s", cfg.URL) } getterConstructor, err := getters.ByScheme(u.Scheme) if err != nil { - return nil, fmt.Errorf("Could not find protocol handler for: %s", u.Scheme) + return nil, errors.Errorf("could not find protocol handler for: %s", u.Scheme) } client, err := getterConstructor(cfg.URL, cfg.CertFile, cfg.KeyFile, cfg.CAFile) if err != nil { - return nil, fmt.Errorf("Could not construct protocol handler for: %s error: %v", u.Scheme, err) + return nil, errors.Wrapf(err, "could not construct protocol handler for: %s", u.Scheme) } return &ChartRepository{ @@ -83,7 +84,7 @@ func (r *ChartRepository) Load() error { return err } if !dirInfo.IsDir() { - return fmt.Errorf("%q is not a directory", r.Config.Name) + return errors.Errorf("%q is not a directory", r.Config.Name) } // FIXME: Why are we recursively walking directories? @@ -204,7 +205,7 @@ func FindChartInAuthRepoURL(repoURL, username, password, chartName, chartVersion // Download and write the index file to a temporary location tempIndexFile, err := ioutil.TempFile("", "tmp-repo-file") if err != nil { - return "", fmt.Errorf("cannot write index file for repository requested") + return "", errors.Errorf("cannot write index file for repository requested") } defer os.Remove(tempIndexFile.Name()) @@ -221,7 +222,7 @@ func FindChartInAuthRepoURL(repoURL, username, password, chartName, chartVersion return "", err } if err := r.DownloadIndexFile(tempIndexFile.Name()); err != nil { - return "", fmt.Errorf("Looks like %q is not a valid chart repository or cannot be reached: %s", repoURL, err) + return "", errors.Wrapf(err, "looks like %q is not a valid chart repository or cannot be reached", repoURL) } // Read the index file for the repository to get chart information and return chart URL @@ -236,18 +237,18 @@ func FindChartInAuthRepoURL(repoURL, username, password, chartName, chartVersion } cv, err := repoIndex.Get(chartName, chartVersion) if err != nil { - return "", fmt.Errorf("%s not found in %s repository", errMsg, repoURL) + return "", errors.Errorf("%s not found in %s repository", errMsg, repoURL) } if len(cv.URLs) == 0 { - return "", fmt.Errorf("%s has no downloadable URLs", errMsg) + return "", errors.Errorf("%s has no downloadable URLs", errMsg) } chartURL := cv.URLs[0] absoluteChartURL, err := ResolveReferenceURL(repoURL, chartURL) if err != nil { - return "", fmt.Errorf("failed to make chart URL absolute: %v", err) + return "", errors.Wrap(err, "failed to make chart URL absolute") } return absoluteChartURL, nil @@ -258,12 +259,12 @@ func FindChartInAuthRepoURL(repoURL, username, password, chartName, chartVersion func ResolveReferenceURL(baseURL, refURL string) (string, error) { parsedBaseURL, err := url.Parse(baseURL) if err != nil { - return "", fmt.Errorf("failed to parse %s as URL: %v", baseURL, err) + return "", errors.Wrapf(err, "failed to parse %s as URL", baseURL) } parsedRefURL, err := url.Parse(refURL) if err != nil { - return "", fmt.Errorf("failed to parse %s as URL: %v", refURL, err) + return "", errors.Wrapf(err, "failed to parse %s as URL", refURL) } return parsedBaseURL.ResolveReference(parsedRefURL).String(), nil diff --git a/pkg/repo/chartrepo_test.go b/pkg/repo/chartrepo_test.go index ab2f174b0..b1c066ced 100644 --- a/pkg/repo/chartrepo_test.go +++ b/pkg/repo/chartrepo_test.go @@ -243,7 +243,7 @@ func TestErrorFindChartInRepoURL(t *testing.T) { if err == nil { t.Errorf("Expected error for bad chart URL, but did not get any errors") } - if err != nil && !strings.Contains(err.Error(), `Looks like "http://someserver/something" is not a valid chart repository or cannot be reached: Get http://someserver/something/index.yaml`) { + if err != nil && !strings.Contains(err.Error(), `looks like "http://someserver/something" is not a valid chart repository or cannot be reached: Get http://someserver/something/index.yaml`) { t.Errorf("Expected error for bad chart URL, but got a different error (%v)", err) } diff --git a/pkg/repo/index.go b/pkg/repo/index.go index 2b1993a23..9cd6159fc 100644 --- a/pkg/repo/index.go +++ b/pkg/repo/index.go @@ -18,7 +18,6 @@ package repo import ( "encoding/json" - "errors" "fmt" "io/ioutil" "os" @@ -29,6 +28,7 @@ import ( "github.com/Masterminds/semver" "github.com/ghodss/yaml" + "github.com/pkg/errors" "k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/hapi/chart" @@ -177,7 +177,7 @@ func (i IndexFile) Get(name, version string) (*ChartVersion, error) { return ver, nil } } - return nil, fmt.Errorf("No chart version found for %s-%s", name, version) + return nil, errors.Errorf("no chart version found for %s-%s", name, version) } // WriteFile writes an index file to the given destination path. diff --git a/pkg/repo/repo.go b/pkg/repo/repo.go index b5bba164e..7c24fcba5 100644 --- a/pkg/repo/repo.go +++ b/pkg/repo/repo.go @@ -17,13 +17,13 @@ limitations under the License. package repo // import "k8s.io/helm/pkg/repo" import ( - "errors" "fmt" "io/ioutil" "os" "time" "github.com/ghodss/yaml" + "github.com/pkg/errors" ) // ErrRepoOutOfDate indicates that the repository file is out of date, but @@ -57,8 +57,8 @@ func LoadRepositoriesFile(path string) (*RepoFile, error) { b, err := ioutil.ReadFile(path) if err != nil { if os.IsNotExist(err) { - return nil, fmt.Errorf( - "Couldn't load repositories file (%s).\n"+ + return nil, errors.Errorf( + "couldn't load repositories file (%s).\n"+ "You might need to run `helm init` (or "+ "`helm init --client-only` if tiller is "+ "already installed)", path) diff --git a/pkg/resolver/resolver.go b/pkg/resolver/resolver.go index ec8ea2cce..2d2fba018 100644 --- a/pkg/resolver/resolver.go +++ b/pkg/resolver/resolver.go @@ -18,13 +18,13 @@ package resolver import ( "bytes" "encoding/json" - "fmt" "os" "path/filepath" "strings" "time" "github.com/Masterminds/semver" + "github.com/pkg/errors" "k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/helm/helmpath" @@ -68,17 +68,17 @@ func (r *Resolver) Resolve(reqs *chartutil.Requirements, repoNames map[string]st } constraint, err := semver.NewConstraint(d.Version) if err != nil { - return nil, fmt.Errorf("dependency %q has an invalid version/constraint format: %s", d.Name, err) + return nil, errors.Wrapf(err, "dependency %q has an invalid version/constraint format", d.Name) } repoIndex, err := repo.LoadIndexFile(r.helmhome.CacheIndex(repoNames[d.Name])) if err != nil { - return nil, fmt.Errorf("no cached repo found. (try 'helm repo update'). %s", err) + return nil, errors.Wrap(err, "no cached repo found. (try 'helm repo update')") } vs, ok := repoIndex.Entries[d.Name] if !ok { - return nil, fmt.Errorf("%s chart not found in repo %s", d.Name, d.Repository) + return nil, errors.Errorf("%s chart not found in repo %s", d.Name, d.Repository) } locked[i] = &chartutil.Dependency{ @@ -105,7 +105,7 @@ func (r *Resolver) Resolve(reqs *chartutil.Requirements, repoNames map[string]st } } if len(missing) > 0 { - return nil, fmt.Errorf("Can't get a valid version for repositories %s. Try changing the version constraint in requirements.yaml", strings.Join(missing, ", ")) + return nil, errors.Errorf("can't get a valid version for repositories %s. Try changing the version constraint in requirements.yaml", strings.Join(missing, ", ")) } return &chartutil.RequirementsLock{ Generated: time.Now(), @@ -129,7 +129,7 @@ func HashReq(req *chartutil.Requirements) (string, error) { // GetLocalPath generates absolute local path when use // "file://" in repository of requirements -func GetLocalPath(repo string, chartpath string) (string, error) { +func GetLocalPath(repo, chartpath string) (string, error) { var depPath string var err error p := strings.TrimPrefix(repo, "file://") @@ -144,7 +144,7 @@ func GetLocalPath(repo string, chartpath string) (string, error) { } if _, err = os.Stat(depPath); os.IsNotExist(err) { - return "", fmt.Errorf("directory %s not found", depPath) + return "", errors.Errorf("directory %s not found", depPath) } else if err != nil { return "", err } diff --git a/pkg/storage/driver/cfgmaps.go b/pkg/storage/driver/cfgmaps.go index a84057610..b083e5fd7 100644 --- a/pkg/storage/driver/cfgmaps.go +++ b/pkg/storage/driver/cfgmaps.go @@ -17,11 +17,12 @@ limitations under the License. package driver // import "k8s.io/helm/pkg/storage/driver" import ( - "fmt" "strconv" "strings" "time" + "github.com/pkg/errors" + "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -117,7 +118,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, fmt.Errorf("invalid label value: %q: %s", v, strings.Join(errs, "; ")) + return nil, errors.Errorf("invalid label value: %q: %s", v, strings.Join(errs, "; ")) } ls[k] = v } diff --git a/pkg/storage/driver/driver.go b/pkg/storage/driver/driver.go index 2c74ebba7..7dfae6c96 100644 --- a/pkg/storage/driver/driver.go +++ b/pkg/storage/driver/driver.go @@ -17,18 +17,18 @@ limitations under the License. package driver // import "k8s.io/helm/pkg/storage/driver" import ( - "fmt" + "github.com/pkg/errors" rspb "k8s.io/helm/pkg/hapi/release" ) var ( // ErrReleaseNotFound indicates that a release is not found. - ErrReleaseNotFound = func(release string) error { return fmt.Errorf("release: %q not found", release) } + ErrReleaseNotFound = func(release string) error { return errors.Errorf("release: %q not found", release) } // ErrReleaseExists indicates that a release already exists. - ErrReleaseExists = func(release string) error { return fmt.Errorf("release: %q already exists", release) } + ErrReleaseExists = func(release string) error { return errors.Errorf("release: %q already exists", release) } // ErrInvalidKey indicates that a release key could not be parsed. - ErrInvalidKey = func(release string) error { return fmt.Errorf("release: %q invalid key", release) } + ErrInvalidKey = func(release string) error { return errors.Errorf("release: %q invalid key", release) } ) // Creator is the interface that wraps the Create method. diff --git a/pkg/storage/driver/secrets.go b/pkg/storage/driver/secrets.go index 72f6ef45e..f0dd4dd1d 100644 --- a/pkg/storage/driver/secrets.go +++ b/pkg/storage/driver/secrets.go @@ -17,11 +17,12 @@ limitations under the License. package driver // import "k8s.io/helm/pkg/storage/driver" import ( - "fmt" "strconv" "strings" "time" + "github.com/pkg/errors" + "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -67,18 +68,11 @@ func (secrets *Secrets) Get(key string) (*rspb.Release, error) { if apierrors.IsNotFound(err) { return nil, ErrReleaseNotFound(key) } - - secrets.Log("get: failed to get %q: %s", key, err) - return nil, err + return nil, errors.Wrapf(err, "get: failed to get %q", key) } // found the secret, decode the base64 data string r, err := decodeRelease(string(obj.Data["release"])) - if err != nil { - secrets.Log("get: failed to decode data %q: %s", key, err) - return nil, err - } - // return the release object - return r, nil + return r, errors.Wrapf(err, "get: failed to decode data %q", key) } // List fetches all releases and returns the list releases such @@ -90,8 +84,7 @@ func (secrets *Secrets) List(filter func(*rspb.Release) bool) ([]*rspb.Release, list, err := secrets.impl.List(opts) if err != nil { - secrets.Log("list: failed to list: %s", err) - return nil, err + return nil, errors.Wrap(err, "list: failed to list") } var results []*rspb.Release @@ -117,7 +110,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, fmt.Errorf("invalid label value: %q: %s", v, strings.Join(errs, "; ")) + return nil, errors.Errorf("invalid label value: %q: %s", v, strings.Join(errs, "; ")) } ls[k] = v } @@ -126,8 +119,7 @@ func (secrets *Secrets) Query(labels map[string]string) ([]*rspb.Release, error) list, err := secrets.impl.List(opts) if err != nil { - secrets.Log("query: failed to query with labels: %s", err) - return nil, err + return nil, errors.Wrap(err, "query: failed to query with labels") } if len(list.Items) == 0 { @@ -158,8 +150,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 { - secrets.Log("create: failed to encode release %q: %s", rls.Name, err) - return err + return errors.Wrapf(err, "create: failed to encode release %q", rls.Name) } // push the secret object out into the kubiverse if _, err := secrets.impl.Create(obj); err != nil { @@ -167,8 +158,7 @@ func (secrets *Secrets) Create(key string, rls *rspb.Release) error { return ErrReleaseExists(rls.Name) } - secrets.Log("create: failed to create: %s", err) - return err + return errors.Wrap(err, "create: failed to create") } return nil } @@ -185,16 +175,11 @@ func (secrets *Secrets) Update(key string, rls *rspb.Release) error { // create a new secret object to hold the release obj, err := newSecretsObject(key, rls, lbs) if err != nil { - secrets.Log("update: failed to encode release %q: %s", rls.Name, err) - return err + return errors.Wrapf(err, "update: failed to encode release %q", rls.Name) } // push the secret object out into the kubiverse _, err = secrets.impl.Update(obj) - if err != nil { - secrets.Log("update: failed to update: %s", err) - return err - } - return nil + return errors.Wrap(err, "update: failed to update") } // Delete deletes the Secret holding the release named by key. @@ -205,14 +190,11 @@ func (secrets *Secrets) Delete(key string) (rls *rspb.Release, err error) { return nil, ErrReleaseExists(rls.Name) } - secrets.Log("delete: failed to get release %q: %s", key, err) - return nil, err + return nil, errors.Wrapf(err, "delete: failed to get release %q", key) } // delete the release - if err = secrets.impl.Delete(key, &metav1.DeleteOptions{}); err != nil { - return rls, err - } - return rls, nil + err = secrets.impl.Delete(key, &metav1.DeleteOptions{}) + return rls, err } // newSecretsObject constructs a kubernetes Secret object diff --git a/pkg/storage/storage.go b/pkg/storage/storage.go index 5c4629e2c..94969cec9 100644 --- a/pkg/storage/storage.go +++ b/pkg/storage/storage.go @@ -20,6 +20,8 @@ import ( "fmt" "strings" + "github.com/pkg/errors" + rspb "k8s.io/helm/pkg/hapi/release" relutil "k8s.io/helm/pkg/releaseutil" "k8s.io/helm/pkg/storage/driver" @@ -124,13 +126,13 @@ func (s *Storage) Deployed(name string) (*rspb.Release, error) { ls, err := s.DeployedAll(name) if err != nil { if strings.Contains(err.Error(), "not found") { - return nil, fmt.Errorf("%q has no deployed releases", name) + return nil, errors.Errorf("%q has no deployed releases", name) } return nil, err } if len(ls) == 0 { - return nil, fmt.Errorf("%q has no deployed releases", name) + return nil, errors.Errorf("%q has no deployed releases", name) } return ls[0], err @@ -150,7 +152,7 @@ func (s *Storage) DeployedAll(name string) ([]*rspb.Release, error) { return ls, nil } if strings.Contains(err.Error(), "not found") { - return nil, fmt.Errorf("%q has no deployed releases", name) + return nil, errors.Errorf("%q has no deployed releases", name) } return nil, err } @@ -187,24 +189,24 @@ func (s *Storage) removeLeastRecent(name string, max int) error { // Delete as many as possible. In the case of API throughput limitations, // multiple invocations of this function will eventually delete them all. toDelete := h[0:overage] - errors := []error{} + errs := []error{} for _, rel := range toDelete { key := makeKey(name, rel.Version) _, innerErr := s.Delete(name, rel.Version) if innerErr != nil { s.Log("error pruning %s from release history: %s", key, innerErr) - errors = append(errors, innerErr) + errs = append(errs, innerErr) } } - s.Log("Pruned %d record(s) from %s with %d error(s)", len(toDelete), name, len(errors)) - switch c := len(errors); c { + s.Log("Pruned %d record(s) from %s with %d error(s)", len(toDelete), name, len(errs)) + switch c := len(errs); c { case 0: return nil case 1: - return errors[0] + return errs[0] default: - return fmt.Errorf("encountered %d deletion errors. First is: %s", c, errors[0]) + return errors.Errorf("encountered %d deletion errors. First is: %s", c, errs[0]) } } @@ -216,7 +218,7 @@ func (s *Storage) Last(name string) (*rspb.Release, error) { return nil, err } if len(h) == 0 { - return nil, fmt.Errorf("no revision for release %q", name) + return nil, errors.Errorf("no revision for release %q", name) } relutil.Reverse(h, relutil.SortByRevision) diff --git a/pkg/strvals/parser.go b/pkg/strvals/parser.go index aa3d15904..40c001942 100644 --- a/pkg/strvals/parser.go +++ b/pkg/strvals/parser.go @@ -17,13 +17,12 @@ package strvals import ( "bytes" - "errors" - "fmt" "io" "strconv" "strings" "github.com/ghodss/yaml" + "github.com/pkg/errors" ) // ErrNotList indicates that a non-list was treated as a list. @@ -121,14 +120,14 @@ func (t *parser) key(data map[string]interface{}) error { if len(k) == 0 { return err } - return fmt.Errorf("key %q has no value", string(k)) + return errors.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 fmt.Errorf("error parsing index: %s", err) + return errors.Wrap(err, "error parsing index") } kk := string(k) // Find or create target list @@ -163,7 +162,7 @@ func (t *parser) key(data map[string]interface{}) error { case last == ',': // No value given. Set the value to empty string. Return error. set(data, string(k), "") - return fmt.Errorf("key %q has no value (cannot end with ,)", string(k)) + return errors.Errorf("key %q has no value (cannot end with ,)", string(k)) case last == '.': // First, create or find the target map. inner := map[string]interface{}{} @@ -174,7 +173,7 @@ func (t *parser) key(data map[string]interface{}) error { // Recurse e := t.key(inner) if len(inner) == 0 { - return fmt.Errorf("key map %q has no value", string(k)) + return errors.Errorf("key map %q has no value", string(k)) } set(data, string(k), inner) return e @@ -215,7 +214,7 @@ func (t *parser) listItem(list []interface{}, i int) ([]interface{}, error) { stop := runeSet([]rune{'[', '.', '='}) switch k, last, err := runesUntil(t.sc, stop); { case len(k) > 0: - return list, fmt.Errorf("unexpected data at end of array index: %q", k) + return list, errors.Errorf("unexpected data at end of array index: %q", k) case err != nil: return list, err case last == '=': @@ -235,7 +234,7 @@ func (t *parser) listItem(list []interface{}, i int) ([]interface{}, error) { // now we have a nested list. Read the index and handle. i, err := t.keyIndex() if err != nil { - return list, fmt.Errorf("error parsing index: %s", err) + return list, errors.Wrap(err, "error parsing index") } // Now we need to get the value after the ]. list2, err := t.listItem(list, i) @@ -251,7 +250,7 @@ func (t *parser) listItem(list []interface{}, i int) ([]interface{}, error) { e := t.key(inner) return setIndex(list, i, inner), e default: - return nil, fmt.Errorf("parse error: unexpected token %v", last) + return nil, errors.Errorf("parse error: unexpected token %v", last) } } diff --git a/pkg/sympath/walk.go b/pkg/sympath/walk.go index 77fa04153..b50756a63 100644 --- a/pkg/sympath/walk.go +++ b/pkg/sympath/walk.go @@ -21,10 +21,11 @@ limitations under the License. package sympath import ( - "fmt" "os" "path/filepath" "sort" + + "github.com/pkg/errors" ) // Walk walks the file tree rooted at root, calling walkFn for each file or directory @@ -67,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 fmt.Errorf("error evaluating symlink %s: %s", path, err) + return errors.Wrapf(err, "error evaluating symlink %s", path) } if info, err = os.Lstat(resolved); err != nil { return err diff --git a/pkg/tiller/environment/environment.go b/pkg/tiller/environment/environment.go index 653d458ec..052120ff9 100644 --- a/pkg/tiller/environment/environment.go +++ b/pkg/tiller/environment/environment.go @@ -173,7 +173,7 @@ func (p *PrintingKubeClient) WatchUntilReady(ns string, r io.Reader, timeout int } // Update implements KubeClient Update. -func (p *PrintingKubeClient) Update(ns string, currentReader, modifiedReader io.Reader, force bool, recreate bool, timeout int64, shouldWait bool) error { +func (p *PrintingKubeClient) Update(ns string, currentReader, modifiedReader io.Reader, force, recreate bool, timeout int64, shouldWait bool) error { _, err := io.Copy(p.Out, modifiedReader) return err } diff --git a/pkg/tiller/environment/environment_test.go b/pkg/tiller/environment/environment_test.go index 72d4a2a96..1f06b1f28 100644 --- a/pkg/tiller/environment/environment_test.go +++ b/pkg/tiller/environment/environment_test.go @@ -49,7 +49,7 @@ func (k *mockKubeClient) Get(ns string, r io.Reader) (string, error) { func (k *mockKubeClient) Delete(ns string, r io.Reader) error { return nil } -func (k *mockKubeClient) Update(ns string, currentReader, modifiedReader io.Reader, force bool, recreate bool, timeout int64, shouldWait bool) error { +func (k *mockKubeClient) Update(ns string, currentReader, modifiedReader io.Reader, force, recreate bool, timeout int64, shouldWait bool) error { return nil } func (k *mockKubeClient) WatchUntilReady(ns string, r io.Reader, timeout int64, shouldWait bool) error { diff --git a/pkg/tiller/hooks.go b/pkg/tiller/hooks.go index 361ac3bf2..29c311509 100644 --- a/pkg/tiller/hooks.go +++ b/pkg/tiller/hooks.go @@ -17,13 +17,13 @@ limitations under the License. package tiller import ( - "fmt" "log" "path" "strconv" "strings" "github.com/ghodss/yaml" + "github.com/pkg/errors" "k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/hapi/release" @@ -130,15 +130,12 @@ func sortManifests(files map[string]string, apis chartutil.VersionSet, sort Sort func (file *manifestFile) sort(result *result) error { for _, m := range file.entries { var entry util.SimpleHead - err := yaml.Unmarshal([]byte(m), &entry) - - if err != nil { - e := fmt.Errorf("YAML parse error on %s: %s", file.path, err) - return e + if err := yaml.Unmarshal([]byte(m), &entry); err != nil { + return errors.Wrapf(err, "YAML parse error on %s", file.path) } if entry.Version != "" && !file.apis.Has(entry.Version) { - return fmt.Errorf("apiVersion %q in %s is not available", entry.Version, file.path) + return errors.Errorf("apiVersion %q in %s is not available", entry.Version, file.path) } if !hasAnyAnnotation(entry) { diff --git a/pkg/tiller/release_content.go b/pkg/tiller/release_content.go index 899c3a79b..0ec04df68 100644 --- a/pkg/tiller/release_content.go +++ b/pkg/tiller/release_content.go @@ -17,6 +17,8 @@ limitations under the License. package tiller import ( + "github.com/pkg/errors" + "k8s.io/helm/pkg/hapi" "k8s.io/helm/pkg/hapi/release" ) @@ -24,8 +26,7 @@ import ( // GetReleaseContent gets all of the stored information for the given release. func (s *ReleaseServer) GetReleaseContent(req *hapi.GetReleaseContentRequest) (*release.Release, error) { if err := validateReleaseName(req.Name); err != nil { - s.Log("releaseContent: Release name is invalid: %s", req.Name) - return nil, err + return nil, errors.Errorf("releaseContent: Release name is invalid: %s", req.Name) } if req.Version <= 0 { diff --git a/pkg/tiller/release_history.go b/pkg/tiller/release_history.go index d4e560232..fc9889a8a 100644 --- a/pkg/tiller/release_history.go +++ b/pkg/tiller/release_history.go @@ -17,6 +17,8 @@ limitations under the License. package tiller import ( + "github.com/pkg/errors" + "k8s.io/helm/pkg/hapi" "k8s.io/helm/pkg/hapi/release" relutil "k8s.io/helm/pkg/releaseutil" @@ -25,8 +27,7 @@ import ( // GetHistory gets the history for a given release. func (s *ReleaseServer) GetHistory(req *hapi.GetHistoryRequest) ([]*release.Release, error) { if err := validateReleaseName(req.Name); err != nil { - s.Log("getHistory: Release name is invalid: %s", req.Name) - return nil, err + return nil, errors.Errorf("getHistory: Release name is invalid: %s", req.Name) } s.Log("getting history for release %s", req.Name) diff --git a/pkg/tiller/release_install.go b/pkg/tiller/release_install.go index d7497c623..1c8ba8a35 100644 --- a/pkg/tiller/release_install.go +++ b/pkg/tiller/release_install.go @@ -22,6 +22,8 @@ import ( "strings" "time" + "github.com/pkg/errors" + "k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/hapi" "k8s.io/helm/pkg/hapi/release" @@ -34,22 +36,17 @@ func (s *ReleaseServer) InstallRelease(req *hapi.InstallReleaseRequest) (*releas s.Log("preparing install for %s", req.Name) rel, err := s.prepareRelease(req) if err != nil { - s.Log("failed install prepare step: %s", err) - // On dry run, append the manifest contents to a failed release. This is // a stop-gap until we can revisit an error backchannel post-2.0. if req.DryRun && strings.HasPrefix(err.Error(), "YAML parse error") { - err = fmt.Errorf("%s\n%s", err, rel.Manifest) + err = errors.Wrap(err, rel.Manifest) } - return rel, err + return rel, errors.Wrap(err, "failed install prepare step") } s.Log("performing install for %s", req.Name) res, err := s.performRelease(rel, req) - if err != nil { - s.Log("failed install perform step: %s", err) - } - return res, err + return res, errors.Wrap(err, "failed install perform step") } // prepareRelease builds a release for an install operation. @@ -192,7 +189,7 @@ func (s *ReleaseServer) performRelease(r *release.Release, req *hapi.InstallRele r.Info.Status = release.StatusFailed r.Info.Description = msg s.recordRelease(r, true) - return r, fmt.Errorf("release %s failed: %s", r.Name, err) + return r, errors.Wrapf(err, "release %s failed", r.Name) } } diff --git a/pkg/tiller/release_install_test.go b/pkg/tiller/release_install_test.go index 4a52e88fa..3f067ac47 100644 --- a/pkg/tiller/release_install_test.go +++ b/pkg/tiller/release_install_test.go @@ -364,7 +364,7 @@ func TestInstallRelease_WrongKubeVersion(t *testing.T) { t.Fatalf("Expected to fail because of wrong version") } - expect := "Chart requires kubernetesVersion" + expect := "chart requires kubernetesVersion" if !strings.Contains(err.Error(), expect) { t.Errorf("Expected %q to contain %q", err.Error(), expect) } diff --git a/pkg/tiller/release_rollback.go b/pkg/tiller/release_rollback.go index 92184ad30..a2dab07c1 100644 --- a/pkg/tiller/release_rollback.go +++ b/pkg/tiller/release_rollback.go @@ -21,6 +21,8 @@ import ( "fmt" "time" + "github.com/pkg/errors" + "k8s.io/helm/pkg/hapi" "k8s.io/helm/pkg/hapi/release" "k8s.io/helm/pkg/hooks" @@ -60,8 +62,7 @@ func (s *ReleaseServer) RollbackRelease(req *hapi.RollbackReleaseRequest) (*rele // the previous release's configuration func (s *ReleaseServer) prepareRollback(req *hapi.RollbackReleaseRequest) (*release.Release, *release.Release, error) { if err := validateReleaseName(req.Name); err != nil { - s.Log("prepareRollback: Release name is invalid: %s", req.Name) - return nil, nil, err + return nil, nil, errors.Errorf("prepareRollback: Release name is invalid: %s", req.Name) } if req.Version < 0 { diff --git a/pkg/tiller/release_server.go b/pkg/tiller/release_server.go index 0cb644e48..8810be0c8 100644 --- a/pkg/tiller/release_server.go +++ b/pkg/tiller/release_server.go @@ -18,13 +18,12 @@ package tiller import ( "bytes" - "errors" - "fmt" "path" "regexp" "strings" "time" + "github.com/pkg/errors" "github.com/technosophos/moniker" "gopkg.in/yaml.v2" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -123,9 +122,7 @@ func (s *ReleaseServer) reuseValues(req *hapi.UpdateReleaseRequest, current *rel // We have to regenerate the old coalesced values: oldVals, err := chartutil.CoalesceValues(current.Chart, current.Config) if err != nil { - err := fmt.Errorf("failed to rebuild old values: %s", err) - s.Log("%s", err) - return err + return errors.Wrap(err, "failed to rebuild old values") } nv, err := yaml.Marshal(oldVals) if err != nil { @@ -170,7 +167,7 @@ func (s *ReleaseServer) uniqName(start string, reuse bool) (string, error) { if start != "" { if len(start) > releaseNameMaxLen { - return "", fmt.Errorf("release name %q exceeds max length of %d", start, releaseNameMaxLen) + return "", errors.Errorf("release name %q exceeds max length of %d", start, releaseNameMaxLen) } h, err := s.Releases.History(start) @@ -188,7 +185,7 @@ func (s *ReleaseServer) uniqName(start string, reuse bool) (string, error) { return "", errors.New("cannot re-use a name that is still in use") } - return "", fmt.Errorf("a release named %s already exists.\nRun: helm ls --all %s; to check the status of the release\nOr run: helm del --purge %s; to delete it", start, start, start) + return "", errors.Errorf("a release named %s already exists.\nRun: helm ls --all %s; to check the status of the release\nOr run: helm del --purge %s; to delete it", start, start, start) } maxTries := 5 @@ -227,7 +224,7 @@ func capabilities(disc discovery.DiscoveryInterface) (*chartutil.Capabilities, e } vs, err := GetVersionSet(disc) if err != nil { - return nil, fmt.Errorf("Could not get apiVersions from Kubernetes: %s", err) + return nil, errors.Wrap(err, "could not get apiVersions from Kubernetes") } return &chartutil.Capabilities{ APIVersions: vs, @@ -260,7 +257,7 @@ func (s *ReleaseServer) renderResources(ch *chart.Chart, values chartutil.Values sver := version.GetVersion() if ch.Metadata.HelmVersion != "" && !version.IsCompatibleRange(ch.Metadata.HelmVersion, sver) { - return nil, nil, "", fmt.Errorf("Chart incompatible with Tiller %s", sver) + return nil, nil, "", errors.Errorf("chart incompatible with Tiller %s", sver) } if ch.Metadata.KubeVersion != "" { @@ -268,7 +265,7 @@ func (s *ReleaseServer) renderResources(ch *chart.Chart, values chartutil.Values gitVersion := cap.KubeVersion.String() k8sVersion := strings.Split(gitVersion, "+")[0] if !version.IsCompatibleRange(ch.Metadata.KubeVersion, k8sVersion) { - return nil, nil, "", fmt.Errorf("Chart requires kubernetesVersion: %s which is incompatible with Kubernetes %s", ch.Metadata.KubeVersion, k8sVersion) + return nil, nil, "", errors.Errorf("chart requires kubernetesVersion: %s which is incompatible with Kubernetes %s", ch.Metadata.KubeVersion, k8sVersion) } } @@ -341,7 +338,7 @@ func (s *ReleaseServer) recordRelease(r *release.Release, reuse bool) { func (s *ReleaseServer) execHook(hs []*release.Hook, name, namespace, hook string, timeout int64) error { code, ok := events[hook] if !ok { - return fmt.Errorf("unknown hook %s", hook) + return errors.Errorf("unknown hook %s", hook) } s.Log("executing %d %s hooks for %s", len(hs), hook, name) @@ -363,8 +360,7 @@ func (s *ReleaseServer) execHook(hs []*release.Hook, name, namespace, hook strin b := bytes.NewBufferString(h.Manifest) if err := s.KubeClient.Create(namespace, b, timeout, false); err != nil { - s.Log("warning: Release %s %s %s failed: %s", name, hook, h.Path, err) - return err + return errors.Wrapf(err, "warning: Release %s %s %s failed", name, hook, h.Path) } // No way to rewind a bytes.Buffer()? b.Reset() @@ -412,7 +408,7 @@ func validateReleaseName(releaseName string) error { return nil } -func (s *ReleaseServer) deleteHookIfShouldBeDeletedByDeletePolicy(h *release.Hook, policy string, name, namespace, hook string, kubeCli environment.KubeClient) error { +func (s *ReleaseServer) deleteHookIfShouldBeDeletedByDeletePolicy(h *release.Hook, policy, name, namespace, hook string, kubeCli environment.KubeClient) error { b := bytes.NewBufferString(h.Manifest) if hookHasDeletePolicy(h, policy) { s.Log("deleting %s hook %s for release %s due to %q policy", hook, h.Name, name, policy) diff --git a/pkg/tiller/release_server_test.go b/pkg/tiller/release_server_test.go index fe30d8c70..de2d63931 100644 --- a/pkg/tiller/release_server_test.go +++ b/pkg/tiller/release_server_test.go @@ -17,7 +17,6 @@ limitations under the License. package tiller import ( - "errors" "flag" "fmt" "io" @@ -28,6 +27,7 @@ import ( "time" "github.com/ghodss/yaml" + "github.com/pkg/errors" "k8s.io/client-go/kubernetes/fake" "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/kubectl/resource" @@ -396,7 +396,7 @@ type updateFailingKubeClient struct { environment.PrintingKubeClient } -func (u *updateFailingKubeClient) Update(namespace string, originalReader, modifiedReader io.Reader, force bool, recreate bool, timeout int64, shouldWait bool) error { +func (u *updateFailingKubeClient) Update(namespace string, originalReader, modifiedReader io.Reader, force, recreate bool, timeout int64, shouldWait bool) error { return errors.New("Failed update in kube client") } @@ -474,16 +474,16 @@ func (kc *mockHooksKubeClient) WatchUntilReady(ns string, r io.Reader, timeout i manifest, hasManifest := kc.Resources[paramManifest.Metadata.Name] if !hasManifest { - return fmt.Errorf("mockHooksKubeClient.WatchUntilReady: no such resource %s found", paramManifest.Metadata.Name) + return errors.Errorf("mockHooksKubeClient.WatchUntilReady: no such resource %s found", paramManifest.Metadata.Name) } if manifest.Metadata.Annotations["mockHooksKubeClient/Emulate"] == "hook-failed" { - return fmt.Errorf("mockHooksKubeClient.WatchUntilReady: hook-failed") + return errors.Errorf("mockHooksKubeClient.WatchUntilReady: hook-failed") } return nil } -func (kc *mockHooksKubeClient) Update(ns string, currentReader, modifiedReader io.Reader, force bool, recreate bool, timeout int64, shouldWait bool) error { +func (kc *mockHooksKubeClient) Update(ns string, currentReader, modifiedReader io.Reader, force, recreate bool, timeout int64, shouldWait bool) error { return nil } func (kc *mockHooksKubeClient) Build(ns string, reader io.Reader) (kube.Result, error) { @@ -533,23 +533,22 @@ name: value`, hookName, extraAnnotationsStr), } } -func execHookShouldSucceed(rs *ReleaseServer, hook *release.Hook, releaseName string, namespace string, hookType string) error { - if err := rs.execHook([]*release.Hook{hook}, releaseName, namespace, hookType, 600); err != nil { - return fmt.Errorf("expected hook %s to be successful: %s", hook.Name, err) - } - return nil +func execHookShouldSucceed(rs *ReleaseServer, hook *release.Hook, releaseName, namespace, hookType string) error { + err := rs.execHook([]*release.Hook{hook}, releaseName, namespace, hookType, 600) + return errors.Wrapf(err, "expected hook %s to be successful", hook.Name) } -func execHookShouldFail(rs *ReleaseServer, hook *release.Hook, releaseName string, namespace string, hookType string) error { +func execHookShouldFail(rs *ReleaseServer, hook *release.Hook, releaseName, namespace, hookType string) error { if err := rs.execHook([]*release.Hook{hook}, releaseName, namespace, hookType, 600); err == nil { - return fmt.Errorf("expected hook %s to be failed", hook.Name) + return errors.Errorf("expected hook %s to be failed", hook.Name) } return nil } -func execHookShouldFailWithError(rs *ReleaseServer, hook *release.Hook, releaseName string, namespace string, hookType string, expectedError error) error { - if err := rs.execHook([]*release.Hook{hook}, releaseName, namespace, hookType, 600); err != expectedError { - return fmt.Errorf("expected hook %s to fail with error %v, got %v", hook.Name, expectedError, err) +func execHookShouldFailWithError(rs *ReleaseServer, hook *release.Hook, releaseName, namespace, hookType string, expectedError error) error { + err := rs.execHook([]*release.Hook{hook}, releaseName, namespace, hookType, 600) + if cause := errors.Cause(err); cause != expectedError { + return errors.Errorf("expected hook %s to fail with error \n%v \ngot \n%v", hook.Name, expectedError, cause) } return nil } diff --git a/pkg/tiller/release_status.go b/pkg/tiller/release_status.go index af34b21af..a2b5b1eca 100644 --- a/pkg/tiller/release_status.go +++ b/pkg/tiller/release_status.go @@ -18,8 +18,8 @@ package tiller import ( "bytes" - "errors" - "fmt" + + "github.com/pkg/errors" "k8s.io/helm/pkg/hapi" "k8s.io/helm/pkg/hapi/release" @@ -28,8 +28,7 @@ import ( // GetReleaseStatus gets the status information for a named release. func (s *ReleaseServer) GetReleaseStatus(req *hapi.GetReleaseStatusRequest) (*hapi.GetReleaseStatusResponse, error) { if err := validateReleaseName(req.Name); err != nil { - s.Log("getStatus: Release name is invalid: %s", req.Name) - return nil, err + return nil, errors.Errorf("getStatus: Release name is invalid: %s", req.Name) } var rel *release.Release @@ -38,12 +37,12 @@ func (s *ReleaseServer) GetReleaseStatus(req *hapi.GetReleaseStatusRequest) (*ha var err error rel, err = s.Releases.Last(req.Name) if err != nil { - return nil, fmt.Errorf("getting deployed release %q: %s", req.Name, err) + return nil, errors.Wrapf(err, "getting deployed release %q", req.Name) } } else { var err error if rel, err = s.Releases.Get(req.Name, req.Version); err != nil { - return nil, fmt.Errorf("getting release '%s' (v%d): %s", req.Name, req.Version, err) + return nil, errors.Wrapf(err, "getting release '%s' (v%d)", req.Name, req.Version) } } @@ -68,8 +67,7 @@ func (s *ReleaseServer) GetReleaseStatus(req *hapi.GetReleaseStatusRequest) (*ha // Skip errors if this is already deleted or failed. return statusResp, nil } else if err != nil { - s.Log("warning: Get for %s failed: %v", rel.Name, err) - return nil, err + return nil, errors.Wrapf(err, "warning: Get for %s failed", rel.Name) } rel.Info.Resources = resp return statusResp, nil diff --git a/pkg/tiller/release_testing.go b/pkg/tiller/release_testing.go index a7f20abaf..9b277f2ba 100644 --- a/pkg/tiller/release_testing.go +++ b/pkg/tiller/release_testing.go @@ -17,6 +17,8 @@ limitations under the License. package tiller import ( + "github.com/pkg/errors" + "k8s.io/helm/pkg/hapi" "k8s.io/helm/pkg/hapi/release" reltesting "k8s.io/helm/pkg/releasetesting" @@ -26,8 +28,7 @@ import ( func (s *ReleaseServer) RunReleaseTest(req *hapi.TestReleaseRequest) (<-chan *hapi.TestReleaseResponse, <-chan error) { errc := make(chan error, 1) if err := validateReleaseName(req.Name); err != nil { - s.Log("releaseTest: Release name is invalid: %s", req.Name) - errc <- err + errc <- errors.Errorf("releaseTest: Release name is invalid: %s", req.Name) return nil, errc } @@ -53,8 +54,7 @@ func (s *ReleaseServer) RunReleaseTest(req *hapi.TestReleaseRequest) (<-chan *ha defer close(ch) if err := tSuite.Run(testEnv); err != nil { - s.Log("error running test suite for %s: %s", rel.Name, err) - errc <- err + errc <- errors.Wrapf(err, "error running test suite for %s", rel.Name) return } diff --git a/pkg/tiller/release_uninstall.go b/pkg/tiller/release_uninstall.go index 0f3366c5b..c3160a2ad 100644 --- a/pkg/tiller/release_uninstall.go +++ b/pkg/tiller/release_uninstall.go @@ -18,11 +18,11 @@ package tiller import ( "bytes" - "errors" - "fmt" "strings" "time" + "github.com/pkg/errors" + "k8s.io/helm/pkg/hapi" "k8s.io/helm/pkg/hapi/release" "k8s.io/helm/pkg/hooks" @@ -33,14 +33,12 @@ import ( // UninstallRelease deletes all of the resources associated with this release, and marks the release DELETED. func (s *ReleaseServer) UninstallRelease(req *hapi.UninstallReleaseRequest) (*hapi.UninstallReleaseResponse, error) { if err := validateReleaseName(req.Name); err != nil { - s.Log("uninstallRelease: Release name is invalid: %s", req.Name) - return nil, err + return nil, errors.Errorf("uninstall: Release name is invalid: %s", req.Name) } rels, err := s.Releases.History(req.Name) if err != nil { - s.Log("uninstall: Release not loaded: %s", req.Name) - return nil, err + return nil, errors.Wrapf(err, "uninstall: Release not loaded: %s", req.Name) } if len(rels) < 1 { return nil, errMissingRelease @@ -54,12 +52,11 @@ func (s *ReleaseServer) UninstallRelease(req *hapi.UninstallReleaseRequest) (*ha if rel.Info.Status == release.StatusDeleted { if req.Purge { if err := s.purgeReleases(rels...); err != nil { - s.Log("uninstall: Failed to purge the release: %s", err) - return nil, err + return nil, errors.Wrap(err, "uninstall: Failed to purge the release") } return &hapi.UninstallReleaseResponse{Release: rel}, nil } - return nil, fmt.Errorf("the release named %q is already deleted", req.Name) + return nil, errors.Errorf("the release named %q is already deleted", req.Name) } s.Log("uninstall: Deleting %s", req.Name) @@ -97,10 +94,7 @@ func (s *ReleaseServer) UninstallRelease(req *hapi.UninstallReleaseRequest) (*ha if req.Purge { s.Log("purge requested for %s", req.Name) err := s.purgeReleases(rels...) - if err != nil { - s.Log("uninstall: Failed to purge the release: %s", err) - } - return res, err + return res, errors.Wrap(err, "uninstall: Failed to purge the release") } if err := s.Releases.Update(rel); err != nil { @@ -108,7 +102,7 @@ func (s *ReleaseServer) UninstallRelease(req *hapi.UninstallReleaseRequest) (*ha } if len(errs) > 0 { - return res, fmt.Errorf("deletion completed with %d error(s): %s", len(errs), joinErrors(errs)) + return res, errors.Errorf("deletion completed with %d error(s): %s", len(errs), joinErrors(errs)) } return res, nil } @@ -134,7 +128,7 @@ func (s *ReleaseServer) purgeReleases(rels ...*release.Release) error { func (s *ReleaseServer) deleteRelease(rel *release.Release) (kept string, errs []error) { vs, err := GetVersionSet(s.discovery) if err != nil { - return rel.Manifest, []error{fmt.Errorf("Could not get apiVersions from Kubernetes: %v", err)} + return rel.Manifest, []error{errors.Wrap(err, "could not get apiVersions from Kubernetes")} } manifests := relutil.SplitManifests(rel.Manifest) @@ -144,7 +138,7 @@ func (s *ReleaseServer) deleteRelease(rel *release.Release) (kept string, errs [ // 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 rel.Manifest, []error{fmt.Errorf("corrupted release record. You must manually delete the resources: %s", err)} + return rel.Manifest, []error{errors.Wrap(err, "corrupted release record. You must manually delete the resources")} } filesToKeep, filesToDelete := filterManifestsToKeep(files) diff --git a/pkg/tiller/release_update.go b/pkg/tiller/release_update.go index b57f2eee7..39abae713 100644 --- a/pkg/tiller/release_update.go +++ b/pkg/tiller/release_update.go @@ -22,6 +22,8 @@ import ( "strings" "time" + "github.com/pkg/errors" + "k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/hapi" "k8s.io/helm/pkg/hapi/release" @@ -31,8 +33,7 @@ import ( // UpdateRelease takes an existing release and new information, and upgrades the release. func (s *ReleaseServer) UpdateRelease(req *hapi.UpdateReleaseRequest) (*release.Release, error) { if err := validateReleaseName(req.Name); err != nil { - s.Log("updateRelease: Release name is invalid: %s", req.Name) - return nil, err + return nil, errors.Errorf("updateRelease: Release name is invalid: %s", req.Name) } s.Log("preparing update for %s", req.Name) currentRelease, updatedRelease, err := s.prepareUpdate(req) @@ -161,13 +162,12 @@ func (s *ReleaseServer) performUpdateForce(req *hapi.UpdateReleaseRequest) (*rel Wait: req.Wait, }) if err != nil { - s.Log("failed update prepare step: %s", err) // On dry run, append the manifest contents to a failed release. This is // a stop-gap until we can revisit an error backchannel post-2.0. if req.DryRun && strings.HasPrefix(err.Error(), "YAML parse error") { - err = fmt.Errorf("%s\n%s", err, newRelease.Manifest) + err = errors.Wrap(err, newRelease.Manifest) } - return newRelease, err + return newRelease, errors.Wrap(err, "failed update prepare step") } // From here on out, the release is considered to be in StatusDeleting or StatusDeleted @@ -194,7 +194,7 @@ func (s *ReleaseServer) performUpdateForce(req *hapi.UpdateReleaseRequest) (*rel s.recordRelease(oldRelease, true) if len(errs) > 0 { - return newRelease, fmt.Errorf("Upgrade --force successfully deleted the previous release, but encountered %d error(s) and cannot continue: %s", len(errs), joinErrors(errs)) + return newRelease, errors.Errorf("upgrade --force successfully deleted the previous release, but encountered %d error(s) and cannot continue: %s", len(errs), joinErrors(errs)) } // post-delete hooks diff --git a/pkg/tlsutil/cfg.go b/pkg/tlsutil/cfg.go index 9ce3109e1..b822b4dc2 100644 --- a/pkg/tlsutil/cfg.go +++ b/pkg/tlsutil/cfg.go @@ -19,8 +19,9 @@ package tlsutil import ( "crypto/tls" "crypto/x509" - "fmt" "os" + + "github.com/pkg/errors" ) // Options represents configurable options used to create client and server TLS configurations. @@ -45,9 +46,9 @@ func ClientConfig(opts Options) (cfg *tls.Config, err error) { if opts.CertFile != "" || opts.KeyFile != "" { if cert, err = CertFromFilePair(opts.CertFile, opts.KeyFile); err != nil { if os.IsNotExist(err) { - return nil, fmt.Errorf("could not load x509 key pair (cert: %q, key: %q): %v", opts.CertFile, opts.KeyFile, err) + return nil, errors.Wrapf(err, "could not load x509 key pair (cert: %q, key: %q)", opts.CertFile, opts.KeyFile) } - return nil, fmt.Errorf("could not read x509 key pair (cert: %q, key: %q): %v", opts.CertFile, opts.KeyFile, err) + return nil, errors.Wrapf(err, "could not read x509 key pair (cert: %q, key: %q)", opts.CertFile, opts.KeyFile) } } if !opts.InsecureSkipVerify && opts.CaCertFile != "" { @@ -67,9 +68,9 @@ func ServerConfig(opts Options) (cfg *tls.Config, err error) { if cert, err = CertFromFilePair(opts.CertFile, opts.KeyFile); err != nil { if os.IsNotExist(err) { - return nil, fmt.Errorf("could not load x509 key pair (cert: %q, key: %q): %v", opts.CertFile, opts.KeyFile, err) + return nil, errors.Wrapf(err, "could not load x509 key pair (cert: %q, key: %q)", opts.CertFile, opts.KeyFile) } - return nil, fmt.Errorf("could not read x509 key pair (cert: %q, key: %q): %v", opts.CertFile, opts.KeyFile, err) + return nil, errors.Wrapf(err, "could not read x509 key pair (cert: %q, key: %q)", opts.CertFile, opts.KeyFile) } if opts.ClientAuth >= tls.VerifyClientCertIfGiven && opts.CaCertFile != "" { if pool, err = CertPoolFromFile(opts.CaCertFile); err != nil { diff --git a/pkg/tlsutil/tls.go b/pkg/tlsutil/tls.go index df698fd4e..bf9befd35 100644 --- a/pkg/tlsutil/tls.go +++ b/pkg/tlsutil/tls.go @@ -19,8 +19,9 @@ package tlsutil import ( "crypto/tls" "crypto/x509" - "fmt" "io/ioutil" + + "github.com/pkg/errors" ) // NewClientTLS returns tls.Config appropriate for client auth. @@ -49,11 +50,11 @@ func NewClientTLS(certFile, keyFile, caFile string) (*tls.Config, error) { func CertPoolFromFile(filename string) (*x509.CertPool, error) { b, err := ioutil.ReadFile(filename) if err != nil { - return nil, fmt.Errorf("can't read CA file: %v", filename) + return nil, errors.Errorf("can't read CA file: %v", filename) } cp := x509.NewCertPool() if !cp.AppendCertsFromPEM(b) { - return nil, fmt.Errorf("failed to append certificates from file: %s", filename) + return nil, errors.Errorf("failed to append certificates from file: %s", filename) } return cp, nil } @@ -65,7 +66,7 @@ func CertPoolFromFile(filename string) (*x509.CertPool, error) { func CertFromFilePair(certFile, keyFile string) (*tls.Certificate, error) { cert, err := tls.LoadX509KeyPair(certFile, keyFile) if err != nil { - return nil, fmt.Errorf("can't load key pair from cert %s and key %s: %s", certFile, keyFile, err) + return nil, errors.Wrapf(err, "can't load key pair from cert %s and key %s", certFile, keyFile) } return &cert, err }