Merge pull request #114800 from haoruan/feature-8976-spew-sprintf-refactor

Capture spew.Sprintf() with all our favorite config into a util func
This commit is contained in:
Kubernetes Prow Robot 2023-04-11 15:34:57 -07:00 committed by GitHub
commit d0fc9d16ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 418 additions and 82 deletions

View File

@ -20,9 +20,9 @@ import (
"reflect" "reflect"
"testing" "testing"
"github.com/davecgh/go-spew/spew" v1 "k8s.io/api/core/v1"
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/dump"
) )
func podRef(uid string) *v1.ObjectReference { func podRef(uid string) *v1.ObjectReference {
@ -458,7 +458,7 @@ func TestPackSubsets(t *testing.T) {
for _, tc := range testCases { for _, tc := range testCases {
result := RepackSubsets(tc.given) result := RepackSubsets(tc.given)
if !reflect.DeepEqual(result, SortSubsets(tc.expect)) { if !reflect.DeepEqual(result, SortSubsets(tc.expect)) {
t.Errorf("case %q: expected %s, got %s", tc.name, spew.Sprintf("%#v", SortSubsets(tc.expect)), spew.Sprintf("%#v", result)) t.Errorf("case %q: expected %s, got %s", tc.name, dump.Pretty(SortSubsets(tc.expect)), dump.Pretty(result))
} }
} }
} }

View File

@ -21,12 +21,12 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/davecgh/go-spew/spew"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts" "github.com/google/go-cmp/cmp/cmpopts"
"k8s.io/apimachinery/pkg/api/resource" "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/dump"
"k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/apimachinery/pkg/util/validation/field"
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
@ -2993,7 +2993,7 @@ func TestValidateDeploymentStatus(t *testing.T) {
errs := ValidateDeploymentStatus(&status, field.NewPath("status")) errs := ValidateDeploymentStatus(&status, field.NewPath("status"))
if hasErr := len(errs) > 0; hasErr != test.expectedErr { if hasErr := len(errs) > 0; hasErr != test.expectedErr {
errString := spew.Sprintf("%#v", errs) errString := dump.Pretty(errs)
t.Errorf("%s: expected error: %t, got error: %t\nerrors: %s", test.name, test.expectedErr, hasErr, errString) t.Errorf("%s: expected error: %t, got error: %t\nerrors: %s", test.name, test.expectedErr, hasErr, errString)
} }
} }
@ -3064,7 +3064,7 @@ func TestValidateDeploymentStatusUpdate(t *testing.T) {
errs := ValidateDeploymentStatusUpdate(to, from) errs := ValidateDeploymentStatusUpdate(to, from)
if hasErr := len(errs) > 0; hasErr != test.expectedErr { if hasErr := len(errs) > 0; hasErr != test.expectedErr {
errString := spew.Sprintf("%#v", errs) errString := dump.Pretty(errs)
t.Errorf("%s: expected error: %t, got error: %t\nerrors: %s", test.name, test.expectedErr, hasErr, errString) t.Errorf("%s: expected error: %t, got error: %t\nerrors: %s", test.name, test.expectedErr, hasErr, errString)
} }
} }

View File

