mirror of https://github.com/k3s-io/k3s
produce more readable error messages
parent
77521a33d3
commit
564c087062
|
@ -113,6 +113,7 @@ type scope struct {
|
||||||
type scopeStackElem struct {
|
type scopeStackElem struct {
|
||||||
tag reflect.StructTag
|
tag reflect.StructTag
|
||||||
value reflect.Value
|
value reflect.Value
|
||||||
|
key string
|
||||||
}
|
}
|
||||||
|
|
||||||
type scopeStack []scopeStackElem
|
type scopeStack []scopeStackElem
|
||||||
|
@ -130,6 +131,37 @@ func (s *scopeStack) top() *scopeStackElem {
|
||||||
return &(*s)[len(*s)-1]
|
return &(*s)[len(*s)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s scopeStack) describe() string {
|
||||||
|
desc := ""
|
||||||
|
if len(s) > 1 {
|
||||||
|
desc = "(" + s[1].value.Type().String() + ")"
|
||||||
|
}
|
||||||
|
for i, v := range s {
|
||||||
|
if i < 2 {
|
||||||
|
// First layer on stack is not real; second is handled specially above.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if v.key == "" {
|
||||||
|
desc += fmt.Sprintf(".%v", v.value.Type())
|
||||||
|
} else {
|
||||||
|
desc += fmt.Sprintf(".%v", v.key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return desc
|
||||||
|
}
|
||||||
|
|
||||||
|
// Formats src & dest as indices for printing.
|
||||||
|
func (s *scope) setIndices(src, dest int) {
|
||||||
|
s.srcStack.top().key = fmt.Sprintf("[%v]", src)
|
||||||
|
s.destStack.top().key = fmt.Sprintf("[%v]", dest)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Formats src & dest as map keys for printing.
|
||||||
|
func (s *scope) setKeys(src, dest interface{}) {
|
||||||
|
s.srcStack.top().key = fmt.Sprintf(`["%v"]`, src)
|
||||||
|
s.destStack.top().key = fmt.Sprintf(`["%v"]`, dest)
|
||||||
|
}
|
||||||
|
|
||||||
// Convert continues a conversion.
|
// Convert continues a conversion.
|
||||||
func (s *scope) Convert(src, dest interface{}, flags FieldMatchingFlags) error {
|
func (s *scope) Convert(src, dest interface{}, flags FieldMatchingFlags) error {
|
||||||
return s.converter.Convert(src, dest, flags, s.meta)
|
return s.converter.Convert(src, dest, flags, s.meta)
|
||||||
|
@ -155,6 +187,19 @@ func (s *scope) Meta() *Meta {
|
||||||
return s.meta
|
return s.meta
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// describe prints the path to get to the current (source, dest) values.
|
||||||
|
func (s *scope) describe() (src, dest string) {
|
||||||
|
return s.srcStack.describe(), s.destStack.describe()
|
||||||
|
}
|
||||||
|
|
||||||
|
// error makes an error that includes information about where we were in the objects
|
||||||
|
// we were asked to convert.
|
||||||
|
func (s *scope) error(message string, args ...interface{}) error {
|
||||||
|
srcPath, destPath := s.describe()
|
||||||
|
where := fmt.Sprintf("converting %v to %v: ", srcPath, destPath)
|
||||||
|
return fmt.Errorf(where+message, args...)
|
||||||
|
}
|
||||||
|
|
||||||
// Register registers a conversion func with the Converter. conversionFunc must take
|
// Register registers a conversion func with the Converter. conversionFunc must take
|
||||||
// three parameters: a pointer to the input type, a pointer to the output type, and
|
// three parameters: a pointer to the input type, a pointer to the output type, and
|
||||||
// a conversion.Scope (which should be used if recursive conversion calls are desired).
|
// a conversion.Scope (which should be used if recursive conversion calls are desired).
|
||||||
|
@ -292,7 +337,7 @@ func (c *Converter) convert(sv, dv reflect.Value, scope *scope) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if !scope.flags.IsSet(AllowDifferentFieldTypeNames) && c.NameFunc(dt) != c.NameFunc(st) {
|
if !scope.flags.IsSet(AllowDifferentFieldTypeNames) && c.NameFunc(dt) != c.NameFunc(st) {
|
||||||
return fmt.Errorf("can't convert %v to %v because type names don't match (%v, %v).", st, dt, c.NameFunc(st), c.NameFunc(dt))
|
return scope.error("type names don't match (%v, %v)", c.NameFunc(st), c.NameFunc(dt))
|
||||||
}
|
}
|
||||||
|
|
||||||
// This should handle all simple types.
|
// This should handle all simple types.
|
||||||
|
@ -325,6 +370,7 @@ func (c *Converter) convert(sv, dv reflect.Value, scope *scope) error {
|
||||||
}
|
}
|
||||||
dv.Set(reflect.MakeSlice(dt, sv.Len(), sv.Cap()))
|
dv.Set(reflect.MakeSlice(dt, sv.Len(), sv.Cap()))
|
||||||
for i := 0; i < sv.Len(); i++ {
|
for i := 0; i < sv.Len(); i++ {
|
||||||
|
scope.setIndices(i, i)
|
||||||
if err := c.convert(sv.Index(i), dv.Index(i), scope); err != nil {
|
if err := c.convert(sv.Index(i), dv.Index(i), scope); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -350,13 +396,14 @@ func (c *Converter) convert(sv, dv reflect.Value, scope *scope) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
dkv := reflect.New(dt.Elem()).Elem()
|
dkv := reflect.New(dt.Elem()).Elem()
|
||||||
|
scope.setKeys(sk.Interface(), dk.Interface())
|
||||||
if err := c.convert(sv.MapIndex(sk), dkv, scope); err != nil {
|
if err := c.convert(sv.MapIndex(sk), dkv, scope); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
dv.SetMapIndex(dk, dkv)
|
dv.SetMapIndex(dk, dkv)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("couldn't copy '%v' into '%v'", st, dt)
|
return scope.error("couldn't copy '%v' into '%v'; didn't understand types", st, dt)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -393,12 +440,14 @@ func (c *Converter) convertStruct(sv, dv reflect.Value, scope *scope) error {
|
||||||
case scope.flags.IsSet(IgnoreMissingFields):
|
case scope.flags.IsSet(IgnoreMissingFields):
|
||||||
// No error.
|
// No error.
|
||||||
case scope.flags.IsSet(SourceToDest):
|
case scope.flags.IsSet(SourceToDest):
|
||||||
return fmt.Errorf("%v not present in dest (%v to %v)", f.Name, st, dt)
|
return scope.error("%v not present in dest (%v to %v)", f.Name, st, dt)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("%v not present in src (%v to %v)", f.Name, st, dt)
|
return scope.error("%v not present in src (%v to %v)", f.Name, st, dt)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
scope.srcStack.top().key = f.Name
|
||||||
|
scope.srcStack.top().key = f.Name
|
||||||
if err := c.convert(sf, df, scope); err != nil {
|
if err := c.convert(sf, df, scope); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -425,6 +474,8 @@ func (c *Converter) checkStructField(fieldName string, sv, dv reflect.Value, sco
|
||||||
}
|
}
|
||||||
if sf.Type() == potentialSourceKey.fieldType {
|
if sf.Type() == potentialSourceKey.fieldType {
|
||||||
// Both the source's name and type matched, so copy.
|
// Both the source's name and type matched, so copy.
|
||||||
|
scope.srcStack.top().key = potentialSourceKey.fieldName
|
||||||
|
scope.destStack.top().key = fieldName
|
||||||
if err := c.convert(sf, df, scope); err != nil {
|
if err := c.convert(sf, df, scope); err != nil {
|
||||||
return true, err
|
return true, err
|
||||||
}
|
}
|
||||||
|
@ -448,6 +499,8 @@ func (c *Converter) checkStructField(fieldName string, sv, dv reflect.Value, sco
|
||||||
}
|
}
|
||||||
if df.Type() == potentialDestKey.fieldType {
|
if df.Type() == potentialDestKey.fieldType {
|
||||||
// Both the dest's name and type matched, so copy.
|
// Both the dest's name and type matched, so copy.
|
||||||
|
scope.srcStack.top().key = fieldName
|
||||||
|
scope.destStack.top().key = potentialDestKey.fieldName
|
||||||
if err := c.convert(sf, df, scope); err != nil {
|
if err := c.convert(sf, df, scope); err != nil {
|
||||||
return true, err
|
return true, err
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue