diff --git a/pkg/kubectl/cmd/update.go b/pkg/kubectl/cmd/update.go index d0d63038b07..24fea3a538f 100644 --- a/pkg/kubectl/cmd/update.go +++ b/pkg/kubectl/cmd/update.go @@ -48,7 +48,7 @@ func NewCmdUpdate(f *cmdutil.Factory, out io.Writer) *cobra.Command { Example: update_example, Run: func(cmd *cobra.Command, args []string) { err := RunUpdate(f, out, cmd, args, filenames) - cmdutil.CheckErr(err) + cmdutil.CheckCustomErr("Update failed", err) }, } usage := "Filename, directory, or URL to file to use to update the resource." diff --git a/pkg/kubectl/cmd/util/helpers.go b/pkg/kubectl/cmd/util/helpers.go index a38e04de758..2d3b59a27e0 100644 --- a/pkg/kubectl/cmd/util/helpers.go +++ b/pkg/kubectl/cmd/util/helpers.go @@ -83,6 +83,58 @@ func checkErr(err error, handleErr func(string)) { handleErr(msg) } +// CheckCustomErr is like CheckErr except a custom prefix error +// string may be provied to help produce more specific error messages. +// For example, for the update failed case this function could be called +// with: +// cmdutil.CheckCustomErr("Update failed", err) +// This function supresses the detailed output that is produced by CheckErr +// and specifically the field is erased and the error message has the details +// of the spec removed. Unfortunately, what starts off as a detail message is +// a sperate field ends up being concatentated into one string which contains +// the spec and the detail string. To avoid significant refactoring of the error +// data structures we just extract the required detail string by looking for it +// after "}': " which is horrible but expedient. +func CheckCustomErr(customPrefix string, err error) { + checkCustomErr(customPrefix, err, fatal) +} + +func checkCustomErr(customPrefix string, err error, handleErr func(string)) { + if err == nil { + return + } + + if errors.IsInvalid(err) { + details := err.(*errors.StatusError).Status().Details + for i := range details.Causes { + c := &details.Causes[i] + s := strings.Split(c.Message, "}': ") + if len(s) == 2 { + c.Message = + s[1] + c.Field = "" + } + } + prefix := fmt.Sprintf("%s", customPrefix) + errs := statusCausesToAggrError(details.Causes) + handleErr(MultilineError(prefix, errs)) + } + + // handle multiline errors + if clientcmd.IsConfigurationInvalid(err) { + handleErr(MultilineError("Error in configuration: ", err)) + } + if agg, ok := err.(utilerrors.Aggregate); ok && len(agg.Errors()) > 0 { + handleErr(MultipleErrors("", agg.Errors())) + } + + msg, ok := StandardErrorMessage(err) + if !ok { + msg = fmt.Sprintf("error: %s\n", err.Error()) + } + handleErr(msg) +} + func statusCausesToAggrError(scs []api.StatusCause) utilerrors.Aggregate { errs := make([]error, len(scs)) for i, sc := range scs {