diff --git a/staging/src/k8s.io/apimachinery/pkg/util/errors/errors.go b/staging/src/k8s.io/apimachinery/pkg/util/errors/errors.go index b05b6aee1aa..62a73f34ebe 100644 --- a/staging/src/k8s.io/apimachinery/pkg/util/errors/errors.go +++ b/staging/src/k8s.io/apimachinery/pkg/util/errors/errors.go @@ -71,23 +71,38 @@ func (agg aggregate) Error() string { } seenerrs := sets.NewString() result := "" - for _, err := range agg { + agg.visit(func(err error) { msg := err.Error() if seenerrs.Has(msg) { - continue + return } seenerrs.Insert(msg) if len(seenerrs) > 1 { result += ", " } result += msg - } + }) if len(seenerrs) == 1 { return result } return "[" + result + "]" } +func (agg aggregate) visit(f func(err error)) { + for _, err := range agg { + switch err := err.(type) { + case aggregate: + err.visit(f) + case Aggregate: + for _, nestedErr := range err.Errors() { + f(nestedErr) + } + default: + f(err) + } + } +} + // Errors is part of the Aggregate interface. func (agg aggregate) Errors() []error { return []error(agg) diff --git a/staging/src/k8s.io/apimachinery/pkg/util/errors/errors_test.go b/staging/src/k8s.io/apimachinery/pkg/util/errors/errors_test.go index 79edc5cfcf2..d70a4d51a0b 100644 --- a/staging/src/k8s.io/apimachinery/pkg/util/errors/errors_test.go +++ b/staging/src/k8s.io/apimachinery/pkg/util/errors/errors_test.go @@ -179,6 +179,38 @@ func TestDedupePluralAggregate(t *testing.T) { } } +func TestFlattenAndDedupeAggregate(t *testing.T) { + var slice []error = []error{fmt.Errorf("abc"), fmt.Errorf("abc"), NewAggregate([]error{fmt.Errorf("abc")})} + var agg Aggregate + + agg = NewAggregate(slice) + if agg == nil { + t.Errorf("expected non-nil") + } + if s := agg.Error(); s != "abc" { + t.Errorf("expected 'abc', got %q", s) + } + if s := agg.Errors(); len(s) != 3 { + t.Errorf("expected three-elements slice, got %#v", s) + } +} + +func TestFlattenAggregate(t *testing.T) { + var slice []error = []error{fmt.Errorf("abc"), fmt.Errorf("abc"), NewAggregate([]error{fmt.Errorf("abc"), fmt.Errorf("def"), NewAggregate([]error{fmt.Errorf("def"), fmt.Errorf("ghi")})})} + var agg Aggregate + + agg = NewAggregate(slice) + if agg == nil { + t.Errorf("expected non-nil") + } + if s := agg.Error(); s != "[abc, def, ghi]" { + t.Errorf("expected '[abc, def, ghi]', got %q", s) + } + if s := agg.Errors(); len(s) != 3 { + t.Errorf("expected three-elements slice, got %#v", s) + } +} + func TestFilterOut(t *testing.T) { testCases := []struct { err error