diff --git a/pkg/util/validation/field/BUILD b/pkg/util/validation/field/BUILD index 81339eb6499..91f2a6beca2 100644 --- a/pkg/util/validation/field/BUILD +++ b/pkg/util/validation/field/BUILD @@ -17,7 +17,10 @@ go_library( "path.go", ], tags = ["automanaged"], - deps = ["//pkg/util/errors:go_default_library"], + deps = [ + "//pkg/util/errors:go_default_library", + "//pkg/util/sets:go_default_library", + ], ) go_test( diff --git a/pkg/util/validation/field/errors.go b/pkg/util/validation/field/errors.go index b4a6c5cd598..227a49eea36 100644 --- a/pkg/util/validation/field/errors.go +++ b/pkg/util/validation/field/errors.go @@ -22,6 +22,7 @@ import ( "strings" utilerrors "k8s.io/kubernetes/pkg/util/errors" + "k8s.io/kubernetes/pkg/util/sets" ) // Error is an implementation of the 'error' interface, which represents a @@ -201,9 +202,15 @@ func NewErrorTypeMatcher(t ErrorType) utilerrors.Matcher { // ToAggregate converts the ErrorList into an errors.Aggregate. func (list ErrorList) ToAggregate() utilerrors.Aggregate { - errs := make([]error, len(list)) - for i := range list { - errs[i] = list[i] + errs := make([]error, 0, len(list)) + errorMsgs := sets.NewString() + for _, err := range list { + msg := fmt.Sprintf("%v", err) + if errorMsgs.Has(msg) { + continue + } + errorMsgs.Insert(msg) + errs = append(errs, err) } return utilerrors.NewAggregate(errs) } diff --git a/pkg/util/validation/field/errors_test.go b/pkg/util/validation/field/errors_test.go index da8baa37e36..023939c8f66 100644 --- a/pkg/util/validation/field/errors_test.go +++ b/pkg/util/validation/field/errors_test.go @@ -99,22 +99,46 @@ func TestErrorUsefulMessage(t *testing.T) { } func TestToAggregate(t *testing.T) { - testCases := []ErrorList{ - nil, - {}, - {Invalid(NewPath("f"), "v", "d")}, - {Invalid(NewPath("f"), "v", "d"), InternalError(NewPath(""), fmt.Errorf("e"))}, + testCases := struct { + ErrList []ErrorList + NumExpectedErrs []int + }{ + []ErrorList{ + nil, + {}, + {Invalid(NewPath("f"), "v", "d")}, + {Invalid(NewPath("f"), "v", "d"), Invalid(NewPath("f"), "v", "d")}, + {Invalid(NewPath("f"), "v", "d"), InternalError(NewPath(""), fmt.Errorf("e"))}, + }, + []int{ + 0, + 0, + 1, + 1, + 2, + }, } - for i, tc := range testCases { + + if len(testCases.ErrList) != len(testCases.NumExpectedErrs) { + t.Errorf("Mismatch: length of NumExpectedErrs does not match length of ErrList") + } + for i, tc := range testCases.ErrList { agg := tc.ToAggregate() + numErrs := 0 + + if agg != nil { + numErrs = len(agg.Errors()) + } + if numErrs != testCases.NumExpectedErrs[i] { + t.Errorf("[%d] Expected %d, got %d", i, testCases.NumExpectedErrs[i], numErrs) + } + if len(tc) == 0 { if agg != nil { t.Errorf("[%d] Expected nil, got %#v", i, agg) } } else if agg == nil { t.Errorf("[%d] Expected non-nil", i) - } else if len(tc) != len(agg.Errors()) { - t.Errorf("[%d] Expected %d, got %d", i, len(tc), len(agg.Errors())) } } }