Implementation and single-command PoC of proposed update to API error

format
malnick-err-cli-update
Jeff Mitchell 6 years ago
parent dc379ed09f
commit 8d534f6803

@ -2,9 +2,7 @@ package api
import (
"errors"
"fmt"
"net/http"
"strings"
"google.golang.org/grpc/codes"
)
@ -28,27 +26,7 @@ func AsServerError(in error) *Error {
// Error satisfies the error interface.
func (e *Error) Error() string {
res := fmt.Sprintf("Status: %d, Code: %q, Error: %q", e.Status, e.Code, e.Message)
var dets []string
if e.Details != nil {
if e.Details.ErrorId != "" {
dets = append(dets, fmt.Sprintf("error_id: %q", e.Details.ErrorId))
}
if e.Details.RequestId != "" {
dets = append(dets, fmt.Sprintf("request_id: %q", e.Details.RequestId))
}
if e.Details.TraceId != "" {
dets = append(dets, fmt.Sprintf("TraceId: %q", e.Details.TraceId))
}
for _, rf := range e.Details.RequestFields {
dets = append(dets, fmt.Sprintf("request_field: {name: %q, desc: %q}", rf.Name, rf.Description))
}
}
if len(dets) > 0 {
det := strings.Join(dets, ", ")
res = fmt.Sprintf("%s, Details: {%s}", res, det)
}
return res
return e.responseBody.String()
}
// Errors are considered the same iff they are both api.Errors and their statuses are the same.

@ -9,6 +9,7 @@ import (
"unicode"
"unicode/utf8"
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/scopes"
"github.com/mitchellh/cli"
"github.com/mitchellh/go-wordwrap"
@ -133,6 +134,50 @@ func WrapMap(prefixSpaces, maxLengthOverride int, input map[string]interface{})
return strings.Join(ret, "\n")
}
func PrintApiError(in *api.Error) string {
nonAttributeMap := map[string]interface{}{
"Status": in.Status,
"Code": in.Code,
"Message": in.Message,
}
if in.Details != nil {
if in.Details.TraceId != "" {
nonAttributeMap["Trace ID"] = in.Details.TraceId
}
if in.Details.RequestId != "" {
nonAttributeMap["Request ID"] = in.Details.RequestId
}
if in.Details.ErrorId != "" {
nonAttributeMap["Error ID"] = in.Details.ErrorId
}
}
maxLength := MaxAttributesLength(nonAttributeMap, nil, nil)
ret := []string{
"",
"Error information:",
WrapMap(2, maxLength+2, nonAttributeMap),
}
if in.Details != nil {
if len(in.Details.RequestFields) > 0 {
ret = append(ret,
"",
" Field-specific Errors:",
)
for _, field := range in.Details.RequestFields {
ret = append(ret,
fmt.Sprintf(" Name: %s", strings.ReplaceAll(field.Name, "_", "-")),
fmt.Sprintf(" Error: %s", field.Description),
)
}
}
}
return WrapForHelpText(ret)
}
// An output formatter for json output of an object
type JsonFormatter struct{}

@ -244,12 +244,23 @@ func (c *Command) Run(args []string) int {
plural = "roles"
}
if err != nil {
if api.AsServerError(err) != nil {
c.UI.Error(fmt.Sprintf("Error from controller when performing %s on %s: %s", c.Func, plural, err.Error()))
return 1
switch base.Format(c.UI) {
case "json":
if apiErr := api.AsServerError(err); apiErr != nil {
c.UI.Error(apiErr.Error())
return 1
}
c.UI.Error(fmt.Sprintf(`{"error": %q}`, err.Error()))
return 2
default:
if apiErr := api.AsServerError(err); apiErr != nil {
c.UI.Error(fmt.Sprintf("Error from controller when performing %s on %s\n%s", c.Func, plural, base.PrintApiError(apiErr)))
return 1
}
c.UI.Error(fmt.Sprintf("Error trying to %s %s: %s", c.Func, plural, err.Error()))
return 2
}
c.UI.Error(fmt.Sprintf("Error trying to %s %s: %s", c.Func, plural, err.Error()))
return 2
}
switch c.Func {

Loading…
Cancel
Save