Merge pull request #4032 from adamreese/dev-v3-errors

feat(*): print stacktrace on error with debug enabled
pull/4029/head
Adam Reese 6 years ago committed by GitHub
commit f2c73cb945
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -17,9 +17,9 @@ package main
import ( import (
"bytes" "bytes"
"fmt"
"io" "io"
"github.com/pkg/errors"
"github.com/spf13/cobra" "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 { func runCompletion(out io.Writer, cmd *cobra.Command, args []string) error {
if len(args) == 0 { if len(args) == 0 {
return fmt.Errorf("shell not specified") return errors.New("shell not specified")
} }
if len(args) > 1 { 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]] run, found := completionShells[args[0]]
if !found { if !found {
return fmt.Errorf("unsupported shell type %q", args[0]) return errors.Errorf("unsupported shell type %q", args[0])
} }
return run(out, cmd) return run(out, cmd)

@ -17,11 +17,11 @@ limitations under the License.
package main package main
import ( import (
"errors"
"fmt" "fmt"
"io" "io"
"path/filepath" "path/filepath"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/chartutil"

@ -17,10 +17,10 @@ limitations under the License.
package main package main
import ( import (
"errors"
"fmt" "fmt"
"io" "io"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/pkg/helm" "k8s.io/helm/pkg/helm"

@ -16,10 +16,10 @@ limitations under the License.
package main package main
import ( import (
"fmt"
"io" "io"
"path/filepath" "path/filepath"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"github.com/spf13/cobra/doc" "github.com/spf13/cobra/doc"
) )
@ -74,6 +74,6 @@ func (o *docsOptions) run(out io.Writer) error {
case "bash": case "bash":
return o.topCmd.GenBashCompletionFile(filepath.Join(o.dest, "completions.bash")) return o.topCmd.GenBashCompletionFile(filepath.Join(o.dest, "completions.bash"))
default: 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)
} }
} }

@ -23,6 +23,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/chartutil"
@ -74,7 +75,7 @@ func newFetchCmd(out io.Writer) *cobra.Command {
Long: fetchDesc, Long: fetchDesc,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
if len(args) == 0 { 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 { if o.version == "" && o.devel {
@ -135,7 +136,7 @@ func (o *fetchOptions) run(out io.Writer) error {
var err error var err error
dest, err = ioutil.TempDir("", "helm-") dest, err = ioutil.TempDir("", "helm-")
if err != nil { if err != nil {
return fmt.Errorf("Failed to untar: %s", err) return errors.Wrap(err, "failed to untar")
} }
defer os.RemoveAll(dest) 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 fi, err := os.Stat(ud); err != nil {
if err := os.MkdirAll(ud, 0755); 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() { } 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) return chartutil.ExpandFile(ud, saved)

@ -17,9 +17,9 @@ limitations under the License.
package main package main
import ( import (
"errors"
"io" "io"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/pkg/helm" "k8s.io/helm/pkg/helm"

@ -24,6 +24,7 @@ import (
"strings" "strings"
"sync" "sync"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
// Import to initialize client auth plugins. // Import to initialize client auth plugins.
_ "k8s.io/client-go/plugin/pkg/client/auth" _ "k8s.io/client-go/plugin/pkg/client/auth"
@ -132,6 +133,7 @@ func logf(format string, v ...interface{}) {
func main() { func main() {
cmd := newRootCmd(nil, os.Stdout, os.Args[1:]) cmd := newRootCmd(nil, os.Stdout, os.Args[1:])
if err := cmd.Execute(); err != nil { if err := cmd.Execute(); err != nil {
logf("%+v", err)
os.Exit(1) os.Exit(1)
} }
} }
@ -143,7 +145,7 @@ func checkArgsLength(argsReceived int, requiredArgs ...string) error {
if expectedNum == 1 { if expectedNum == 1 {
arg = "argument" 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 return nil
} }

@ -18,7 +18,6 @@ package main
import ( import (
"bytes" "bytes"
"fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
@ -26,6 +25,7 @@ import (
"testing" "testing"
shellwords "github.com/mattn/go-shellwords" shellwords "github.com/mattn/go-shellwords"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/internal/test" "k8s.io/helm/internal/test"
@ -117,7 +117,7 @@ func ensureTestHome(t *testing.T, home helmpath.Home) error {
home.Starters(), home.Starters(),
} { } {
if err := os.MkdirAll(p, 0755); err != nil { 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)
} }
} }

@ -23,6 +23,7 @@ import (
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"github.com/gosuri/uitable" "github.com/gosuri/uitable"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/pkg/hapi/chart" "k8s.io/helm/pkg/hapi/chart"
@ -114,7 +115,7 @@ func (o *historyOptions) run(out io.Writer) error {
case "table": case "table":
history = formatAsTable(releaseHistory, o.colWidth) history = formatAsTable(releaseHistory, o.colWidth)
default: default:
return fmt.Errorf("unknown output format %q", o.outputFormat) return errors.Errorf("unknown output format %q", o.outputFormat)
} }
if formattingError != nil { if formattingError != nil {

@ -17,11 +17,11 @@ limitations under the License.
package main package main
import ( import (
"errors"
"fmt" "fmt"
"io" "io"
"os" "os"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/pkg/getter" "k8s.io/helm/pkg/getter"
@ -54,7 +54,7 @@ func newInitCmd(out io.Writer) *cobra.Command {
Long: initDesc, Long: initDesc,
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
if len(args) != 0 { 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 o.home = settings.Home
return o.run(out) 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 { if fi, err := os.Stat(p); err != nil {
fmt.Fprintf(out, "Creating %s \n", p) fmt.Fprintf(out, "Creating %s \n", p)
if err := os.MkdirAll(p, 0755); err != nil { 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() { } 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 return err
} }
} else if fi.IsDir() { } 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 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 // In this case, the cacheFile is always absolute. So passing empty string
// is safe. // is safe.
if err := r.DownloadIndexFile(""); err != nil { 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 return &c, nil

@ -18,7 +18,6 @@ package main
import ( import (
"bytes" "bytes"
"errors"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
@ -30,6 +29,7 @@ import (
"github.com/Masterminds/sprig" "github.com/Masterminds/sprig"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/chartutil"
@ -250,7 +250,7 @@ func (o *installOptions) run(out io.Writer) error {
} }
} else if err != chartutil.ErrRequirementsNotFound { } 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( 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 // vals merges values from files specified via -f/--values and
// directly via --set or --set-string, marshaling them to YAML // 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{}{} base := map[string]interface{}{}
// User specified a values files via -f/--values // 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, &currentMap); err != nil { if err := yaml.Unmarshal(bytes, &currentMap); 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 // Merge with the previous map
base = mergeValues(base, currentMap) base = mergeValues(base, currentMap)
@ -344,14 +344,14 @@ func vals(valueFiles valueFiles, values []string, stringValues []string) ([]byte
// User specified a value via --set // User specified a value via --set
for _, value := range values { for _, value := range values {
if err := strvals.ParseInto(value, base); err != nil { 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 // User specified a value via --set-string
for _, value := range stringValues { for _, value := range stringValues {
if err := strvals.ParseIntoString(value, base); err != nil { 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 return abs, nil
} }
if filepath.IsAbs(name) || strings.HasPrefix(name, ".") { 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) 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, 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) { func generateName(nameTemplate string) (string, error) {
@ -479,7 +479,7 @@ func checkDependencies(ch *chart.Chart, reqs *chartutil.Requirements) error {
} }
if len(missing) > 0 { 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 return nil
} }

@ -17,7 +17,6 @@ limitations under the License.
package main package main
import ( import (
"errors"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
@ -26,6 +25,7 @@ import (
"strings" "strings"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/chartutil"
@ -74,7 +74,7 @@ func newLintCmd(out io.Writer) *cobra.Command {
return cmd 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 { func (o *lintOptions) run(out io.Writer) error {
var lowestTolerance int var lowestTolerance int
@ -120,7 +120,7 @@ func (o *lintOptions) run(out io.Writer) error {
msg := fmt.Sprintf("%d chart(s) linted", total) msg := fmt.Sprintf("%d chart(s) linted", total)
if failures > 0 { 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) 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), "-") lastHyphenIndex := strings.LastIndex(filepath.Base(path), "-")
if lastHyphenIndex <= 0 { 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] base := filepath.Base(path)[:lastHyphenIndex]
chartPath = filepath.Join(tempDir, base) chartPath = filepath.Join(tempDir, base)
@ -179,7 +179,7 @@ func (o *lintOptions) vals() ([]byte, error) {
} }
if err := yaml.Unmarshal(bytes, &currentMap); err != nil { if err := yaml.Unmarshal(bytes, &currentMap); 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 // Merge with the previous map
base = mergeValues(base, currentMap) base = mergeValues(base, currentMap)
@ -188,14 +188,14 @@ func (o *lintOptions) vals() ([]byte, error) {
// User specified a value via --set // User specified a value via --set
for _, value := range o.values { for _, value := range o.values {
if err := strvals.ParseInto(value, base); err != nil { 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 // User specified a value via --set-string
for _, value := range o.sValues { for _, value := range o.sValues {
if err := strvals.ParseIntoString(value, base); err != nil { 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")
} }
} }

@ -33,22 +33,18 @@ var (
func TestLintChart(t *testing.T) { func TestLintChart(t *testing.T) {
if _, err := lintChart(chartDirPath, values, namespace, strict); err != nil { 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 { 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 { 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 { 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 { if _, err := lintChart(chartMissingManifest, values, namespace, strict); err == nil {
t.Errorf("Expected a chart parsing error") t.Error("Expected a chart parsing error")
} }
} }

@ -23,6 +23,7 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/pkg/plugin" "k8s.io/helm/pkg/plugin"
@ -87,7 +88,7 @@ func loadPlugins(baseCmd *cobra.Command, out io.Writer) {
if err := prog.Run(); err != nil { if err := prog.Run(); err != nil {
if eerr, ok := err.(*exec.ExitError); ok { if eerr, ok := err.(*exec.ExitError); ok {
os.Stderr.Write(eerr.Stderr) 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 return err
} }

@ -17,7 +17,6 @@ limitations under the License.
package main package main
import ( import (
"errors"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
@ -27,6 +26,7 @@ import (
"github.com/Masterminds/semver" "github.com/Masterminds/semver"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"golang.org/x/crypto/ssh/terminal" "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 { RunE: func(cmd *cobra.Command, args []string) error {
o.home = settings.Home o.home = settings.Home
if len(args) == 0 { 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.sign {
if o.key == "" { if o.key == "" {
@ -166,7 +166,7 @@ func (o *packageOptions) run(out io.Writer) error {
} }
if filepath.Base(path) != ch.Metadata.Name { 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 { if reqs, err := chartutil.LoadRequirements(ch); err == nil {
@ -195,7 +195,7 @@ func (o *packageOptions) run(out io.Writer) error {
if err == nil { if err == nil {
fmt.Fprintf(out, "Successfully packaged chart and saved it to: %s\n", name) fmt.Fprintf(out, "Successfully packaged chart and saved it to: %s\n", name)
} else { } else {
return fmt.Errorf("Failed to save: %s", err) return errors.Wrap(err, "failed to save")
} }
if o.sign { if o.sign {

@ -16,13 +16,13 @@ limitations under the License.
package main package main
import ( import (
"fmt"
"io" "io"
"os" "os"
"os/exec" "os/exec"
"k8s.io/helm/pkg/plugin" "k8s.io/helm/pkg/plugin"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -64,7 +64,7 @@ func runHook(p *plugin.Plugin, event string) error {
if err := prog.Run(); err != nil { if err := prog.Run(); err != nil {
if eerr, ok := err.(*exec.ExitError); ok { if eerr, ok := err.(*exec.ExitError); ok {
os.Stderr.Write(eerr.Stderr) 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 return err
} }

@ -16,16 +16,16 @@ limitations under the License.
package main package main
import ( import (
"errors"
"fmt" "fmt"
"io" "io"
"os" "os"
"strings" "strings"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"k8s.io/helm/pkg/helm/helmpath" "k8s.io/helm/pkg/helm/helmpath"
"k8s.io/helm/pkg/plugin" "k8s.io/helm/pkg/plugin"
"github.com/spf13/cobra"
) )
type pluginRemoveOptions struct { type pluginRemoveOptions struct {
@ -76,7 +76,7 @@ func (o *pluginRemoveOptions) run(out io.Writer) error {
} }
} }
if len(errorPlugins) > 0 { if len(errorPlugins) > 0 {
return fmt.Errorf(strings.Join(errorPlugins, "\n")) return errors.Errorf(strings.Join(errorPlugins, "\n"))
} }
return nil return nil
} }

@ -16,17 +16,17 @@ limitations under the License.
package main package main
import ( import (
"errors"
"fmt" "fmt"
"io" "io"
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"k8s.io/helm/pkg/helm/helmpath" "k8s.io/helm/pkg/helm/helmpath"
"k8s.io/helm/pkg/plugin" "k8s.io/helm/pkg/plugin"
"k8s.io/helm/pkg/plugin/installer" "k8s.io/helm/pkg/plugin/installer"
"github.com/spf13/cobra"
) )
type pluginUpdateOptions struct { type pluginUpdateOptions struct {
@ -79,7 +79,7 @@ func (o *pluginUpdateOptions) run(out io.Writer) error {
} }
} }
if len(errorPlugins) > 0 { if len(errorPlugins) > 0 {
return fmt.Errorf(strings.Join(errorPlugins, "\n")) return errors.Errorf(strings.Join(errorPlugins, "\n"))
} }
return nil return nil
} }

@ -20,6 +20,7 @@ import (
"fmt" "fmt"
"io" "io"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/pkg/hapi/release" "k8s.io/helm/pkg/hapi/release"
@ -98,5 +99,5 @@ type testErr struct {
} }
func (err *testErr) Error() error { func (err *testErr) Error() error {
return fmt.Errorf("%v test(s) failed", err.failed) return errors.Errorf("%v test(s) failed", err.failed)
} }

@ -20,6 +20,7 @@ import (
"fmt" "fmt"
"io" "io"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/pkg/getter" "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) { 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) 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 { 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) f.Update(&c)

@ -17,11 +17,11 @@ limitations under the License.
package main package main
import ( import (
"fmt"
"io" "io"
"os" "os"
"path/filepath" "path/filepath"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/pkg/repo" "k8s.io/helm/pkg/repo"
@ -94,7 +94,7 @@ func index(dir, url, mergeTo string) error {
} else { } else {
i2, err = repo.LoadIndexFile(mergeTo) i2, err = repo.LoadIndexFile(mergeTo)
if err != nil { if err != nil {
return fmt.Errorf("Merge failed: %s", err) return errors.Wrap(err, "merge failed")
} }
} }
i.Merge(i2) i.Merge(i2)

@ -17,11 +17,11 @@ limitations under the License.
package main package main
import ( import (
"errors"
"fmt" "fmt"
"io" "io"
"github.com/gosuri/uitable" "github.com/gosuri/uitable"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/pkg/helm/helmpath" "k8s.io/helm/pkg/helm/helmpath"

@ -21,6 +21,7 @@ import (
"io" "io"
"os" "os"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/pkg/helm/helmpath" "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) { 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 { if err := r.WriteFile(repoFile, 0644); err != nil {
return err return err

@ -17,11 +17,11 @@ limitations under the License.
package main package main
import ( import (
"errors"
"fmt" "fmt"
"io" "io"
"sync" "sync"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/pkg/getter" "k8s.io/helm/pkg/getter"

@ -21,6 +21,7 @@ import (
"io" "io"
"strconv" "strconv"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/pkg/helm" "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) v64, err := strconv.ParseInt(args[1], 10, 32)
if err != nil { 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) o.revision = int(v64)

@ -23,6 +23,7 @@ import (
"github.com/Masterminds/semver" "github.com/Masterminds/semver"
"github.com/gosuri/uitable" "github.com/gosuri/uitable"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/cmd/helm/search" "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) constraint, err := semver.NewConstraint(o.version)
if err != nil { 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] data := res[:0]

@ -23,13 +23,14 @@ to find matches.
package search package search
import ( import (
"errors"
"path" "path"
"regexp" "regexp"
"sort" "sort"
"strings" "strings"
"github.com/Masterminds/semver" "github.com/Masterminds/semver"
"github.com/pkg/errors"
"k8s.io/helm/pkg/repo" "k8s.io/helm/pkg/repo"
) )

@ -26,6 +26,7 @@ import (
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"github.com/gosuri/uitable" "github.com/gosuri/uitable"
"github.com/gosuri/uitable/util/strutil" "github.com/gosuri/uitable/util/strutil"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/pkg/hapi" "k8s.io/helm/pkg/hapi"
@ -87,20 +88,20 @@ func (o *statusOptions) run(out io.Writer) error {
case "json": case "json":
data, err := json.Marshal(res) data, err := json.Marshal(res)
if err != nil { 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) out.Write(data)
return nil return nil
case "yaml": case "yaml":
data, err := yaml.Marshal(res) data, err := yaml.Marshal(res)
if err != nil { 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) out.Write(data)
return nil 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 // PrintStatus prints out the status of a release. Shared because also used by

@ -17,7 +17,6 @@ limitations under the License.
package main package main
import ( import (
"errors"
"fmt" "fmt"
"io" "io"
"os" "os"
@ -28,6 +27,7 @@ import (
"time" "time"
"github.com/Masterminds/semver" "github.com/Masterminds/semver"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/chartutil"
@ -120,7 +120,7 @@ func (o *templateOptions) run(out io.Writer) error {
if !filepath.IsAbs(f) { if !filepath.IsAbs(f) {
af, err = filepath.Abs(filepath.Join(o.chartPath, f)) af, err = filepath.Abs(filepath.Join(o.chartPath, f))
if err != nil { if err != nil {
return fmt.Errorf("could not resolve template path: %s", err) return errors.Wrap(err, "could not resolve template path")
} }
} else { } else {
af = f af = f
@ -128,7 +128,7 @@ func (o *templateOptions) run(out io.Writer) error {
rf = append(rf, af) rf = append(rf, af)
if _, err := os.Stat(af); err != nil { 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 != "" { if o.outputDir != "" {
_, err = os.Stat(o.outputDir) _, err = os.Stat(o.outputDir)
if os.IsNotExist(err) { 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 return err
} }
} else if err != chartutil.ErrRequirementsNotFound { } else if err != chartutil.ErrRequirementsNotFound {
return fmt.Errorf("cannot load requirements: %v", err) return errors.Wrap(err, "cannot load requirements")
} }
options := chartutil.ReleaseOptions{ options := chartutil.ReleaseOptions{
Name: o.releaseName, Name: o.releaseName,
@ -195,7 +195,7 @@ func (o *templateOptions) run(out io.Writer) error {
// kubernetes version // kubernetes version
kv, err := semver.NewVersion(o.kubeVersion) kv, err := semver.NewVersion(o.kubeVersion)
if err != nil { 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.Major = fmt.Sprint(kv.Major())
caps.KubeVersion.Minor = fmt.Sprint(kv.Minor()) caps.KubeVersion.Minor = fmt.Sprint(kv.Minor())
@ -277,7 +277,7 @@ func (o *templateOptions) run(out io.Writer) error {
} }
// write the <data> to <output-dir>/<name> // write the <data> to <output-dir>/<name>
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)) outfileName := strings.Join([]string{outputDir, name}, string(filepath.Separator))
err := ensureDirectoryForFile(outfileName) err := ensureDirectoryForFile(outfileName)

@ -1 +1 @@
Error: This command needs 1 argument: chart name Error: this command needs 1 argument: chart name

@ -1 +1 @@
Error: This command needs 2 arguments: release name, revision number Error: this command needs 2 arguments: release name, revision number

@ -1 +1 @@
Error: This command needs 2 arguments: release name, chart path Error: this command needs 2 arguments: release name, chart path

@ -21,6 +21,7 @@ import (
"io" "io"
"strings" "strings"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/pkg/chartutil" "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.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.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 return cmd
} }
@ -180,7 +179,7 @@ func (o *upgradeOptions) run(out io.Writer) error {
return err return err
} }
} else if err != chartutil.ErrRequirementsNotFound { } else if err != chartutil.ErrRequirementsNotFound {
return fmt.Errorf("cannot load requirements: %v", err) return errors.Wrap(err, "cannot load requirements")
} }
} else { } else {
return err return err
@ -199,7 +198,7 @@ func (o *upgradeOptions) run(out io.Writer) error {
helm.ReuseValues(o.reuseValues), helm.ReuseValues(o.reuseValues),
helm.UpgradeWait(o.wait)) helm.UpgradeWait(o.wait))
if err != nil { if err != nil {
return fmt.Errorf("UPGRADE FAILED: %v", err) return errors.Wrap(err, "UPGRADE FAILED")
} }
if settings.Debug { if settings.Debug {

@ -16,9 +16,9 @@ limitations under the License.
package main package main
import ( import (
"errors"
"io" "io"
"github.com/pkg/errors"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/helm/pkg/downloader" "k8s.io/helm/pkg/downloader"

@ -17,13 +17,12 @@ limitations under the License.
package chartutil package chartutil
import ( import (
"errors"
"fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"github.com/pkg/errors"
"k8s.io/helm/pkg/hapi/chart" "k8s.io/helm/pkg/hapi/chart"
) )
@ -68,17 +67,17 @@ func IsChartDir(dirName string) (bool, error) {
if fi, err := os.Stat(dirName); err != nil { if fi, err := os.Stat(dirName); err != nil {
return false, err return false, err
} else if !fi.IsDir() { } 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") chartYaml := filepath.Join(dirName, "Chart.yaml")
if _, err := os.Stat(chartYaml); os.IsNotExist(err) { 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) chartYamlContent, err := ioutil.ReadFile(chartYaml)
if err != nil { 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) chartContent, err := UnmarshalChartfile(chartYamlContent)

@ -22,6 +22,8 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"github.com/pkg/errors"
"k8s.io/helm/pkg/hapi/chart" "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. // 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) schart, err := Load(src)
if err != nil { 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 schart.Metadata = chartfile
@ -334,13 +336,13 @@ func Create(chartfile *chart.Metadata, dir string) (string, error) {
if fi, err := os.Stat(path); err != nil { if fi, err := os.Stat(path); err != nil {
return path, err return path, err
} else if !fi.IsDir() { } 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 n := chartfile.Name
cdir := filepath.Join(path, n) cdir := filepath.Join(path, n)
if fi, err := os.Stat(cdir); err == nil && !fi.IsDir() { 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 { if err := os.MkdirAll(cdir, 0755); err != nil {
return cdir, err return cdir, err

@ -20,14 +20,14 @@ import (
"archive/tar" "archive/tar"
"bytes" "bytes"
"compress/gzip" "compress/gzip"
"errors"
"fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/pkg/errors"
"k8s.io/helm/pkg/hapi/chart" "k8s.io/helm/pkg/hapi/chart"
"k8s.io/helm/pkg/ignore" "k8s.io/helm/pkg/ignore"
"k8s.io/helm/pkg/sympath" "k8s.io/helm/pkg/sympath"
@ -169,7 +169,7 @@ func LoadFiles(files []*BufferedFile) (*chart.Chart, error) {
} else if filepath.Ext(n) == ".tgz" { } else if filepath.Ext(n) == ".tgz" {
file := files[0] file := files[0]
if file.Name != n { 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 // Untar the chart and add to c.Dependencies
b := bytes.NewBuffer(file.Data) b := bytes.NewBuffer(file.Data)
@ -190,7 +190,7 @@ func LoadFiles(files []*BufferedFile) (*chart.Chart, error) {
} }
if err != nil { 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) c.Dependencies = append(c.Dependencies, sc)
@ -272,7 +272,7 @@ func LoadDir(dir string) (*chart.Chart, error) {
data, err := ioutil.ReadFile(name) data, err := ioutil.ReadFile(name)
if err != nil { 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}) files = append(files, &BufferedFile{Name: n, Data: data})

@ -16,12 +16,12 @@ limitations under the License.
package chartutil package chartutil
import ( import (
"errors"
"log" "log"
"strings" "strings"
"time" "time"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"github.com/pkg/errors"
"k8s.io/helm/pkg/hapi/chart" "k8s.io/helm/pkg/hapi/chart"
"k8s.io/helm/pkg/version" "k8s.io/helm/pkg/version"

@ -19,13 +19,13 @@ package chartutil
import ( import (
"archive/tar" "archive/tar"
"compress/gzip" "compress/gzip"
"errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"github.com/pkg/errors"
"k8s.io/helm/pkg/hapi/chart" "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 { if fi, err := os.Stat(outDir); err != nil {
return "", err return "", err
} else if !fi.IsDir() { } 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 { if c.Metadata == nil {
@ -126,7 +126,7 @@ func Save(c *chart.Chart, outDir string) (string, error) {
return "", err return "", err
} }
} else if !stat.IsDir() { } 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) f, err := os.Create(filename)

@ -20,6 +20,6 @@ import "strings"
// Transform performs a string replacement of the specified source for // Transform performs a string replacement of the specified source for
// a given key with the replacement string // 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)) return []byte(strings.Replace(src, key, replacement, -1))
} }

@ -17,8 +17,6 @@ limitations under the License.
package chartutil package chartutil
import ( import (
"errors"
"fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"log" "log"
@ -26,6 +24,7 @@ import (
"time" "time"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"github.com/pkg/errors"
"k8s.io/helm/pkg/hapi/chart" "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) { func tableLookup(v Values, simple string) (Values, error) {
v2, ok := v[simple] v2, ok := v[simple]
if !ok { 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 { if vv, ok := v2.(map[string]interface{}); ok {
return vv, nil return vv, nil
@ -111,7 +110,7 @@ func tableLookup(v Values, simple string) (Values, error) {
return vv, nil 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 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. // If dest doesn't already have the key, create it.
dest[subchart.Metadata.Name] = map[string]interface{}{} dest[subchart.Metadata.Name] = map[string]interface{}{}
} else if !istable(c) { } 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 { if dv, ok := dest[subchart.Metadata.Name]; ok {
dvmap := dv.(map[string]interface{}) 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. // On error, we return just the overridden values.
// FIXME: We should log this error. It indicates that the YAML data // FIXME: We should log this error. It indicates that the YAML data
// did not parse. // 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 { for key, val := range nv {
@ -410,7 +409,7 @@ func (v Values) PathValue(ypath string) (interface{}, error) {
return vals[yps[0]], nil return vals[yps[0]], nil
} }
// key not found // 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 // join all elements of YAML path except last to get string table path
ypsLen := len(yps) ypsLen := len(yps)
@ -422,7 +421,7 @@ func (v Values) PathValue(ypath string) (interface{}, error) {
t, err := v.Table(st) t, err := v.Table(st)
if err != nil { if err != nil {
//no table //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 // check table for key and ensure value is not a table
if k, ok := t[sk]; ok && !istable(k) { if k, ok := t[sk]; ok && !istable(k) {
@ -431,5 +430,5 @@ func (v Values) PathValue(ypath string) (interface{}, error) {
} }
// key not found // key not found
return nil, ErrNoValue(fmt.Errorf("key not found: %s", sk)) return nil, ErrNoValue(errors.Errorf("key not found: %s", sk))
} }

@ -16,7 +16,6 @@ limitations under the License.
package downloader package downloader
import ( import (
"errors"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
@ -25,6 +24,8 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/pkg/errors"
"k8s.io/helm/pkg/getter" "k8s.io/helm/pkg/getter"
"k8s.io/helm/pkg/helm/helmpath" "k8s.io/helm/pkg/helm/helmpath"
"k8s.io/helm/pkg/provenance" "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") body, err := r.Client.Get(u.String() + ".prov")
if err != nil { if err != nil {
if c.Verify == VerifyAlways { 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) fmt.Fprintf(c.Out, "WARNING: Verification not found for %s: %s\n", ref, err)
return destfile, ver, nil 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) { func (c *ChartDownloader) ResolveChartVersionAndGetRepo(ref, version string) (*url.URL, *repo.ChartRepository, *getter.HttpGetter, error) {
u, err := url.Parse(ref) u, err := url.Parse(ref)
if err != nil { 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()) 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 // See if it's of the form: repo/path_to_chart
p := strings.SplitN(u.Path, "/", 2) p := strings.SplitN(u.Path, "/", 2)
if len(p) < 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] 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. // Next, we need to load the index, and actually look up the chart.
i, err := repo.LoadIndexFile(c.HelmHome.CacheIndex(r.Config.Name)) i, err := repo.LoadIndexFile(c.HelmHome.CacheIndex(r.Config.Name))
if err != nil { 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) cv, err := i.Get(chartName, version)
if err != nil { 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 { 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 // TODO: Seems that picking first URL is not fully correct
u, err = url.Parse(cv.URLs[0]) u, err = url.Parse(cv.URLs[0])
if err != nil { 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 // 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 // It assumes that a chart archive file is accompanied by a provenance file whose
// name is the archive file name plus the ".prov" extension. // 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. // For now, error out if it's not a tar file.
if fi, err := os.Stat(path); err != nil { if fi, err := os.Stat(path); err != nil {
return nil, err return nil, err
@ -289,12 +290,12 @@ func VerifyChart(path string, keyring string) (*provenance.Verification, error)
provfile := path + ".prov" provfile := path + ".prov"
if _, err := os.Stat(provfile); err != nil { 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, "") sig, err := provenance.NewFromKeyring(keyring, "")
if err != nil { 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) return sig.Verify(path, provfile)
} }
@ -311,12 +312,12 @@ func pickChartRepositoryConfigByName(name string, cfgs []*repo.Entry) (*repo.Ent
for _, rc := range cfgs { for _, rc := range cfgs {
if rc.Name == name { if rc.Name == name {
if rc.URL == "" { 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 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. // 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)) i, err := repo.LoadIndexFile(c.HelmHome.CacheIndex(r.Config.Name))
if err != nil { 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 { for _, entry := range i.Entries {

@ -16,7 +16,6 @@ limitations under the License.
package downloader package downloader
import ( import (
"errors"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
@ -29,6 +28,7 @@ import (
"github.com/Masterminds/semver" "github.com/Masterminds/semver"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"github.com/pkg/errors"
"k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/getter" "k8s.io/helm/pkg/getter"
@ -80,10 +80,10 @@ func (m *Manager) Build() error {
// A lock must accompany a requirements.yaml file. // A lock must accompany a requirements.yaml file.
req, err := chartutil.LoadRequirements(c) req, err := chartutil.LoadRequirements(c)
if err != nil { 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 { 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. // 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) { func (m *Manager) loadChartDir() (*chart.Chart, error) {
if fi, err := os.Stat(m.ChartPath); err != nil { 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() { } else if !fi.IsDir() {
return nil, errors.New("only unpacked charts can be updated") return nil, errors.New("only unpacked charts can be updated")
} }
@ -206,11 +206,11 @@ func (m *Manager) downloadAll(deps []*chartutil.Dependency) error {
return err return err
} }
} else if !fi.IsDir() { } 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 { 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 { 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 // https://github.com/kubernetes/helm/issues/1439
churl, username, password, err := findChartURL(dep.Name, dep.Version, dep.Repository, repos) churl, username, password, err := findChartURL(dep.Name, dep.Version, dep.Repository, repos)
if err != nil { if err != nil {
saveError = fmt.Errorf("could not find %s: %s", churl, err) saveError = errors.Wrapf(err, "could not find %s", churl)
break break
} }
@ -254,7 +254,7 @@ func (m *Manager) downloadAll(deps []*chartutil.Dependency) error {
} }
if _, _, err := dl.DownloadTo(churl, "", destPath); err != nil { 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 break
} }
} }
@ -270,7 +270,7 @@ func (m *Manager) downloadAll(deps []*chartutil.Dependency) error {
return err return err
} }
if err := os.RemoveAll(tmpPath); err != nil { 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 { } else {
fmt.Fprintln(m.Out, "Save error occurred: ", saveError) 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 { 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 { 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 return saveError
} }
@ -356,7 +356,7 @@ func (m *Manager) hasAllRepos(deps []*chartutil.Dependency) error {
} }
} }
if len(missing) > 0 { 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 return nil
} }
@ -500,7 +500,7 @@ func findChartURL(name, version, repoURL string, repos map[string]*repo.ChartRep
return return
} }
} }
err = fmt.Errorf("chart %s not found in %s", name, repoURL) err = errors.Errorf("chart %s not found in %s", name, repoURL)
return return
} }
@ -556,7 +556,7 @@ func normalizeURL(baseURL, urlOrPath string) (string, error) {
} }
u2, err := url.Parse(baseURL) u2, err := url.Parse(baseURL)
if err != nil { 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) u2.Path = path.Join(u2.Path, urlOrPath)
@ -574,7 +574,7 @@ func (m *Manager) loadChartRepositories() (map[string]*repo.ChartRepository, err
// Load repositories.yaml file // Load repositories.yaml file
rf, err := repo.LoadRepositoriesFile(repoyaml) rf, err := repo.LoadRepositoriesFile(repoyaml)
if err != nil { 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 { 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/ // 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") destPath := filepath.Join(chartpath, "charts")
if !strings.HasPrefix(repo, "file://") { 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) 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) constraint, err := semver.NewConstraint(version)
if err != nil { 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) 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 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 // move files from tmppath to destpath
@ -649,7 +649,7 @@ func move(tmpPath, destPath string) error {
tmpfile := filepath.Join(tmpPath, filename) tmpfile := filepath.Join(tmpPath, filename)
destfile := filepath.Join(destPath, filename) destfile := filepath.Join(destPath, filename)
if err := os.Rename(tmpfile, destfile); err != nil { 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 return nil

@ -18,13 +18,13 @@ package engine
import ( import (
"bytes" "bytes"
"fmt"
"path" "path"
"sort" "sort"
"strings" "strings"
"text/template" "text/template"
"github.com/Masterminds/sprig" "github.com/Masterminds/sprig"
"github.com/pkg/errors"
"k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/hapi/chart" "k8s.io/helm/pkg/hapi/chart"
@ -155,10 +155,10 @@ func (e *Engine) alterFuncMap(t *template.Template) template.FuncMap {
// Add the 'required' function here // Add the 'required' function here
funcMap["required"] = func(warn string, val interface{}) (interface{}, error) { funcMap["required"] = func(warn string, val interface{}) (interface{}, error) {
if val == nil { if val == nil {
return val, fmt.Errorf(warn) return val, errors.Errorf(warn)
} else if _, ok := val.(string); ok { } else if _, ok := val.(string); ok {
if val == "" { if val == "" {
return val, fmt.Errorf(warn) return val, errors.Errorf(warn)
} }
} }
return val, nil 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) { funcMap["tpl"] = func(tpl string, vals chartutil.Values) (string, error) {
basePath, err := vals.PathValue("Template.BasePath") basePath, err := vals.PathValue("Template.BasePath")
if err != nil { 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{ r := renderable{
@ -180,14 +180,14 @@ func (e *Engine) alterFuncMap(t *template.Template) template.FuncMap {
templates := map[string]renderable{} templates := map[string]renderable{}
templateName, err := vals.PathValue("Template.Name") templateName, err := vals.PathValue("Template.Name")
if err != nil { 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 templates[templateName.(string)] = r
result, err := e.render(templates) result, err := e.render(templates)
if err != nil { 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 return result[templateName.(string)], nil
} }
@ -206,7 +206,7 @@ func (e *Engine) render(tpls map[string]renderable) (rendered map[string]string,
// template engine. // template engine.
defer func() { defer func() {
if r := recover(); r != nil { 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") t := template.New("gotpl")
@ -230,7 +230,7 @@ func (e *Engine) render(tpls map[string]renderable) (rendered map[string]string,
r := tpls[fname] r := tpls[fname]
t = t.New(fname).Funcs(funcMap) t = t.New(fname).Funcs(funcMap)
if _, err := t.Parse(r.tpl); err != nil { 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) 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 { if t.Lookup(fname) == nil {
t = t.New(fname).Funcs(funcMap) t = t.New(fname).Funcs(funcMap)
if _, err := t.Parse(r.tpl); err != nil { 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 := tpls[file].vals
vals["Template"] = map[string]interface{}{"Name": file, "BasePath": tpls[file].basePath} vals["Template"] = map[string]interface{}{"Name": file, "BasePath": tpls[file].basePath}
if err := t.ExecuteTemplate(&buf, file, vals); err != nil { 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 "<no value>" even if Options(missing=zero) // Work around the issue where Go will emit "<no value>" even if Options(missing=zero)

@ -18,7 +18,8 @@ package getter
import ( import (
"bytes" "bytes"
"fmt"
"github.com/pkg/errors"
"k8s.io/helm/pkg/helm/environment" "k8s.io/helm/pkg/helm/environment"
) )
@ -64,7 +65,7 @@ func (p Providers) ByScheme(scheme string) (Constructor, error) {
return pp.New, nil 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. // 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 p, nil
} }
} }
return Provider{}, fmt.Errorf("scheme %q not supported", scheme) return Provider{}, errors.Errorf("scheme %q not supported", scheme)
} }

@ -17,11 +17,12 @@ package getter
import ( import (
"bytes" "bytes"
"fmt"
"io" "io"
"net/http" "net/http"
"strings" "strings"
"github.com/pkg/errors"
"k8s.io/helm/pkg/tlsutil" "k8s.io/helm/pkg/tlsutil"
"k8s.io/helm/pkg/urlutil" "k8s.io/helm/pkg/urlutil"
"k8s.io/helm/pkg/version" "k8s.io/helm/pkg/version"
@ -66,7 +67,7 @@ func (g *HttpGetter) get(href string) (*bytes.Buffer, error) {
return buf, err return buf, err
} }
if resp.StatusCode != 200 { 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) _, err = io.Copy(buf, resp.Body)
@ -85,7 +86,7 @@ func NewHTTPGetter(URL, CertFile, KeyFile, CAFile string) (*HttpGetter, error) {
if CertFile != "" && KeyFile != "" { if CertFile != "" && KeyFile != "" {
tlsConf, err := tlsutil.NewClientTLS(CertFile, KeyFile, CAFile) tlsConf, err := tlsutil.NewClientTLS(CertFile, KeyFile, CAFile)
if err != nil { 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() tlsConf.BuildNameToCertificate()

@ -17,11 +17,12 @@ package getter
import ( import (
"bytes" "bytes"
"fmt"
"os" "os"
"os/exec" "os/exec"
"path/filepath" "path/filepath"
"github.com/pkg/errors"
"k8s.io/helm/pkg/helm/environment" "k8s.io/helm/pkg/helm/environment"
"k8s.io/helm/pkg/plugin" "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 err := prog.Run(); err != nil {
if eerr, ok := err.(*exec.ExitError); ok { if eerr, ok := err.(*exec.ExitError); ok {
os.Stderr.Write(eerr.Stderr) 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 return nil, err
} }

@ -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. // 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 // load the chart to update
chart, err := chartutil.Load(chstr) chart, err := chartutil.Load(chstr)
if err != nil { if err != nil {

@ -17,12 +17,12 @@ limitations under the License.
package helm // import "k8s.io/helm/pkg/helm" package helm // import "k8s.io/helm/pkg/helm"
import ( import (
"errors"
"fmt"
"math/rand" "math/rand"
"sync" "sync"
"time" "time"
"github.com/pkg/errors"
"k8s.io/helm/pkg/hapi" "k8s.io/helm/pkg/hapi"
"k8s.io/helm/pkg/hapi/chart" "k8s.io/helm/pkg/hapi/chart"
"k8s.io/helm/pkg/hapi/release" "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 // 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...) return c.UpdateReleaseFromChart(rlsName, &chart.Chart{}, opts...)
} }
@ -118,7 +118,7 @@ func (c *FakeClient) ReleaseStatus(rlsName string, version int) (*hapi.GetReleas
}, nil }, 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. // 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 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. // ReleaseHistory returns a release's revision history.

@ -17,11 +17,12 @@ limitations under the License.
package helm // import "k8s.io/helm/pkg/helm" package helm // import "k8s.io/helm/pkg/helm"
import ( import (
"errors"
"path/filepath" "path/filepath"
"reflect" "reflect"
"testing" "testing"
"github.com/pkg/errors"
"k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/hapi" "k8s.io/helm/pkg/hapi"
cpb "k8s.io/helm/pkg/hapi/chart" cpb "k8s.io/helm/pkg/hapi/chart"

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

@ -19,7 +19,6 @@ package kube // import "k8s.io/helm/pkg/kube"
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
goerrors "errors"
"fmt" "fmt"
"io" "io"
"log" "log"
@ -27,6 +26,7 @@ import (
"time" "time"
jsonpatch "github.com/evanphx/json-patch" jsonpatch "github.com/evanphx/json-patch"
goerrors "github.com/pkg/errors"
appsv1 "k8s.io/api/apps/v1" appsv1 "k8s.io/api/apps/v1"
appsv1beta1 "k8s.io/api/apps/v1beta1" appsv1beta1 "k8s.io/api/apps/v1beta1"
appsv1beta2 "k8s.io/api/apps/v1beta2" 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 { for _, o := range ot {
if err := p.PrintObj(o, buf); err != nil { if err := p.PrintObj(o, buf); err != nil {
c.Log("failed to print object type %s, object: %q :\n %v", t, o, err) return "", goerrors.Wrapf(err, "failed to print object type %s, object: %q", t, o)
return "", err
} }
} }
if _, err := buf.WriteString("\n"); err != nil { 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. // not present in the target configuration.
// //
// Namespace will set the namespaces. // 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) original, err := c.BuildUnstructured(namespace, originalReader)
if err != nil { 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") c.Log("building resources from updated manifest")
target, err := c.BuildUnstructured(namespace, targetReader) target, err := c.BuildUnstructured(namespace, targetReader)
if err != nil { if err != nil {
return fmt.Errorf("failed decoding reader into objects: %s", err) return goerrors.Wrap(err, "failed decoding reader into objects")
} }
updateErrors := []string{} updateErrors := []string{}
@ -259,12 +258,12 @@ func (c *Client) Update(namespace string, originalReader, targetReader io.Reader
helper := resource.NewHelper(info.Client, info.Mapping) helper := resource.NewHelper(info.Client, info.Mapping)
if _, err := helper.Get(info.Namespace, info.Name, info.Export); err != nil { if _, err := helper.Get(info.Namespace, info.Name, info.Export); err != nil {
if !errors.IsNotFound(err) { 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. // Since the resource does not exist, create it.
if err := createResource(info); err != nil { 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 kind := info.Mapping.GroupVersionKind.Kind
@ -275,7 +274,7 @@ func (c *Client) Update(namespace string, originalReader, targetReader io.Reader
originalInfo := original.Get(info) originalInfo := original.Get(info)
if originalInfo == nil { if originalInfo == nil {
kind := info.Mapping.GroupVersionKind.Kind 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 { 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: case err != nil:
return err return err
case len(updateErrors) != 0: case len(updateErrors) != 0:
return fmt.Errorf(strings.Join(updateErrors, " && ")) return goerrors.Errorf(strings.Join(updateErrors, " && "))
} }
for _, info := range original.Difference(target) { 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) { func createPatch(target *resource.Info, current runtime.Object) ([]byte, types.PatchType, error) {
oldData, err := json.Marshal(current) oldData, err := json.Marshal(current)
if err != nil { 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) newData, err := json.Marshal(target.Object)
if err != nil { 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 // 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) patch, err := jsonpatch.CreateMergePatch(oldData, newData)
return patch, types.MergePatchType, err return patch, types.MergePatchType, err
case err != nil: 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: default:
patch, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, versionedObject) patch, err := strategicpatch.CreateTwoWayMergePatch(oldData, newData, versionedObject)
return patch, types.StrategicMergePatchType, err 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) patch, patchType, err := createPatch(target, currentObj)
if err != nil { if err != nil {
return fmt.Errorf("failed to create patch: %s", err) return goerrors.Wrap(err, "failed to create patch")
} }
if patch == nil { if patch == nil {
c.Log("Looks like there are no changes for %s %q", target.Mapping.GroupVersionKind.Kind, target.Name) 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 // 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 // Otherwise there will be no labels and other functions that use labels will panic
if err := target.Get(); err != nil { 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 { } else {
// send patch to server // send patch to server
@ -460,7 +459,7 @@ func updateResource(c *Client, target *resource.Info, currentObj runtime.Object,
// ... and recreate // ... and recreate
if err := createResource(target); err != nil { 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) 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 return typed.Spec.Selector.MatchLabels, nil
default: 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: case watch.Error:
// Handle error and return with an error. // Handle error and return with an error.
c.Log("Error event for %s", info.Name) 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: default:
return false, nil 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) { func (c *Client) waitForJob(e watch.Event, name string) (bool, error) {
o, ok := e.Object.(*batchinternal.Job) o, ok := e.Object.(*batchinternal.Job)
if !ok { 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 { for _, c := range o.Status.Conditions {
if c.Type == batchinternal.JobComplete && c.Status == core.ConditionTrue { if c.Type == batchinternal.JobComplete && c.Status == core.ConditionTrue {
return true, nil return true, nil
} else if c.Type == batchinternal.JobFailed && c.Status == core.ConditionTrue { } 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 kind := info.Mapping.GroupVersionKind.Kind
if kind != "Pod" { 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 { if err := c.watchPodUntilComplete(timeout, info); err != nil {

@ -17,14 +17,12 @@ limitations under the License.
package rules // import "k8s.io/helm/pkg/lint/rules" package rules // import "k8s.io/helm/pkg/lint/rules"
import ( import (
"errors"
"fmt"
"os" "os"
"path/filepath" "path/filepath"
"github.com/Masterminds/semver" "github.com/Masterminds/semver"
"github.com/asaskevich/govalidator" "github.com/asaskevich/govalidator"
"github.com/pkg/errors"
"k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/hapi/chart" "k8s.io/helm/pkg/hapi/chart"
@ -68,7 +66,7 @@ func validateChartYamlNotDirectory(chartPath string) error {
func validateChartYamlFormat(chartFileError error) error { func validateChartYamlFormat(chartFileError error) error {
if chartFileError != nil { 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 return nil
} }
@ -82,7 +80,7 @@ func validateChartName(cf *chart.Metadata) error {
func validateChartNameDirMatch(chartDir string, cf *chart.Metadata) error { func validateChartNameDirMatch(chartDir string, cf *chart.Metadata) error {
if cf.Name != filepath.Base(chartDir) { 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 return nil
} }
@ -95,7 +93,7 @@ func validateChartVersion(cf *chart.Metadata) error {
version, err := semver.NewVersion(cf.Version) version, err := semver.NewVersion(cf.Version)
if err != nil { 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") c, err := semver.NewConstraint("> 0")
@ -105,7 +103,7 @@ func validateChartVersion(cf *chart.Metadata) error {
valid, msg := c.Validate(version) valid, msg := c.Validate(version)
if !valid && len(msg) > 0 { if !valid && len(msg) > 0 {
return fmt.Errorf("version %v", msg[0]) return errors.Errorf("version %v", msg[0])
} }
return nil return nil
@ -116,9 +114,9 @@ func validateChartMaintainer(cf *chart.Metadata) error {
if maintainer.Name == "" { if maintainer.Name == "" {
return errors.New("each maintainer requires a name") return errors.New("each maintainer requires a name")
} else if maintainer.Email != "" && !govalidator.IsEmail(maintainer.Email) { } 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) { } 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 return nil
@ -127,7 +125,7 @@ func validateChartMaintainer(cf *chart.Metadata) error {
func validateChartSources(cf *chart.Metadata) error { func validateChartSources(cf *chart.Metadata) error {
for _, source := range cf.Sources { for _, source := range cf.Sources {
if source == "" || !govalidator.IsRequestURL(source) { if source == "" || !govalidator.IsRequestURL(source) {
return fmt.Errorf("invalid source URL '%s'", source) return errors.Errorf("invalid source URL '%s'", source)
} }
} }
return nil return nil
@ -142,7 +140,7 @@ func validateChartIconPresence(cf *chart.Metadata) error {
func validateChartIconURL(cf *chart.Metadata) error { func validateChartIconURL(cf *chart.Metadata) error {
if cf.Icon != "" && !govalidator.IsRequestURL(cf.Icon) { 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 return nil
} }

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

@ -17,13 +17,12 @@ limitations under the License.
package rules package rules
import ( import (
"errors"
"fmt"
"os" "os"
"path/filepath" "path/filepath"
"time" "time"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"github.com/pkg/errors"
"k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/engine" "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 { func validateYamlContent(err error) error {
if err != nil { return errors.Wrap(err, "unable to parse YAML")
return fmt.Errorf("unable to parse YAML\n\t%s", err)
}
return nil
} }
// K8sYamlStruct stubs a Kubernetes YAML file. // K8sYamlStruct stubs a Kubernetes YAML file.

@ -17,10 +17,11 @@ limitations under the License.
package rules package rules
import ( import (
"fmt"
"os" "os"
"path/filepath" "path/filepath"
"github.com/pkg/errors"
"k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/lint/support" "k8s.io/helm/pkg/lint/support"
) )
@ -41,15 +42,12 @@ func Values(linter *support.Linter) {
func validateValuesFileExistence(valuesPath string) error { func validateValuesFileExistence(valuesPath string) error {
_, err := os.Stat(valuesPath) _, err := os.Stat(valuesPath)
if err != nil { if err != nil {
return fmt.Errorf("file does not exist") return errors.Errorf("file does not exist")
} }
return nil return nil
} }
func validateValuesFile(valuesPath string) error { func validateValuesFile(valuesPath string) error {
_, err := chartutil.ReadValuesFile(valuesPath) _, err := chartutil.ReadValuesFile(valuesPath)
if err != nil { return errors.Wrap(err, "unable to parse YAML")
return fmt.Errorf("unable to parse YAML\n\t%s", err)
}
return nil
} }

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

@ -19,13 +19,14 @@ import (
"archive/tar" "archive/tar"
"bytes" "bytes"
"compress/gzip" "compress/gzip"
"fmt"
"io" "io"
"os" "os"
"path/filepath" "path/filepath"
"regexp" "regexp"
"strings" "strings"
"github.com/pkg/errors"
"k8s.io/helm/pkg/getter" "k8s.io/helm/pkg/getter"
"k8s.io/helm/pkg/helm/environment" "k8s.io/helm/pkg/helm/environment"
"k8s.io/helm/pkg/helm/helmpath" "k8s.io/helm/pkg/helm/helmpath"
@ -62,7 +63,7 @@ func NewExtractor(source string) (Extractor, error) {
return extractor, nil 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. // NewHTTPInstaller creates a new HttpInstaller.
@ -141,7 +142,7 @@ func (i *HTTPInstaller) Install() error {
// Update updates a local repository // Update updates a local repository
// Not implemented for now since tarball most likely will be packaged by version // Not implemented for now since tarball most likely will be packaged by version
func (i *HTTPInstaller) Update() error { 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() // 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() outFile.Close()
default: 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)
} }
} }

@ -18,11 +18,12 @@ package installer // import "k8s.io/helm/pkg/plugin/installer"
import ( import (
"bytes" "bytes"
"encoding/base64" "encoding/base64"
"fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"testing" "testing"
"github.com/pkg/errors"
"k8s.io/helm/pkg/helm/helmpath" "k8s.io/helm/pkg/helm/helmpath"
) )
@ -131,7 +132,7 @@ func TestHTTPInstallerNonExistentVersion(t *testing.T) {
// inject fake http client responding with error // inject fake http client responding with error
httpInstaller.getter = &TestHTTPGetter{ 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 // attempt to install the plugin

@ -16,13 +16,14 @@ limitations under the License.
package installer package installer
import ( import (
"errors"
"fmt" "fmt"
"os" "os"
"path" "path"
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/pkg/errors"
"k8s.io/helm/pkg/helm/helmpath" "k8s.io/helm/pkg/helm/helmpath"
) )

@ -16,9 +16,10 @@ limitations under the License.
package installer // import "k8s.io/helm/pkg/plugin/installer" package installer // import "k8s.io/helm/pkg/plugin/installer"
import ( import (
"fmt"
"path/filepath" "path/filepath"
"github.com/pkg/errors"
"k8s.io/helm/pkg/helm/helmpath" "k8s.io/helm/pkg/helm/helmpath"
) )
@ -31,7 +32,7 @@ type LocalInstaller struct {
func NewLocalInstaller(source string, home helmpath.Home) (*LocalInstaller, error) { func NewLocalInstaller(source string, home helmpath.Home) (*LocalInstaller, error) {
src, err := filepath.Abs(source) src, err := filepath.Abs(source)
if err != nil { 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{ i := &LocalInstaller{
base: newBase(src, home), base: newBase(src, home),

@ -16,13 +16,12 @@ limitations under the License.
package installer // import "k8s.io/helm/pkg/plugin/installer" package installer // import "k8s.io/helm/pkg/plugin/installer"
import ( import (
"errors"
"fmt"
"os" "os"
"sort" "sort"
"github.com/Masterminds/semver" "github.com/Masterminds/semver"
"github.com/Masterminds/vcs" "github.com/Masterminds/vcs"
"github.com/pkg/errors"
"k8s.io/helm/pkg/helm/helmpath" "k8s.io/helm/pkg/helm/helmpath"
"k8s.io/helm/pkg/plugin/cache" "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 // setVersion attempts to checkout the version

@ -19,8 +19,6 @@ import (
"bytes" "bytes"
"crypto" "crypto"
"encoding/hex" "encoding/hex"
"errors"
"fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"os" "os"
@ -28,7 +26,7 @@ import (
"strings" "strings"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"github.com/pkg/errors"
"golang.org/x/crypto/openpgp" "golang.org/x/crypto/openpgp"
"golang.org/x/crypto/openpgp/clearsign" "golang.org/x/crypto/openpgp/clearsign"
"golang.org/x/crypto/openpgp/packet" "golang.org/x/crypto/openpgp/packet"
@ -142,7 +140,7 @@ func NewFromKeyring(keyringfile, id string) (*Signatory, error) {
} }
} }
if vague { 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 s.Entity = candidate
@ -238,14 +236,14 @@ func (s *Signatory) Verify(chartpath, sigpath string) (*Verification, error) {
if fi, err := os.Stat(fname); err != nil { if fi, err := os.Stat(fname); err != nil {
return ver, err return ver, err
} else if fi.IsDir() { } 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 // First verify the signature
sig, err := s.decodeSignature(sigpath) sig, err := s.decodeSignature(sigpath)
if err != nil { 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) by, err := s.verifySignature(sig)
@ -267,9 +265,9 @@ func (s *Signatory) Verify(chartpath, sigpath string) (*Verification, error) {
sum = "sha256:" + sum sum = "sha256:" + sum
basename := filepath.Base(chartpath) basename := filepath.Base(chartpath)
if sha, ok := sums.Files[basename]; !ok { 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 { } 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.FileHash = sum
ver.FileName = basename ver.FileName = basename

@ -17,9 +17,10 @@ limitations under the License.
package releasetesting package releasetesting
import ( import (
"errors"
"testing" "testing"
"github.com/pkg/errors"
"k8s.io/helm/pkg/hapi/release" "k8s.io/helm/pkg/hapi/release"
) )

@ -17,11 +17,11 @@ limitations under the License.
package releasetesting package releasetesting
import ( import (
"fmt"
"strings" "strings"
"time" "time"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"github.com/pkg/errors"
"k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/helm/pkg/hapi/release" "k8s.io/helm/pkg/hapi/release"
@ -141,7 +141,7 @@ func expectedSuccess(hookTypes []string) (bool, error) {
return false, nil 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 { func extractTestManifestsFromHooks(h []*release.Hook) []string {
@ -165,7 +165,7 @@ func newTest(testManifest string) (*test, error) {
} }
if sh.Kind != "Pod" { 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] hookTypes := sh.Metadata.Annotations[hooks.HookAnno]

@ -25,6 +25,7 @@ import (
"strings" "strings"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"github.com/pkg/errors"
"k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/getter" "k8s.io/helm/pkg/getter"
@ -55,16 +56,16 @@ type ChartRepository struct {
func NewChartRepository(cfg *Entry, getters getter.Providers) (*ChartRepository, error) { func NewChartRepository(cfg *Entry, getters getter.Providers) (*ChartRepository, error) {
u, err := url.Parse(cfg.URL) u, err := url.Parse(cfg.URL)
if err != nil { 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) getterConstructor, err := getters.ByScheme(u.Scheme)
if err != nil { 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) client, err := getterConstructor(cfg.URL, cfg.CertFile, cfg.KeyFile, cfg.CAFile)
if err != nil { 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{ return &ChartRepository{
@ -83,7 +84,7 @@ func (r *ChartRepository) Load() error {
return err return err
} }
if !dirInfo.IsDir() { 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? // 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 // Download and write the index file to a temporary location
tempIndexFile, err := ioutil.TempFile("", "tmp-repo-file") tempIndexFile, err := ioutil.TempFile("", "tmp-repo-file")
if err != nil { 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()) defer os.Remove(tempIndexFile.Name())
@ -221,7 +222,7 @@ func FindChartInAuthRepoURL(repoURL, username, password, chartName, chartVersion
return "", err return "", err
} }
if err := r.DownloadIndexFile(tempIndexFile.Name()); err != nil { 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 // 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) cv, err := repoIndex.Get(chartName, chartVersion)
if err != nil { 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 { 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] chartURL := cv.URLs[0]
absoluteChartURL, err := ResolveReferenceURL(repoURL, chartURL) absoluteChartURL, err := ResolveReferenceURL(repoURL, chartURL)
if err != nil { 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 return absoluteChartURL, nil
@ -258,12 +259,12 @@ func FindChartInAuthRepoURL(repoURL, username, password, chartName, chartVersion
func ResolveReferenceURL(baseURL, refURL string) (string, error) { func ResolveReferenceURL(baseURL, refURL string) (string, error) {
parsedBaseURL, err := url.Parse(baseURL) parsedBaseURL, err := url.Parse(baseURL)
if err != nil { 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) parsedRefURL, err := url.Parse(refURL)
if err != nil { 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 return parsedBaseURL.ResolveReference(parsedRefURL).String(), nil

@ -243,7 +243,7 @@ func TestErrorFindChartInRepoURL(t *testing.T) {
if err == nil { if err == nil {
t.Errorf("Expected error for bad chart URL, but did not get any errors") 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) t.Errorf("Expected error for bad chart URL, but got a different error (%v)", err)
} }

@ -18,7 +18,6 @@ package repo
import ( import (
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
@ -29,6 +28,7 @@ import (
"github.com/Masterminds/semver" "github.com/Masterminds/semver"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"github.com/pkg/errors"
"k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/hapi/chart" "k8s.io/helm/pkg/hapi/chart"
@ -177,7 +177,7 @@ func (i IndexFile) Get(name, version string) (*ChartVersion, error) {
return ver, nil 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. // WriteFile writes an index file to the given destination path.

@ -17,13 +17,13 @@ limitations under the License.
package repo // import "k8s.io/helm/pkg/repo" package repo // import "k8s.io/helm/pkg/repo"
import ( import (
"errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
"os" "os"
"time" "time"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"github.com/pkg/errors"
) )
// ErrRepoOutOfDate indicates that the repository file is out of date, but // 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) b, err := ioutil.ReadFile(path)
if err != nil { if err != nil {
if os.IsNotExist(err) { if os.IsNotExist(err) {
return nil, fmt.Errorf( return nil, errors.Errorf(
"Couldn't load repositories file (%s).\n"+ "couldn't load repositories file (%s).\n"+
"You might need to run `helm init` (or "+ "You might need to run `helm init` (or "+
"`helm init --client-only` if tiller is "+ "`helm init --client-only` if tiller is "+
"already installed)", path) "already installed)", path)

@ -18,13 +18,13 @@ package resolver
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"fmt"
"os" "os"
"path/filepath" "path/filepath"
"strings" "strings"
"time" "time"
"github.com/Masterminds/semver" "github.com/Masterminds/semver"
"github.com/pkg/errors"
"k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/helm/helmpath" "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) constraint, err := semver.NewConstraint(d.Version)
if err != nil { 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])) repoIndex, err := repo.LoadIndexFile(r.helmhome.CacheIndex(repoNames[d.Name]))
if err != nil { 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] vs, ok := repoIndex.Entries[d.Name]
if !ok { 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{ locked[i] = &chartutil.Dependency{
@ -105,7 +105,7 @@ func (r *Resolver) Resolve(reqs *chartutil.Requirements, repoNames map[string]st
} }
} }
if len(missing) > 0 { 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{ return &chartutil.RequirementsLock{
Generated: time.Now(), Generated: time.Now(),
@ -129,7 +129,7 @@ func HashReq(req *chartutil.Requirements) (string, error) {
// GetLocalPath generates absolute local path when use // GetLocalPath generates absolute local path when use
// "file://" in repository of requirements // "file://" in repository of requirements
func GetLocalPath(repo string, chartpath string) (string, error) { func GetLocalPath(repo, chartpath string) (string, error) {
var depPath string var depPath string
var err error var err error
p := strings.TrimPrefix(repo, "file://") 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) { 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 { } else if err != nil {
return "", err return "", err
} }

@ -17,11 +17,12 @@ limitations under the License.
package driver // import "k8s.io/helm/pkg/storage/driver" package driver // import "k8s.io/helm/pkg/storage/driver"
import ( import (
"fmt"
"strconv" "strconv"
"strings" "strings"
"time" "time"
"github.com/pkg/errors"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 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{} ls := kblabels.Set{}
for k, v := range labels { for k, v := range labels {
if errs := validation.IsValidLabelValue(v); len(errs) != 0 { 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 ls[k] = v
} }

@ -17,18 +17,18 @@ limitations under the License.
package driver // import "k8s.io/helm/pkg/storage/driver" package driver // import "k8s.io/helm/pkg/storage/driver"
import ( import (
"fmt" "github.com/pkg/errors"
rspb "k8s.io/helm/pkg/hapi/release" rspb "k8s.io/helm/pkg/hapi/release"
) )
var ( var (
// ErrReleaseNotFound indicates that a release is not found. // 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 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 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. // Creator is the interface that wraps the Create method.

@ -17,11 +17,12 @@ limitations under the License.
package driver // import "k8s.io/helm/pkg/storage/driver" package driver // import "k8s.io/helm/pkg/storage/driver"
import ( import (
"fmt"
"strconv" "strconv"
"strings" "strings"
"time" "time"
"github.com/pkg/errors"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 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) { if apierrors.IsNotFound(err) {
return nil, ErrReleaseNotFound(key) return nil, ErrReleaseNotFound(key)
} }
return nil, errors.Wrapf(err, "get: failed to get %q", key)
secrets.Log("get: failed to get %q: %s", key, err)
return nil, err
} }
// found the secret, decode the base64 data string // found the secret, decode the base64 data string
r, err := decodeRelease(string(obj.Data["release"])) r, err := decodeRelease(string(obj.Data["release"]))
if err != nil { return r, errors.Wrapf(err, "get: failed to decode data %q", key)
secrets.Log("get: failed to decode data %q: %s", key, err)
return nil, err
}
// return the release object
return r, nil
} }
// List fetches all releases and returns the list releases such // 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) list, err := secrets.impl.List(opts)
if err != nil { if err != nil {
secrets.Log("list: failed to list: %s", err) return nil, errors.Wrap(err, "list: failed to list")
return nil, err
} }
var results []*rspb.Release var results []*rspb.Release
@ -117,7 +110,7 @@ func (secrets *Secrets) Query(labels map[string]string) ([]*rspb.Release, error)
ls := kblabels.Set{} ls := kblabels.Set{}
for k, v := range labels { for k, v := range labels {
if errs := validation.IsValidLabelValue(v); len(errs) != 0 { 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 ls[k] = v
} }
@ -126,8 +119,7 @@ func (secrets *Secrets) Query(labels map[string]string) ([]*rspb.Release, error)
list, err := secrets.impl.List(opts) list, err := secrets.impl.List(opts)
if err != nil { if err != nil {
secrets.Log("query: failed to query with labels: %s", err) return nil, errors.Wrap(err, "query: failed to query with labels")
return nil, err
} }
if len(list.Items) == 0 { 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 // create a new secret to hold the release
obj, err := newSecretsObject(key, rls, lbs) obj, err := newSecretsObject(key, rls, lbs)
if err != nil { if err != nil {
secrets.Log("create: failed to encode release %q: %s", rls.Name, err) return errors.Wrapf(err, "create: failed to encode release %q", rls.Name)
return err
} }
// push the secret object out into the kubiverse // push the secret object out into the kubiverse
if _, err := secrets.impl.Create(obj); err != nil { 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) return ErrReleaseExists(rls.Name)
} }
secrets.Log("create: failed to create: %s", err) return errors.Wrap(err, "create: failed to create")
return err
} }
return nil 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 // create a new secret object to hold the release
obj, err := newSecretsObject(key, rls, lbs) obj, err := newSecretsObject(key, rls, lbs)
if err != nil { if err != nil {
secrets.Log("update: failed to encode release %q: %s", rls.Name, err) return errors.Wrapf(err, "update: failed to encode release %q", rls.Name)
return err
} }
// push the secret object out into the kubiverse // push the secret object out into the kubiverse
_, err = secrets.impl.Update(obj) _, err = secrets.impl.Update(obj)
if err != nil { return errors.Wrap(err, "update: failed to update")
secrets.Log("update: failed to update: %s", err)
return err
}
return nil
} }
// Delete deletes the Secret holding the release named by key. // 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) return nil, ErrReleaseExists(rls.Name)
} }
secrets.Log("delete: failed to get release %q: %s", key, err) return nil, errors.Wrapf(err, "delete: failed to get release %q", key)
return nil, err
} }
// delete the release // delete the release
if err = secrets.impl.Delete(key, &metav1.DeleteOptions{}); err != nil { err = secrets.impl.Delete(key, &metav1.DeleteOptions{})
return rls, err return rls, err
}
return rls, nil
} }
// newSecretsObject constructs a kubernetes Secret object // newSecretsObject constructs a kubernetes Secret object

@ -20,6 +20,8 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/pkg/errors"
rspb "k8s.io/helm/pkg/hapi/release" rspb "k8s.io/helm/pkg/hapi/release"
relutil "k8s.io/helm/pkg/releaseutil" relutil "k8s.io/helm/pkg/releaseutil"
"k8s.io/helm/pkg/storage/driver" "k8s.io/helm/pkg/storage/driver"
@ -124,13 +126,13 @@ func (s *Storage) Deployed(name string) (*rspb.Release, error) {
ls, err := s.DeployedAll(name) ls, err := s.DeployedAll(name)
if err != nil { if err != nil {
if strings.Contains(err.Error(), "not found") { 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 return nil, err
} }
if len(ls) == 0 { 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 return ls[0], err
@ -150,7 +152,7 @@ func (s *Storage) DeployedAll(name string) ([]*rspb.Release, error) {
return ls, nil return ls, nil
} }
if strings.Contains(err.Error(), "not found") { 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 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, // Delete as many as possible. In the case of API throughput limitations,
// multiple invocations of this function will eventually delete them all. // multiple invocations of this function will eventually delete them all.
toDelete := h[0:overage] toDelete := h[0:overage]
errors := []error{} errs := []error{}
for _, rel := range toDelete { for _, rel := range toDelete {
key := makeKey(name, rel.Version) key := makeKey(name, rel.Version)
_, innerErr := s.Delete(name, rel.Version) _, innerErr := s.Delete(name, rel.Version)
if innerErr != nil { if innerErr != nil {
s.Log("error pruning %s from release history: %s", key, innerErr) 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)) s.Log("Pruned %d record(s) from %s with %d error(s)", len(toDelete), name, len(errs))
switch c := len(errors); c { switch c := len(errs); c {
case 0: case 0:
return nil return nil
case 1: case 1:
return errors[0] return errs[0]
default: 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 return nil, err
} }
if len(h) == 0 { 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) relutil.Reverse(h, relutil.SortByRevision)

@ -17,13 +17,12 @@ package strvals
import ( import (
"bytes" "bytes"
"errors"
"fmt"
"io" "io"
"strconv" "strconv"
"strings" "strings"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"github.com/pkg/errors"
) )
// ErrNotList indicates that a non-list was treated as a list. // 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 { if len(k) == 0 {
return err 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), "") //set(data, string(k), "")
//return err //return err
case last == '[': case last == '[':
// We are in a list index context, so we need to set an index. // We are in a list index context, so we need to set an index.
i, err := t.keyIndex() i, err := t.keyIndex()
if err != nil { if err != nil {
return fmt.Errorf("error parsing index: %s", err) return errors.Wrap(err, "error parsing index")
} }
kk := string(k) kk := string(k)
// Find or create target list // Find or create target list
@ -163,7 +162,7 @@ func (t *parser) key(data map[string]interface{}) error {
case last == ',': case last == ',':
// No value given. Set the value to empty string. Return error. // No value given. Set the value to empty string. Return error.
set(data, string(k), "") 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 == '.': case last == '.':
// First, create or find the target map. // First, create or find the target map.
inner := map[string]interface{}{} inner := map[string]interface{}{}
@ -174,7 +173,7 @@ func (t *parser) key(data map[string]interface{}) error {
// Recurse // Recurse
e := t.key(inner) e := t.key(inner)
if len(inner) == 0 { 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) set(data, string(k), inner)
return e return e
@ -215,7 +214,7 @@ func (t *parser) listItem(list []interface{}, i int) ([]interface{}, error) {
stop := runeSet([]rune{'[', '.', '='}) stop := runeSet([]rune{'[', '.', '='})
switch k, last, err := runesUntil(t.sc, stop); { switch k, last, err := runesUntil(t.sc, stop); {
case len(k) > 0: 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: case err != nil:
return list, err return list, err
case last == '=': 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. // now we have a nested list. Read the index and handle.
i, err := t.keyIndex() i, err := t.keyIndex()
if err != nil { 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 ]. // Now we need to get the value after the ].
list2, err := t.listItem(list, i) list2, err := t.listItem(list, i)
@ -251,7 +250,7 @@ func (t *parser) listItem(list []interface{}, i int) ([]interface{}, error) {
e := t.key(inner) e := t.key(inner)
return setIndex(list, i, inner), e return setIndex(list, i, inner), e
default: default:
return nil, fmt.Errorf("parse error: unexpected token %v", last) return nil, errors.Errorf("parse error: unexpected token %v", last)
} }
} }

@ -21,10 +21,11 @@ limitations under the License.
package sympath package sympath
import ( import (
"fmt"
"os" "os"
"path/filepath" "path/filepath"
"sort" "sort"
"github.com/pkg/errors"
) )
// Walk walks the file tree rooted at root, calling walkFn for each file or directory // 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) { if IsSymlink(info) {
resolved, err := filepath.EvalSymlinks(path) resolved, err := filepath.EvalSymlinks(path)
if err != nil { 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 { if info, err = os.Lstat(resolved); err != nil {
return err return err

@ -173,7 +173,7 @@ func (p *PrintingKubeClient) WatchUntilReady(ns string, r io.Reader, timeout int
} }
// Update implements KubeClient Update. // 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) _, err := io.Copy(p.Out, modifiedReader)
return err return err
} }

@ -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 { func (k *mockKubeClient) Delete(ns string, r io.Reader) error {
return nil 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 return nil
} }
func (k *mockKubeClient) WatchUntilReady(ns string, r io.Reader, timeout int64, shouldWait bool) error { func (k *mockKubeClient) WatchUntilReady(ns string, r io.Reader, timeout int64, shouldWait bool) error {

@ -17,13 +17,13 @@ limitations under the License.
package tiller package tiller
import ( import (
"fmt"
"log" "log"
"path" "path"
"strconv" "strconv"
"strings" "strings"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"github.com/pkg/errors"
"k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/hapi/release" "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 { func (file *manifestFile) sort(result *result) error {
for _, m := range file.entries { for _, m := range file.entries {
var entry util.SimpleHead var entry util.SimpleHead
err := yaml.Unmarshal([]byte(m), &entry) if err := yaml.Unmarshal([]byte(m), &entry); err != nil {
return errors.Wrapf(err, "YAML parse error on %s", file.path)
if err != nil {
e := fmt.Errorf("YAML parse error on %s: %s", file.path, err)
return e
} }
if entry.Version != "" && !file.apis.Has(entry.Version) { 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) { if !hasAnyAnnotation(entry) {

@ -17,6 +17,8 @@ limitations under the License.
package tiller package tiller
import ( import (
"github.com/pkg/errors"
"k8s.io/helm/pkg/hapi" "k8s.io/helm/pkg/hapi"
"k8s.io/helm/pkg/hapi/release" "k8s.io/helm/pkg/hapi/release"
) )
@ -24,8 +26,7 @@ import (
// GetReleaseContent gets all of the stored information for the given release. // GetReleaseContent gets all of the stored information for the given release.
func (s *ReleaseServer) GetReleaseContent(req *hapi.GetReleaseContentRequest) (*release.Release, error) { func (s *ReleaseServer) GetReleaseContent(req *hapi.GetReleaseContentRequest) (*release.Release, error) {
if err := validateReleaseName(req.Name); err != nil { if err := validateReleaseName(req.Name); err != nil {
s.Log("releaseContent: Release name is invalid: %s", req.Name) return nil, errors.Errorf("releaseContent: Release name is invalid: %s", req.Name)
return nil, err
} }
if req.Version <= 0 { if req.Version <= 0 {

@ -17,6 +17,8 @@ limitations under the License.
package tiller package tiller
import ( import (
"github.com/pkg/errors"
"k8s.io/helm/pkg/hapi" "k8s.io/helm/pkg/hapi"
"k8s.io/helm/pkg/hapi/release" "k8s.io/helm/pkg/hapi/release"
relutil "k8s.io/helm/pkg/releaseutil" relutil "k8s.io/helm/pkg/releaseutil"
@ -25,8 +27,7 @@ import (
// GetHistory gets the history for a given release. // GetHistory gets the history for a given release.
func (s *ReleaseServer) GetHistory(req *hapi.GetHistoryRequest) ([]*release.Release, error) { func (s *ReleaseServer) GetHistory(req *hapi.GetHistoryRequest) ([]*release.Release, error) {
if err := validateReleaseName(req.Name); err != nil { if err := validateReleaseName(req.Name); err != nil {
s.Log("getHistory: Release name is invalid: %s", req.Name) return nil, errors.Errorf("getHistory: Release name is invalid: %s", req.Name)
return nil, err
} }
s.Log("getting history for release %s", req.Name) s.Log("getting history for release %s", req.Name)

@ -22,6 +22,8 @@ import (
"strings" "strings"
"time" "time"
"github.com/pkg/errors"
"k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/hapi" "k8s.io/helm/pkg/hapi"
"k8s.io/helm/pkg/hapi/release" "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) s.Log("preparing install for %s", req.Name)
rel, err := s.prepareRelease(req) rel, err := s.prepareRelease(req)
if err != nil { if err != nil {
s.Log("failed install prepare step: %s", err)
// On dry run, append the manifest contents to a failed release. This is // 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. // a stop-gap until we can revisit an error backchannel post-2.0.
if req.DryRun && strings.HasPrefix(err.Error(), "YAML parse error") { 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) s.Log("performing install for %s", req.Name)
res, err := s.performRelease(rel, req) res, err := s.performRelease(rel, req)
if err != nil { return res, errors.Wrap(err, "failed install perform step")
s.Log("failed install perform step: %s", err)
}
return res, err
} }
// prepareRelease builds a release for an install operation. // 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.Status = release.StatusFailed
r.Info.Description = msg r.Info.Description = msg
s.recordRelease(r, true) 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)
} }
} }

@ -364,7 +364,7 @@ func TestInstallRelease_WrongKubeVersion(t *testing.T) {
t.Fatalf("Expected to fail because of wrong version") t.Fatalf("Expected to fail because of wrong version")
} }
expect := "Chart requires kubernetesVersion" expect := "chart requires kubernetesVersion"
if !strings.Contains(err.Error(), expect) { if !strings.Contains(err.Error(), expect) {
t.Errorf("Expected %q to contain %q", err.Error(), expect) t.Errorf("Expected %q to contain %q", err.Error(), expect)
} }

@ -21,6 +21,8 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/pkg/errors"
"k8s.io/helm/pkg/hapi" "k8s.io/helm/pkg/hapi"
"k8s.io/helm/pkg/hapi/release" "k8s.io/helm/pkg/hapi/release"
"k8s.io/helm/pkg/hooks" "k8s.io/helm/pkg/hooks"
@ -60,8 +62,7 @@ func (s *ReleaseServer) RollbackRelease(req *hapi.RollbackReleaseRequest) (*rele
// the previous release's configuration // the previous release's configuration
func (s *ReleaseServer) prepareRollback(req *hapi.RollbackReleaseRequest) (*release.Release, *release.Release, error) { func (s *ReleaseServer) prepareRollback(req *hapi.RollbackReleaseRequest) (*release.Release, *release.Release, error) {
if err := validateReleaseName(req.Name); err != nil { if err := validateReleaseName(req.Name); err != nil {
s.Log("prepareRollback: Release name is invalid: %s", req.Name) return nil, nil, errors.Errorf("prepareRollback: Release name is invalid: %s", req.Name)
return nil, nil, err
} }
if req.Version < 0 { if req.Version < 0 {

@ -18,13 +18,12 @@ package tiller
import ( import (
"bytes" "bytes"
"errors"
"fmt"
"path" "path"
"regexp" "regexp"
"strings" "strings"
"time" "time"
"github.com/pkg/errors"
"github.com/technosophos/moniker" "github.com/technosophos/moniker"
"gopkg.in/yaml.v2" "gopkg.in/yaml.v2"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 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: // We have to regenerate the old coalesced values:
oldVals, err := chartutil.CoalesceValues(current.Chart, current.Config) oldVals, err := chartutil.CoalesceValues(current.Chart, current.Config)
if err != nil { if err != nil {
err := fmt.Errorf("failed to rebuild old values: %s", err) return errors.Wrap(err, "failed to rebuild old values")
s.Log("%s", err)
return err
} }
nv, err := yaml.Marshal(oldVals) nv, err := yaml.Marshal(oldVals)
if err != nil { if err != nil {
@ -170,7 +167,7 @@ func (s *ReleaseServer) uniqName(start string, reuse bool) (string, error) {
if start != "" { if start != "" {
if len(start) > releaseNameMaxLen { 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) 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 "", 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 maxTries := 5
@ -227,7 +224,7 @@ func capabilities(disc discovery.DiscoveryInterface) (*chartutil.Capabilities, e
} }
vs, err := GetVersionSet(disc) vs, err := GetVersionSet(disc)
if err != nil { 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{ return &chartutil.Capabilities{
APIVersions: vs, APIVersions: vs,
@ -260,7 +257,7 @@ func (s *ReleaseServer) renderResources(ch *chart.Chart, values chartutil.Values
sver := version.GetVersion() sver := version.GetVersion()
if ch.Metadata.HelmVersion != "" && if ch.Metadata.HelmVersion != "" &&
!version.IsCompatibleRange(ch.Metadata.HelmVersion, sver) { !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 != "" { if ch.Metadata.KubeVersion != "" {
@ -268,7 +265,7 @@ func (s *ReleaseServer) renderResources(ch *chart.Chart, values chartutil.Values
gitVersion := cap.KubeVersion.String() gitVersion := cap.KubeVersion.String()
k8sVersion := strings.Split(gitVersion, "+")[0] k8sVersion := strings.Split(gitVersion, "+")[0]
if !version.IsCompatibleRange(ch.Metadata.KubeVersion, k8sVersion) { 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 { func (s *ReleaseServer) execHook(hs []*release.Hook, name, namespace, hook string, timeout int64) error {
code, ok := events[hook] code, ok := events[hook]
if !ok { 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) 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) b := bytes.NewBufferString(h.Manifest)
if err := s.KubeClient.Create(namespace, b, timeout, false); err != nil { 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 errors.Wrapf(err, "warning: Release %s %s %s failed", name, hook, h.Path)
return err
} }
// No way to rewind a bytes.Buffer()? // No way to rewind a bytes.Buffer()?
b.Reset() b.Reset()
@ -412,7 +408,7 @@ func validateReleaseName(releaseName string) error {
return nil 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) b := bytes.NewBufferString(h.Manifest)
if hookHasDeletePolicy(h, policy) { if hookHasDeletePolicy(h, policy) {
s.Log("deleting %s hook %s for release %s due to %q policy", hook, h.Name, name, policy) s.Log("deleting %s hook %s for release %s due to %q policy", hook, h.Name, name, policy)

@ -17,7 +17,6 @@ limitations under the License.
package tiller package tiller
import ( import (
"errors"
"flag" "flag"
"fmt" "fmt"
"io" "io"
@ -28,6 +27,7 @@ import (
"time" "time"
"github.com/ghodss/yaml" "github.com/ghodss/yaml"
"github.com/pkg/errors"
"k8s.io/client-go/kubernetes/fake" "k8s.io/client-go/kubernetes/fake"
"k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/kubectl/resource"
@ -396,7 +396,7 @@ type updateFailingKubeClient struct {
environment.PrintingKubeClient 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") 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] manifest, hasManifest := kc.Resources[paramManifest.Metadata.Name]
if !hasManifest { 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" { if manifest.Metadata.Annotations["mockHooksKubeClient/Emulate"] == "hook-failed" {
return fmt.Errorf("mockHooksKubeClient.WatchUntilReady: hook-failed") return errors.Errorf("mockHooksKubeClient.WatchUntilReady: hook-failed")
} }
return nil 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 return nil
} }
func (kc *mockHooksKubeClient) Build(ns string, reader io.Reader) (kube.Result, error) { 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 { func execHookShouldSucceed(rs *ReleaseServer, hook *release.Hook, releaseName, namespace, hookType string) error {
if err := rs.execHook([]*release.Hook{hook}, releaseName, namespace, hookType, 600); err != nil { err := rs.execHook([]*release.Hook{hook}, releaseName, namespace, hookType, 600)
return fmt.Errorf("expected hook %s to be successful: %s", hook.Name, err) return errors.Wrapf(err, "expected hook %s to be successful", hook.Name)
}
return nil
} }
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 { 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 return nil
} }
func execHookShouldFailWithError(rs *ReleaseServer, hook *release.Hook, releaseName string, namespace string, hookType string, expectedError error) error { func execHookShouldFailWithError(rs *ReleaseServer, hook *release.Hook, releaseName, namespace, hookType string, expectedError error) error {
if err := rs.execHook([]*release.Hook{hook}, releaseName, namespace, hookType, 600); err != expectedError { err := rs.execHook([]*release.Hook{hook}, releaseName, namespace, hookType, 600)
return fmt.Errorf("expected hook %s to fail with error %v, got %v", hook.Name, expectedError, err) 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 return nil
} }

@ -18,8 +18,8 @@ package tiller
import ( import (
"bytes" "bytes"
"errors"
"fmt" "github.com/pkg/errors"
"k8s.io/helm/pkg/hapi" "k8s.io/helm/pkg/hapi"
"k8s.io/helm/pkg/hapi/release" "k8s.io/helm/pkg/hapi/release"
@ -28,8 +28,7 @@ import (
// GetReleaseStatus gets the status information for a named release. // GetReleaseStatus gets the status information for a named release.
func (s *ReleaseServer) GetReleaseStatus(req *hapi.GetReleaseStatusRequest) (*hapi.GetReleaseStatusResponse, error) { func (s *ReleaseServer) GetReleaseStatus(req *hapi.GetReleaseStatusRequest) (*hapi.GetReleaseStatusResponse, error) {
if err := validateReleaseName(req.Name); err != nil { if err := validateReleaseName(req.Name); err != nil {
s.Log("getStatus: Release name is invalid: %s", req.Name) return nil, errors.Errorf("getStatus: Release name is invalid: %s", req.Name)
return nil, err
} }
var rel *release.Release var rel *release.Release
@ -38,12 +37,12 @@ func (s *ReleaseServer) GetReleaseStatus(req *hapi.GetReleaseStatusRequest) (*ha
var err error var err error
rel, err = s.Releases.Last(req.Name) rel, err = s.Releases.Last(req.Name)
if err != nil { 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 { } else {
var err error var err error
if rel, err = s.Releases.Get(req.Name, req.Version); err != nil { 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. // Skip errors if this is already deleted or failed.
return statusResp, nil return statusResp, nil
} else if err != nil { } else if err != nil {
s.Log("warning: Get for %s failed: %v", rel.Name, err) return nil, errors.Wrapf(err, "warning: Get for %s failed", rel.Name)
return nil, err
} }
rel.Info.Resources = resp rel.Info.Resources = resp
return statusResp, nil return statusResp, nil

@ -17,6 +17,8 @@ limitations under the License.
package tiller package tiller
import ( import (
"github.com/pkg/errors"
"k8s.io/helm/pkg/hapi" "k8s.io/helm/pkg/hapi"
"k8s.io/helm/pkg/hapi/release" "k8s.io/helm/pkg/hapi/release"
reltesting "k8s.io/helm/pkg/releasetesting" reltesting "k8s.io/helm/pkg/releasetesting"
@ -26,8 +28,7 @@ import (
func (s *ReleaseServer) RunReleaseTest(req *hapi.TestReleaseRequest) (<-chan *hapi.TestReleaseResponse, <-chan error) { func (s *ReleaseServer) RunReleaseTest(req *hapi.TestReleaseRequest) (<-chan *hapi.TestReleaseResponse, <-chan error) {
errc := make(chan error, 1) errc := make(chan error, 1)
if err := validateReleaseName(req.Name); err != nil { if err := validateReleaseName(req.Name); err != nil {
s.Log("releaseTest: Release name is invalid: %s", req.Name) errc <- errors.Errorf("releaseTest: Release name is invalid: %s", req.Name)
errc <- err
return nil, errc return nil, errc
} }
@ -53,8 +54,7 @@ func (s *ReleaseServer) RunReleaseTest(req *hapi.TestReleaseRequest) (<-chan *ha
defer close(ch) defer close(ch)
if err := tSuite.Run(testEnv); err != nil { if err := tSuite.Run(testEnv); err != nil {
s.Log("error running test suite for %s: %s", rel.Name, err) errc <- errors.Wrapf(err, "error running test suite for %s", rel.Name)
errc <- err
return return
} }

@ -18,11 +18,11 @@ package tiller
import ( import (
"bytes" "bytes"
"errors"
"fmt"
"strings" "strings"
"time" "time"
"github.com/pkg/errors"
"k8s.io/helm/pkg/hapi" "k8s.io/helm/pkg/hapi"
"k8s.io/helm/pkg/hapi/release" "k8s.io/helm/pkg/hapi/release"
"k8s.io/helm/pkg/hooks" "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. // 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) { func (s *ReleaseServer) UninstallRelease(req *hapi.UninstallReleaseRequest) (*hapi.UninstallReleaseResponse, error) {
if err := validateReleaseName(req.Name); err != nil { if err := validateReleaseName(req.Name); err != nil {
s.Log("uninstallRelease: Release name is invalid: %s", req.Name) return nil, errors.Errorf("uninstall: Release name is invalid: %s", req.Name)
return nil, err
} }
rels, err := s.Releases.History(req.Name) rels, err := s.Releases.History(req.Name)
if err != nil { if err != nil {
s.Log("uninstall: Release not loaded: %s", req.Name) return nil, errors.Wrapf(err, "uninstall: Release not loaded: %s", req.Name)
return nil, err
} }
if len(rels) < 1 { if len(rels) < 1 {
return nil, errMissingRelease return nil, errMissingRelease
@ -54,12 +52,11 @@ func (s *ReleaseServer) UninstallRelease(req *hapi.UninstallReleaseRequest) (*ha
if rel.Info.Status == release.StatusDeleted { if rel.Info.Status == release.StatusDeleted {
if req.Purge { if req.Purge {
if err := s.purgeReleases(rels...); err != nil { if err := s.purgeReleases(rels...); err != nil {
s.Log("uninstall: Failed to purge the release: %s", err) return nil, errors.Wrap(err, "uninstall: Failed to purge the release")
return nil, err
} }
return &hapi.UninstallReleaseResponse{Release: rel}, nil 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) s.Log("uninstall: Deleting %s", req.Name)
@ -97,10 +94,7 @@ func (s *ReleaseServer) UninstallRelease(req *hapi.UninstallReleaseRequest) (*ha
if req.Purge { if req.Purge {
s.Log("purge requested for %s", req.Name) s.Log("purge requested for %s", req.Name)
err := s.purgeReleases(rels...) err := s.purgeReleases(rels...)
if err != nil { return res, errors.Wrap(err, "uninstall: Failed to purge the release")
s.Log("uninstall: Failed to purge the release: %s", err)
}
return res, err
} }
if err := s.Releases.Update(rel); err != nil { if err := s.Releases.Update(rel); err != nil {
@ -108,7 +102,7 @@ func (s *ReleaseServer) UninstallRelease(req *hapi.UninstallReleaseRequest) (*ha
} }
if len(errs) > 0 { 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 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) { func (s *ReleaseServer) deleteRelease(rel *release.Release) (kept string, errs []error) {
vs, err := GetVersionSet(s.discovery) vs, err := GetVersionSet(s.discovery)
if err != nil { 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) 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 // 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 // deletion. The problem with this is that we could get a false positive
// and delete something that was not legitimately part of this release. // 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) filesToKeep, filesToDelete := filterManifestsToKeep(files)

@ -22,6 +22,8 @@ import (
"strings" "strings"
"time" "time"
"github.com/pkg/errors"
"k8s.io/helm/pkg/chartutil" "k8s.io/helm/pkg/chartutil"
"k8s.io/helm/pkg/hapi" "k8s.io/helm/pkg/hapi"
"k8s.io/helm/pkg/hapi/release" "k8s.io/helm/pkg/hapi/release"
@ -31,8 +33,7 @@ import (
// UpdateRelease takes an existing release and new information, and upgrades the release. // UpdateRelease takes an existing release and new information, and upgrades the release.
func (s *ReleaseServer) UpdateRelease(req *hapi.UpdateReleaseRequest) (*release.Release, error) { func (s *ReleaseServer) UpdateRelease(req *hapi.UpdateReleaseRequest) (*release.Release, error) {
if err := validateReleaseName(req.Name); err != nil { if err := validateReleaseName(req.Name); err != nil {
s.Log("updateRelease: Release name is invalid: %s", req.Name) return nil, errors.Errorf("updateRelease: Release name is invalid: %s", req.Name)
return nil, err
} }
s.Log("preparing update for %s", req.Name) s.Log("preparing update for %s", req.Name)
currentRelease, updatedRelease, err := s.prepareUpdate(req) currentRelease, updatedRelease, err := s.prepareUpdate(req)
@ -161,13 +162,12 @@ func (s *ReleaseServer) performUpdateForce(req *hapi.UpdateReleaseRequest) (*rel
Wait: req.Wait, Wait: req.Wait,
}) })
if err != nil { if err != nil {
s.Log("failed update prepare step: %s", err)
// On dry run, append the manifest contents to a failed release. This is // 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. // a stop-gap until we can revisit an error backchannel post-2.0.
if req.DryRun && strings.HasPrefix(err.Error(), "YAML parse error") { 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 // 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) s.recordRelease(oldRelease, true)
if len(errs) > 0 { 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 // post-delete hooks

@ -19,8 +19,9 @@ package tlsutil
import ( import (
"crypto/tls" "crypto/tls"
"crypto/x509" "crypto/x509"
"fmt"
"os" "os"
"github.com/pkg/errors"
) )
// Options represents configurable options used to create client and server TLS configurations. // 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 opts.CertFile != "" || opts.KeyFile != "" {
if cert, err = CertFromFilePair(opts.CertFile, opts.KeyFile); err != nil { if cert, err = CertFromFilePair(opts.CertFile, opts.KeyFile); err != nil {
if os.IsNotExist(err) { 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 != "" { 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 cert, err = CertFromFilePair(opts.CertFile, opts.KeyFile); err != nil {
if os.IsNotExist(err) { 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 opts.ClientAuth >= tls.VerifyClientCertIfGiven && opts.CaCertFile != "" {
if pool, err = CertPoolFromFile(opts.CaCertFile); err != nil { if pool, err = CertPoolFromFile(opts.CaCertFile); err != nil {

@ -19,8 +19,9 @@ package tlsutil
import ( import (
"crypto/tls" "crypto/tls"
"crypto/x509" "crypto/x509"
"fmt"
"io/ioutil" "io/ioutil"
"github.com/pkg/errors"
) )
// NewClientTLS returns tls.Config appropriate for client auth. // 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) { func CertPoolFromFile(filename string) (*x509.CertPool, error) {
b, err := ioutil.ReadFile(filename) b, err := ioutil.ReadFile(filename)
if err != nil { 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() cp := x509.NewCertPool()
if !cp.AppendCertsFromPEM(b) { 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 return cp, nil
} }
@ -65,7 +66,7 @@ func CertPoolFromFile(filename string) (*x509.CertPool, error) {
func CertFromFilePair(certFile, keyFile string) (*tls.Certificate, error) { func CertFromFilePair(certFile, keyFile string) (*tls.Certificate, error) {
cert, err := tls.LoadX509KeyPair(certFile, keyFile) cert, err := tls.LoadX509KeyPair(certFile, keyFile)
if err != nil { 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 return &cert, err
} }

Loading…
Cancel
Save