@ -18,11 +18,11 @@ package state
import ( import (
"encoding/json" "encoding/json"
"fmt"
"hash/fnv" "hash/fnv"
"strings" "strings"
"github.com/davecgh/go-spew/spew" "k8s.io/apimachinery/pkg/util/dump"
"k8s.io/kubernetes/pkg/kubelet/checkpointmanager" "k8s.io/kubernetes/pkg/kubelet/checkpointmanager"
"k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checksum" "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checksum"
"k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors" "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors"
@ -102,21 +102,14 @@ func (cp *CPUManagerCheckpointV1) VerifyChecksum() error {
return nil return nil
} }
printer := spew.ConfigState{
Indent: " ",
SortKeys: true,
DisableMethods: true,
SpewKeys: true,
}
ck := cp.Checksum ck := cp.Checksum
cp.Checksum = 0 cp.Checksum = 0
object := printer.Sprintf("%#v", cp) object := dump.ForHash(cp)
object = strings.Replace(object, "CPUManagerCheckpointV1", "CPUManagerCheckpoint", 1) object = strings.Replace(object, "CPUManagerCheckpointV1", "CPUManagerCheckpoint", 1)
cp.Checksum = ck cp.Checksum = ck
hash := fnv.New32a() hash := fnv.New32a()
printer.Fprintf(hash, "%v", object) fmt.Fprintf(hash, "%v", object)
if cp.Checksum != checksum.Checksum(hash.Sum32()) { if cp.Checksum != checksum.Checksum(hash.Sum32()) {
return errors.ErrCorruptCheckpoint return errors.ErrCorruptCheckpoint
} }

View File

@ -18,11 +18,11 @@ package checkpoint
import ( import (
"encoding/json" "encoding/json"
"fmt"
"hash/fnv" "hash/fnv"
"strings" "strings"
"github.com/davecgh/go-spew/spew" "k8s.io/apimachinery/pkg/util/dump"
"k8s.io/klog/v2" "k8s.io/klog/v2"
"k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checksum" "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/checksum"
"k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors" "k8s.io/kubernetes/pkg/kubelet/checkpointmanager/errors"
@ -48,18 +48,11 @@ type checkpointDataV1 struct {
// We need this special code path to be able to correctly validate the checksum k8s 1.19 wrote. // We need this special code path to be able to correctly validate the checksum k8s 1.19 wrote.
// credits to https://github.com/kubernetes/kubernetes/pull/102717/commits/353f93895118d2ffa2d59a29a1fbc225160ea1d6 // credits to https://github.com/kubernetes/kubernetes/pull/102717/commits/353f93895118d2ffa2d59a29a1fbc225160ea1d6
func (cp checkpointDataV1) checksum() checksum.Checksum { func (cp checkpointDataV1) checksum() checksum.Checksum {
printer := spew.ConfigState{ object := dump.ForHash(cp)
Indent: " ",
SortKeys: true,
DisableMethods: true,
SpewKeys: true,
}
object := printer.Sprintf("%#v", cp)
object = strings.Replace(object, "checkpointDataV1", "checkpointData", 1) object = strings.Replace(object, "checkpointDataV1", "checkpointData", 1)
object = strings.Replace(object, "PodDevicesEntryV1", "PodDevicesEntry", -1) object = strings.Replace(object, "PodDevicesEntryV1", "PodDevicesEntry", -1)
hash := fnv.New32a() hash := fnv.New32a()
printer.Fprintf(hash, "%v", object) fmt.Fprintf(hash, "%v", object)
return checksum.Checksum(hash.Sum32()) return checksum.Checksum(hash.Sum32())
} }

View File

@ -17,9 +17,10 @@ limitations under the License.
package hash package hash
import ( import (
"fmt"
"hash" "hash"
"github.com/davecgh/go-spew/spew" "k8s.io/apimachinery/pkg/util/dump"
) )
// DeepHashObject writes specified object to hash using the spew library // DeepHashObject writes specified object to hash using the spew library
@ -27,11 +28,5 @@ import (
// ensuring the hash does not change when a pointer changes. // ensuring the hash does not change when a pointer changes.
func DeepHashObject(hasher hash.Hash, objectToWrite interface{}) { func DeepHashObject(hasher hash.Hash, objectToWrite interface{}) {
hasher.Reset() hasher.Reset()
printer := spew.ConfigState{ fmt.Fprintf(hasher, "%v", dump.ForHash(objectToWrite))
Indent: " ",
SortKeys: true,
DisableMethods: true,
SpewKeys: true,
}
printer.Fprintf(hasher, "%#v", objectToWrite)
} }

View File

@ -21,7 +21,7 @@ import (
"hash/adler32" "hash/adler32"
"testing" "testing"
"github.com/davecgh/go-spew/spew" "k8s.io/apimachinery/pkg/util/dump"
) )
type A struct { type A struct {
@ -93,7 +93,7 @@ func TestDeepHashObject(t *testing.T) {
} }
func toString(obj interface{}) string { func toString(obj interface{}) string {
return spew.Sprintf("%#v", obj) return dump.Pretty(obj)
} }
type wheel struct { type wheel struct {

View File

@ -24,7 +24,6 @@ import (
"strings" "strings"
"testing" "testing"
"github.com/davecgh/go-spew/spew"
//nolint:staticcheck //iccheck // SA1019 Keep using deprecated module; it still seems to be maintained and the api of the recommended replacement differs //nolint:staticcheck //iccheck // SA1019 Keep using deprecated module; it still seems to be maintained and the api of the recommended replacement differs
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
fuzz "github.com/google/gofuzz" fuzz "github.com/google/gofuzz"
@ -41,6 +40,7 @@ import (
"k8s.io/apimachinery/pkg/runtime/serializer/json" "k8s.io/apimachinery/pkg/runtime/serializer/json"
"k8s.io/apimachinery/pkg/runtime/serializer/protobuf" "k8s.io/apimachinery/pkg/runtime/serializer/protobuf"
"k8s.io/apimachinery/pkg/util/diff" "k8s.io/apimachinery/pkg/util/diff"
"k8s.io/apimachinery/pkg/util/dump"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
) )
@ -299,7 +299,6 @@ func roundTripOfExternalType(t *testing.T, scheme *runtime.Scheme, codecFactory
// //
// external -> json/protobuf -> external. // external -> json/protobuf -> external.
func roundTrip(t *testing.T, scheme *runtime.Scheme, codec runtime.Codec, object runtime.Object) { func roundTrip(t *testing.T, scheme *runtime.Scheme, codec runtime.Codec, object runtime.Object) {
printer := spew.ConfigState{DisableMethods: true}
original := object original := object
// deep copy the original object // deep copy the original object
@ -307,8 +306,8 @@ func roundTrip(t *testing.T, scheme *runtime.Scheme, codec runtime.Codec, object
name := reflect.TypeOf(object).Elem().Name() name := reflect.TypeOf(object).Elem().Name()
if !apiequality.Semantic.DeepEqual(original, object) { if !apiequality.Semantic.DeepEqual(original, object) {
t.Errorf("%v: DeepCopy altered the object, diff: %v", name, diff.ObjectReflectDiff(original, object)) t.Errorf("%v: DeepCopy altered the object, diff: %v", name, diff.ObjectReflectDiff(original, object))
t.Errorf("%s", spew.Sdump(original)) t.Errorf("%s", dump.Pretty(original))
t.Errorf("%s", spew.Sdump(object)) t.Errorf("%s", dump.Pretty(object))
return return
} }
@ -316,9 +315,9 @@ func roundTrip(t *testing.T, scheme *runtime.Scheme, codec runtime.Codec, object
data, err := runtime.Encode(codec, object) data, err := runtime.Encode(codec, object)
if err != nil { if err != nil {
if runtime.IsNotRegisteredError(err) { if runtime.IsNotRegisteredError(err) {
t.Logf("%v: not registered: %v (%s)", name, err, printer.Sprintf("%#v", object)) t.Logf("%v: not registered: %v (%s)", name, err, dump.Pretty(object))
} else { } else {
t.Errorf("%v: %v (%s)", name, err, printer.Sprintf("%#v", object)) t.Errorf("%v: %v (%s)", name, err, dump.Pretty(object))
} }
return return
} }
@ -335,9 +334,9 @@ func roundTrip(t *testing.T, scheme *runtime.Scheme, codec runtime.Codec, object
secondData, err := runtime.Encode(codec, object) secondData, err := runtime.Encode(codec, object)
if err != nil { if err != nil {
if runtime.IsNotRegisteredError(err) { if runtime.IsNotRegisteredError(err) {
t.Logf("%v: not registered: %v (%s)", name, err, printer.Sprintf("%#v", object)) t.Logf("%v: not registered: %v (%s)", name, err, dump.Pretty(object))
} else { } else {
t.Errorf("%v: %v (%s)", name, err, printer.Sprintf("%#v", object)) t.Errorf("%v: %v (%s)", name, err, dump.Pretty(object))
} }
return return
} }
@ -345,20 +344,20 @@ func roundTrip(t *testing.T, scheme *runtime.Scheme, codec runtime.Codec, object
// serialization to the wire must be stable to ensure that we don't write twice to the DB // serialization to the wire must be stable to ensure that we don't write twice to the DB
// when the object hasn't changed. // when the object hasn't changed.
if !bytes.Equal(data, secondData) { if !bytes.Equal(data, secondData) {
t.Errorf("%v: serialization is not stable: %s", name, printer.Sprintf("%#v", object)) t.Errorf("%v: serialization is not stable: %s", name, dump.Pretty(object))
} }
// decode (deserialize) the encoded data back into an object // decode (deserialize) the encoded data back into an object
obj2, err := runtime.Decode(codec, data) obj2, err := runtime.Decode(codec, data)
if err != nil { if err != nil {
t.Errorf("%v: %v\nCodec: %#v\nData: %s\nSource: %#v", name, err, codec, dataAsString(data), printer.Sprintf("%#v", object)) t.Errorf("%v: %v\nCodec: %#v\nData: %s\nSource: %#v", name, err, codec, dataAsString(data), dump.Pretty(object))
panic("failed") panic("failed")
} }
// ensure that the object produced from decoding the encoded data is equal // ensure that the object produced from decoding the encoded data is equal
// to the original object // to the original object
if !apiequality.Semantic.DeepEqual(original, obj2) { if !apiequality.Semantic.DeepEqual(original, obj2) {
t.Errorf("%v: diff: %v\nCodec: %#v\nSource:\n\n%#v\n\nEncoded:\n\n%s\n\nFinal:\n\n%#v", name, diff.ObjectReflectDiff(original, obj2), codec, printer.Sprintf("%#v", original), dataAsString(data), printer.Sprintf("%#v", obj2)) t.Errorf("%v: diff: %v\nCodec: %#v\nSource:\n\n%#v\n\nEncoded:\n\n%s\n\nFinal:\n\n%#v", name, diff.ObjectReflectDiff(original, obj2), codec, dump.Pretty(original), dataAsString(data), dump.Pretty(obj2))
return return
} }

View File

@ -23,8 +23,8 @@ import (
"strings" "strings"
"text/tabwriter" "text/tabwriter"
"github.com/davecgh/go-spew/spew"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"k8s.io/apimachinery/pkg/util/dump"
) )
// StringDiff diffs a and b and returns a human readable diff. // StringDiff diffs a and b and returns a human readable diff.
@ -75,13 +75,8 @@ func ObjectReflectDiff(a, b interface{}) string {
// ObjectGoPrintSideBySide prints a and b as textual dumps side by side, // ObjectGoPrintSideBySide prints a and b as textual dumps side by side,
// enabling easy visual scanning for mismatches. // enabling easy visual scanning for mismatches.
func ObjectGoPrintSideBySide(a, b interface{}) string { func ObjectGoPrintSideBySide(a, b interface{}) string {
s := spew.ConfigState{ sA := dump.Pretty(a)
Indent: " ", sB := dump.Pretty(b)
// Extra deep spew.
DisableMethods: true,
}
sA := s.Sdump(a)
sB := s.Sdump(b)
linesA := strings.Split(sA, "\n") linesA := strings.Split(sA, "\n")
linesB := strings.Split(sB, "\n") linesB := strings.Split(sB, "\n")

View File

@ -0,0 +1,54 @@
/*
Copyright 2021 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package dump
import (
"github.com/davecgh/go-spew/spew"
)
var prettyPrintConfig = &spew.ConfigState{
Indent: " ",
DisableMethods: true,
DisablePointerAddresses: true,
DisableCapacities: true,
}
// The config MUST NOT be changed because that could change the result of a hash operation
var prettyPrintConfigForHash = &spew.ConfigState{
Indent: " ",
SortKeys: true,
DisableMethods: true,
SpewKeys: true,
DisablePointerAddresses: true,
DisableCapacities: true,
}
// Pretty wrap the spew.Sdump with Indent, and disabled methods like error() and String()
// The output may change over time, so for guaranteed output please take more direct control
func Pretty(a interface{}) string {
return prettyPrintConfig.Sdump(a)
}
// ForHash keeps the original Spew.Sprintf format to ensure the same checksum
func ForHash(a interface{}) string {
return prettyPrintConfigForHash.Sprintf("%#v", a)
}
// OneLine outputs the object in one line
func OneLine(a interface{}) string {
return prettyPrintConfig.Sprintf("%#v", a)
}

View File

@ -0,0 +1,310 @@
/*
Copyright 2021 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package dump
import (
"fmt"
"testing"
)
func ptrint(i int) *int {
return &i
}
func ptrstr(s string) *string {
return &s
}
// custom type to test Stringer interface on non-pointer receiver.
type customString string
// String implements the Stringer interface for testing invocation
func (s customString) String() string {
return "custom string " + string(s)
}
// custom type to test error interface on non-pointer receiver.
type customError int
// Error implements the error interface for testing invocation
func (e customError) Error() string {
return fmt.Sprintf("custom error: %d", int(e))
}
// custom type to test Stringer interface on pointer receiver.
type pCustomString string
// String implements the Stringer interface for testing invocation
func (s *pCustomString) String() string {
return "custom string " + string(*s)
}
// custom type to test error interface on pointer receiver.
type pCustomError int
// Error implements the error interface for testing invocation
func (e *pCustomError) Error() string {
return fmt.Sprintf("custom error: %d", int(*e))
}
// embed is used to test embedded structures.
type embed struct {
s string
}
// embedwrap is used to test embedded structures.
type embedwrap struct {
embed
e *embed
}
func TestPretty(t *testing.T) {
tcs := customString("test")
tpcs := pCustomString("&test")
tce := customError(0)
tpce := pCustomError(0)
teb := embed{"test"}
tebw := embedwrap{teb, &teb}
testCases := []struct {
a interface{}
want string
}{
{int8(93), "(int8) 93\n"},
{int16(93), "(int16) 93\n"},
{int32(93), "(int32) 93\n"},
{int64(93), "(int64) 93\n"},
{int(-93), "(int) -93\n"},
{int8(-93), "(int8) -93\n"},
{int16(-93), "(int16) -93\n"},
{int32(-93), "(int32) -93\n"},
{int64(-93), "(int64) -93\n"},
{uint(93), "(uint) 93\n"},
{uint8(93), "(uint8) 93\n"},
{uint16(93), "(uint16) 93\n"},
{uint32(93), "(uint32) 93\n"},
{uint64(93), "(uint64) 93\n"},
{uintptr(93), "(uintptr) 0x5d\n"},
{ptrint(93), "(*int)(93)\n"},
{float32(93.76), "(float32) 93.76\n"},
{float64(93.76), "(float64) 93.76\n"},
{complex64(93i), "(complex64) (0+93i)\n"},
{complex128(93i), "(complex128) (0+93i)\n"},
{bool(true), "(bool) true\n"},
{bool(false), "(bool) false\n"},
{string("test"), "(string) (len=4) \"test\"\n"},
{ptrstr("test"), "(*string)((len=4) \"test\")\n"},
{[1]string{"arr"}, "([1]string) (len=1) {\n (string) (len=3) \"arr\"\n}\n"},
{[]string{"slice"}, "([]string) (len=1) {\n (string) (len=5) \"slice\"\n}\n"},
{tcs, "(dump.customString) (len=4) \"test\"\n"},
{&tcs, "(*dump.customString)((len=4) \"test\")\n"},
{tpcs, "(dump.pCustomString) (len=5) \"&test\"\n"},
{&tpcs, "(*dump.pCustomString)((len=5) \"&test\")\n"},
{tce, "(dump.customError) 0\n"},
{&tce, "(*dump.customError)(0)\n"},
{tpce, "(dump.pCustomError) 0\n"},
{&tpce, "(*dump.pCustomError)(0)\n"},
{
struct {
arr [1]string
slice []string
m map[string]int
}{
[1]string{"arr"},
[]string{"slice"},
map[string]int{"one": 1},
},
"(struct { arr [1]string; slice []string; m map[string]int }) {\n arr: ([1]string) (len=1) {\n (string) (len=3) \"arr\"\n },\n slice: ([]string) (len=1) {\n (string) (len=5) \"slice\"\n },\n m: (map[string]int) (len=1) {\n (string) (len=3) \"one\": (int) 1\n }\n}\n",
},
{teb, "(dump.embed) {\n s: (string) (len=4) \"test\"\n}\n"},
{tebw, "(dump.embedwrap) {\n embed: (dump.embed) {\n s: (string) (len=4) \"test\"\n },\n e: (*dump.embed)({\n s: (string) (len=4) \"test\"\n })\n}\n"},
{map[string]int{}, "(map[string]int) {\n}\n"},
{map[string]int{"one": 1}, "(map[string]int) (len=1) {\n (string) (len=3) \"one\": (int) 1\n}\n"},
{map[string]interface{}{"one": 1}, "(map[string]interface {}) (len=1) {\n (string) (len=3) \"one\": (int) 1\n}\n"},
{map[string]customString{"key": tcs}, "(map[string]dump.customString) (len=1) {\n (string) (len=3) \"key\": (dump.customString) (len=4) \"test\"\n}\n"},
{map[string]customError{"key": tce}, "(map[string]dump.customError) (len=1) {\n (string) (len=3) \"key\": (dump.customError) 0\n}\n"},
{map[string]embed{"key": teb}, "(map[string]dump.embed) (len=1) {\n (string) (len=3) \"key\": (dump.embed) {\n s: (string) (len=4) \"test\"\n }\n}\n"},
{map[string]embedwrap{"key": tebw}, "(map[string]dump.embedwrap) (len=1) {\n (string) (len=3) \"key\": (dump.embedwrap) {\n embed: (dump.embed) {\n s: (string) (len=4) \"test\"\n },\n e: (*dump.embed)({\n s: (string) (len=4) \"test\"\n })\n }\n}\n"},
}
for i, tc := range testCases {
s := Pretty(tc.a)
if tc.want != s {
t.Errorf("[%d]:\n\texpected %q\n\tgot %q", i, tc.want, s)
}
}
}
func TestForHash(t *testing.T) {
tcs := customString("test")
tpcs := pCustomString("&test")
tce := customError(0)
tpce := pCustomError(0)
teb := embed{"test"}
tebw := embedwrap{teb, &teb}
testCases := []struct {
a interface{}
want string
}{
{int8(93), "(int8)93"},
{int16(93), "(int16)93"},
{int32(93), "(int32)93"},
{int64(93), "(int64)93"},
{int(-93), "(int)-93"},
{int8(-93), "(int8)-93"},
{int16(-93), "(int16)-93"},
{int32(-93), "(int32)-93"},
{int64(-93), "(int64)-93"},
{uint(93), "(uint)93"},
{uint8(93), "(uint8)93"},
{uint16(93), "(uint16)93"},
{uint32(93), "(uint32)93"},
{uint64(93), "(uint64)93"},
{uintptr(93), "(uintptr)0x5d"},
{ptrint(93), "(*int)93"},
{float32(93.76), "(float32)93.76"},
{float64(93.76), "(float64)93.76"},
{complex64(93i), "(complex64)(0+93i)"},
{complex128(93i), "(complex128)(0+93i)"},
{bool(true), "(bool)true"},
{bool(false), "(bool)false"},
{string("test"), "(string)test"},
{ptrstr("test"), "(*string)test"},
{[1]string{"arr"}, "([1]string)[arr]"},
{[]string{"slice"}, "([]string)[slice]"},
{tcs, "(dump.customString)test"},
{&tcs, "(*dump.customString)test"},
{tpcs, "(dump.pCustomString)&test"},
{&tpcs, "(*dump.pCustomString)&test"},
{tce, "(dump.customError)0"},
{&tce, "(*dump.customError)0"},
{tpce, "(dump.pCustomError)0"},
{&tpce, "(*dump.pCustomError)0"},
{
struct {
arr [1]string
slice []string
m map[string]int
}{
[1]string{"arr"},
[]string{"slice"},
map[string]int{"one": 1},
},
"(struct { arr [1]string; slice []string; m map[string]int }){arr:([1]string)[arr] slice:([]string)[slice] m:(map[string]int)map[one:1]}",
},
{teb, "(dump.embed){s:(string)test}"},
{tebw, "(dump.embedwrap){embed:(dump.embed){s:(string)test} e:(*dump.embed){s:(string)test}}"},
{map[string]int{}, "(map[string]int)map[]"},
{map[string]int{"one": 1, "two": 2}, "(map[string]int)map[one:1 two:2]"},
{map[string]interface{}{"one": 1}, "(map[string]interface {})map[one:(int)1]"},
{map[string]customString{"key": tcs}, "(map[string]dump.customString)map[key:test]"},
{map[string]customError{"key": tce}, "(map[string]dump.customError)map[key:0]"},
{map[string]embed{"key": teb}, "(map[string]dump.embed)map[key:{s:(string)test}]"},
{map[string]embedwrap{"key": tebw}, "(map[string]dump.embedwrap)map[key:{embed:(dump.embed){s:(string)test} e:(*dump.embed){s:(string)test}}]"},
}
for i, tc := range testCases {
s := ForHash(tc.a)
if tc.want != s {
t.Errorf("[%d]:\n\texpected %q\n\tgot %q", i, tc.want, s)
}
}
}
func TestOneLine(t *testing.T) {
tcs := customString("test")
tpcs := pCustomString("&test")
tce := customError(0)
tpce := pCustomError(0)
teb := embed{"test"}
tebw := embedwrap{teb, &teb}
testCases := []struct {
a interface{}
want string
}{
{int8(93), "(int8)93"},
{int16(93), "(int16)93"},
{int32(93), "(int32)93"},
{int64(93), "(int64)93"},
{int(-93), "(int)-93"},
{int8(-93), "(int8)-93"},
{int16(-93), "(int16)-93"},
{int32(-93), "(int32)-93"},
{int64(-93), "(int64)-93"},
{uint(93), "(uint)93"},
{uint8(93), "(uint8)93"},
{uint16(93), "(uint16)93"},
{uint32(93), "(uint32)93"},
{uint64(93), "(uint64)93"},
{uintptr(93), "(uintptr)0x5d"},
{ptrint(93), "(*int)93"},
{float32(93.76), "(float32)93.76"},
{float64(93.76), "(float64)93.76"},
{complex64(93i), "(complex64)(0+93i)"},
{complex128(93i), "(complex128)(0+93i)"},
{bool(true), "(bool)true"},
{bool(false), "(bool)false"},
{string("test"), "(string)test"},
{ptrstr("test"), "(*string)test"},
{[1]string{"arr"}, "([1]string)[arr]"},
{[]string{"slice"}, "([]string)[slice]"},
{tcs, "(dump.customString)test"},
{&tcs, "(*dump.customString)test"},
{tpcs, "(dump.pCustomString)&test"},
{&tpcs, "(*dump.pCustomString)&test"},
{tce, "(dump.customError)0"},
{&tce, "(*dump.customError)0"},
{tpce, "(dump.pCustomError)0"},
{&tpce, "(*dump.pCustomError)0"},
{
struct {
arr [1]string
slice []string
m map[string]int
}{
[1]string{"arr"},
[]string{"slice"},
map[string]int{"one": 1},
},
"(struct { arr [1]string; slice []string; m map[string]int }){arr:([1]string)[arr] slice:([]string)[slice] m:(map[string]int)map[one:1]}",
},
{teb, "(dump.embed){s:(string)test}"},
{tebw, "(dump.embedwrap){embed:(dump.embed){s:(string)test} e:(*dump.embed){s:(string)test}}"},
{map[string]int{}, "(map[string]int)map[]"},
{map[string]int{"one": 1}, "(map[string]int)map[one:1]"},
{map[string]interface{}{"one": 1}, "(map[string]interface {})map[one:(int)1]"},
{map[string]customString{"key": tcs}, "(map[string]dump.customString)map[key:test]"},
{map[string]customError{"key": tce}, "(map[string]dump.customError)map[key:0]"},
{map[string]embed{"key": teb}, "(map[string]dump.embed)map[key:{s:(string)test}]"},
{map[string]embedwrap{"key": tebw}, "(map[string]dump.embedwrap)map[key:{embed:(dump.embed){s:(string)test} e:(*dump.embed){s:(string)test}}]"},
}
for i, tc := range testCases {
s := OneLine(tc.a)
if tc.want != s {
t.Errorf("[%d]:\n\texpected %q\n\tgot %q", i, tc.want, s)
}
}
}

View File

@ -20,7 +20,7 @@ import (
"fmt" "fmt"
"reflect" "reflect"
"github.com/davecgh/go-spew/spew" "k8s.io/apimachinery/pkg/util/dump"
"sigs.k8s.io/yaml" "sigs.k8s.io/yaml"
) )
@ -76,7 +76,7 @@ func ToYAMLOrError(v interface{}) string {
func toYAML(v interface{}) (string, error) { func toYAML(v interface{}) (string, error) {
y, err := yaml.Marshal(v) y, err := yaml.Marshal(v)
if err != nil { if err != nil {
return "", fmt.Errorf("yaml marshal failed:%v\n%v\n", err, spew.Sdump(v)) return "", fmt.Errorf("yaml marshal failed:%v\n%v\n", err, dump.Pretty(v))
} }
return string(y), nil return string(y), nil

View File

@ -32,12 +32,12 @@ import (
"sync" "sync"
"time" "time"
"github.com/davecgh/go-spew/spew"
"golang.org/x/term" "golang.org/x/term"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer" "k8s.io/apimachinery/pkg/runtime/serializer"
"k8s.io/apimachinery/pkg/util/dump"
utilnet "k8s.io/apimachinery/pkg/util/net" utilnet "k8s.io/apimachinery/pkg/util/net"
"k8s.io/client-go/pkg/apis/clientauthentication" "k8s.io/client-go/pkg/apis/clientauthentication"
"k8s.io/client-go/pkg/apis/clientauthentication/install" "k8s.io/client-go/pkg/apis/clientauthentication/install"
@ -81,8 +81,6 @@ func newCache() *cache {
return &cache{m: make(map[string]*Authenticator)} return &cache{m: make(map[string]*Authenticator)}
} }
var spewConfig = &spew.ConfigState{DisableMethods: true, Indent: " "}
func cacheKey(conf *api.ExecConfig, cluster *clientauthentication.Cluster) string { func cacheKey(conf *api.ExecConfig, cluster *clientauthentication.Cluster) string {
key := struct { key := struct {
conf *api.ExecConfig conf *api.ExecConfig
@ -91,7 +89,7 @@ func cacheKey(conf *api.ExecConfig, cluster *clientauthentication.Cluster) strin
conf: conf, conf: conf,
cluster: cluster, cluster: cluster,
} }
return spewConfig.Sprint(key) return dump.Pretty(key)
} }
type cache struct { type cache struct {

View File

@ -24,10 +24,9 @@ import (
"net/http" "net/http"
"time" "time"
"github.com/davecgh/go-spew/spew"
apierrors "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/dump"
"k8s.io/apimachinery/pkg/util/net" "k8s.io/apimachinery/pkg/util/net"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apimachinery/pkg/watch" "k8s.io/apimachinery/pkg/watch"
@ -191,7 +190,7 @@ func (rw *RetryWatcher) doReceive() (bool, time.Duration) {
errObject := apierrors.FromObject(event.Object) errObject := apierrors.FromObject(event.Object)
statusErr, ok := errObject.(*apierrors.StatusError) statusErr, ok := errObject.(*apierrors.StatusError)
if !ok { if !ok {
klog.Error(spew.Sprintf("Received an error which is not *metav1.Status but %#+v", event.Object)) klog.Error(fmt.Sprintf("Received an error which is not *metav1.Status but %s", dump.Pretty(event.Object)))
// Retry unknown errors // Retry unknown errors
return false, 0 return false, 0
} }
@ -220,7 +219,7 @@ func (rw *RetryWatcher) doReceive() (bool, time.Duration) {
// Log here so we have a record of hitting the unexpected error // Log here so we have a record of hitting the unexpected error
// and we can whitelist some error codes if we missed any that are expected. // and we can whitelist some error codes if we missed any that are expected.
klog.V(5).Info(spew.Sprintf("Retrying after unexpected error: %#+v", event.Object)) klog.V(5).Info(fmt.Sprintf("Retrying after unexpected error: %s", dump.Pretty(event.Object)))
// Retry // Retry
return false, statusDelay return false, statusDelay

View File

@ -24,7 +24,6 @@ import (
"strings" "strings"
"time" "time"
"github.com/davecgh/go-spew/spew"
"github.com/onsi/ginkgo/v2" "github.com/onsi/ginkgo/v2"
"github.com/onsi/gomega" "github.com/onsi/gomega"
"k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/fields"
@ -40,6 +39,7 @@ import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/dump"
"k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/intstr"
utilrand "k8s.io/apimachinery/pkg/util/rand" utilrand "k8s.io/apimachinery/pkg/util/rand"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
@ -626,7 +626,7 @@ func failureTrap(ctx context.Context, c clientset.Interface, ns string) {
for i := range deployments.Items { for i := range deployments.Items {
d := deployments.Items[i] d := deployments.Items[i]
framework.Logf(spew.Sprintf("Deployment %q:\n%+v\n", d.Name, d)) framework.Logf("Deployment %q:\n%s\n", d.Name, dump.Pretty(d))
_, allOldRSs, newRS, err := testutil.GetAllReplicaSets(&d, c) _, allOldRSs, newRS, err := testutil.GetAllReplicaSets(&d, c)
if err != nil { if err != nil {
framework.Logf("Could not list ReplicaSets for Deployment %q: %v", d.Name, err) framework.Logf("Could not list ReplicaSets for Deployment %q: %v", d.Name, err)
@ -650,7 +650,7 @@ func failureTrap(ctx context.Context, c clientset.Interface, ns string) {
return return
} }
for _, rs := range rss.Items { for _, rs := range rss.Items {
framework.Logf(spew.Sprintf("ReplicaSet %q:\n%+v\n", rs.Name, rs)) framework.Logf("ReplicaSet %q:\n%s\n", rs.Name, dump.Pretty(rs))
selector, err := metav1.LabelSelectorAsSelector(rs.Spec.Selector) selector, err := metav1.LabelSelectorAsSelector(rs.Spec.Selector)
if err != nil { if err != nil {
framework.Logf("failed to get selector of ReplicaSet %s: %v", rs.Name, err) framework.Logf("failed to get selector of ReplicaSet %s: %v", rs.Name, err)
@ -662,7 +662,7 @@ func failureTrap(ctx context.Context, c clientset.Interface, ns string) {
continue continue
} }
for _, pod := range podList.Items { for _, pod := range podList.Items {
framework.Logf(spew.Sprintf("pod: %q:\n%+v\n", pod.Name, pod)) framework.Logf("pod: %q:\n%s\n", pod.Name, dump.Pretty(pod))
} }
} }
} }

View File

@ -22,13 +22,13 @@ import (
"sync" "sync"
"time" "time"
"github.com/davecgh/go-spew/spew"
"github.com/onsi/ginkgo/v2" "github.com/onsi/ginkgo/v2"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
storagev1 "k8s.io/api/storage/v1" storagev1 "k8s.io/api/storage/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/dump"
"k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/watch" "k8s.io/apimachinery/pkg/watch"
clientset "k8s.io/client-go/kubernetes" clientset "k8s.io/client-go/kubernetes"
@ -205,7 +205,7 @@ func (t *volumePerformanceTestSuite) DefineTests(driver storageframework.TestDri
ginkgo.By("Calculating performance metrics for provisioning operations") ginkgo.By("Calculating performance metrics for provisioning operations")
createPerformanceStats(provisioningStats, l.options.ProvisioningOptions.Count, l.pvcs) createPerformanceStats(provisioningStats, l.options.ProvisioningOptions.Count, l.pvcs)
ginkgo.By(fmt.Sprintf("Validating performance metrics for provisioning operations against baseline %v", spew.Sdump(l.options.ProvisioningOptions.ExpectedMetrics))) ginkgo.By(fmt.Sprintf("Validating performance metrics for provisioning operations against baseline %v", dump.Pretty(l.options.ProvisioningOptions.ExpectedMetrics)))
errList := validatePerformanceStats(provisioningStats.operationMetrics, l.options.ProvisioningOptions.ExpectedMetrics) errList := validatePerformanceStats(provisioningStats.operationMetrics, l.options.ProvisioningOptions.ExpectedMetrics)
framework.ExpectNoError(errors.NewAggregate(errList), "while validating performance metrics") framework.ExpectNoError(errors.NewAggregate(errList), "while validating performance metrics")
}) })
@ -240,7 +240,7 @@ func createPerformanceStats(stats *performanceStats, provisionCount int, pvcs []
// validatePerformanceStats validates if test performance metrics meet the baseline target // validatePerformanceStats validates if test performance metrics meet the baseline target
func validatePerformanceStats(operationMetrics *storageframework.Metrics, baselineMetrics *storageframework.Metrics) []error { func validatePerformanceStats(operationMetrics *storageframework.Metrics, baselineMetrics *storageframework.Metrics) []error {
var errList []error var errList []error
framework.Logf("Metrics to evaluate: %+v", spew.Sdump(operationMetrics)) framework.Logf("Metrics to evaluate: %+v", dump.Pretty(operationMetrics))
if operationMetrics.AvgLatency > baselineMetrics.AvgLatency { if operationMetrics.AvgLatency > baselineMetrics.AvgLatency {
err := fmt.Errorf("expected latency to be less than %v but calculated latency %v", baselineMetrics.AvgLatency, operationMetrics.AvgLatency) err := fmt.Errorf("expected latency to be less than %v but calculated latency %v", baselineMetrics.AvgLatency, operationMetrics.AvgLatency)

View File

@ -33,10 +33,10 @@ import (
"testing" "testing"
"time" "time"
"github.com/davecgh/go-spew/spew"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/dump"
"k8s.io/apimachinery/pkg/util/rand" "k8s.io/apimachinery/pkg/util/rand"
"k8s.io/apimachinery/pkg/util/sets" "k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
@ -612,7 +612,7 @@ func (is *informerSpy) waitForEvents(t *testing.T, wantEvents bool) {
if err != nil { if err != nil {
t.Fatalf("wanted no events, but got error: %v", err) t.Fatalf("wanted no events, but got error: %v", err)
} else { } else {
t.Fatalf("wanted no events, but got some: %s", spew.Sprintf("%#v", is)) t.Fatalf("wanted no events, but got some: %s", dump.Pretty(is))
} }
} }
} }

View File

@ -21,11 +21,10 @@ import (
"fmt" "fmt"
"time" "time"
"github.com/davecgh/go-spew/spew"
apps "k8s.io/api/apps/v1" apps "k8s.io/api/apps/v1"
"k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/dump"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
clientset "k8s.io/client-go/kubernetes" clientset "k8s.io/client-go/kubernetes"
podutil "k8s.io/kubernetes/pkg/api/v1/pod" podutil "k8s.io/kubernetes/pkg/api/v1/pod"
@ -37,7 +36,7 @@ type LogfFn func(format string, args ...interface{})
func LogReplicaSetsOfDeployment(deployment *apps.Deployment, allOldRSs []*apps.ReplicaSet, newRS *apps.ReplicaSet, logf LogfFn) { func LogReplicaSetsOfDeployment(deployment *apps.Deployment, allOldRSs []*apps.ReplicaSet, newRS *apps.ReplicaSet, logf LogfFn) {
if newRS != nil { if newRS != nil {
logf(spew.Sprintf("New ReplicaSet %q of Deployment %q:\n%+v", newRS.Name, deployment.Name, *newRS)) logf("New ReplicaSet %q of Deployment %q:\n%s", newRS.Name, deployment.Name, dump.Pretty(*newRS))
} else { } else {
logf("New ReplicaSet of Deployment %q is nil.", deployment.Name) logf("New ReplicaSet of Deployment %q is nil.", deployment.Name)
} }
@ -45,7 +44,7 @@ func LogReplicaSetsOfDeployment(deployment *apps.Deployment, allOldRSs []*apps.R
logf("All old ReplicaSets of Deployment %q:", deployment.Name) logf("All old ReplicaSets of Deployment %q:", deployment.Name)
} }
for i := range allOldRSs { for i := range allOldRSs {
logf(spew.Sprintf("%+v", *allOldRSs[i])) logf(dump.Pretty(*allOldRSs[i]))
} }
} }
@ -65,7 +64,7 @@ func LogPodsOfDeployment(c clientset.Interface, deployment *apps.Deployment, rsL
if podutil.IsPodAvailable(&pod, minReadySeconds, metav1.Now()) { if podutil.IsPodAvailable(&pod, minReadySeconds, metav1.Now()) {
availability = "available" availability = "available"
} }
logf(spew.Sprintf("Pod %q is %s:\n%+v", pod.Name, availability, pod)) logf("Pod %q is %s:\n%s", pod.Name, availability, dump.Pretty(pod))
} }
} }

1
vendor/modules.txt vendored
View File

@ -1355,6 +1355,7 @@ k8s.io/apimachinery/pkg/selection
k8s.io/apimachinery/pkg/types k8s.io/apimachinery/pkg/types
k8s.io/apimachinery/pkg/util/cache k8s.io/apimachinery/pkg/util/cache
k8s.io/apimachinery/pkg/util/diff k8s.io/apimachinery/pkg/util/diff
k8s.io/apimachinery/pkg/util/dump
k8s.io/apimachinery/pkg/util/duration k8s.io/apimachinery/pkg/util/duration
k8s.io/apimachinery/pkg/util/errors k8s.io/apimachinery/pkg/util/errors
k8s.io/apimachinery/pkg/util/framer k8s.io/apimachinery/pkg/util/framer