mirror of
https://github.com/kubernetes/kubernetes.git
synced 2026-02-03 20:40:26 -05:00
Merge pull request #136620 from yongruilin/master_vg-fix-fuzz
fix DeclarativeValidation fuzzing test panic and refactor subresource handlin
This commit is contained in:
commit
c8e45a3331
2 changed files with 42 additions and 5 deletions
|
|
@ -32,6 +32,7 @@ import (
|
|||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"sigs.k8s.io/randfill"
|
||||
)
|
||||
|
||||
// ValidateFunc is a function that runs validation.
|
||||
|
|
@ -89,6 +90,13 @@ func VerifyVersionedValidationEquivalence(t *testing.T, obj, old runtime.Object,
|
|||
if internalObj == nil {
|
||||
return
|
||||
}
|
||||
// We do fuzzing on the internal version of the object.
|
||||
// This is because custom fuzzing function are only
|
||||
// supported for internal objects.
|
||||
// Fuzz the internal object if a fuzzer is provided.
|
||||
if opts.Fuzzer != nil {
|
||||
opts.Fuzzer.Fill(internalObj)
|
||||
}
|
||||
if old == nil {
|
||||
runtimetest.RunValidationForEachVersion(t, legacyscheme.Scheme, []string{}, internalObj, accumulate, opts.IgnoreObjectConversionErrors, opts.SubResources...)
|
||||
} else {
|
||||
|
|
@ -101,6 +109,10 @@ func VerifyVersionedValidationEquivalence(t *testing.T, obj, old runtime.Object,
|
|||
if internalOld == nil {
|
||||
return
|
||||
}
|
||||
// Fuzz the internal old object if a fuzzer is provided.
|
||||
if opts.Fuzzer != nil {
|
||||
opts.Fuzzer.Fill(internalOld)
|
||||
}
|
||||
runtimetest.RunUpdateValidationForEachVersion(t, legacyscheme.Scheme, []string{}, internalObj, internalOld, accumulate, opts.IgnoreObjectConversionErrors, opts.SubResources...)
|
||||
}
|
||||
|
||||
|
|
@ -206,6 +218,9 @@ type validationOption struct {
|
|||
// IgnoreObjectConversions skips the tests if the conversion from the internal object
|
||||
// to the versioned object fails.
|
||||
IgnoreObjectConversionErrors bool
|
||||
|
||||
// Fuzzer is the fuzzer to use for generating test objects.
|
||||
Fuzzer *randfill.Filler
|
||||
}
|
||||
|
||||
func WithSubResources(subResources ...string) ValidationTestConfig {
|
||||
|
|
@ -226,6 +241,12 @@ func WithIgnoreObjectConversionErrors() ValidationTestConfig {
|
|||
}
|
||||
}
|
||||
|
||||
func WithFuzzer(fuzzer *randfill.Filler) ValidationTestConfig {
|
||||
return func(o *validationOption) {
|
||||
o.Fuzzer = fuzzer
|
||||
}
|
||||
}
|
||||
|
||||
// VerifyValidationEquivalence provides a helper for testing the migration from
|
||||
// hand-written imperative validation to declarative validation. It ensures that
|
||||
// the validation logic remains consistent before and after the feature is enabled.
|
||||
|
|
|
|||
|
|
@ -65,6 +65,18 @@ func TestVersionedValidationByFuzzing(t *testing.T) {
|
|||
{Group: "admissionregistration.k8s.io", Version: "v1alpha1"},
|
||||
}
|
||||
|
||||
// subresourceOnly specifies the subresource path for types that can only be validated
|
||||
// as subresources (e.g. autoscaling/Scale) and do not support root-level validation.
|
||||
// For GVKs not in this map, the test defaults to fuzzing the root resource ("").
|
||||
// Other resources with subresources (e.g. Pod status, exec) share validation logic with
|
||||
// the root resource, so fuzzing the root is sufficient to verify validation equivalence.
|
||||
subresourceOnly := map[schema.GroupVersionKind]string{
|
||||
{Group: "autoscaling", Version: "v1", Kind: "Scale"}: "scale",
|
||||
{Group: "autoscaling", Version: "v1beta1", Kind: "Scale"}: "scale",
|
||||
{Group: "autoscaling", Version: "v1beta2", Kind: "Scale"}: "scale",
|
||||
{Group: "autoscaling", Version: "v2", Kind: "Scale"}: "scale",
|
||||
}
|
||||
|
||||
fuzzIters := *roundtrip.FuzzIters / 10 // TODO: Find a better way to manage test running time
|
||||
f := fuzzer.FuzzerFor(FuzzerFuncs, rand.NewSource(rand.Int63()), legacyscheme.Codecs)
|
||||
|
||||
|
|
@ -77,7 +89,11 @@ func TestVersionedValidationByFuzzing(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("could not create a %v: %s", kind, err)
|
||||
}
|
||||
f.Fill(obj)
|
||||
|
||||
subresource := ""
|
||||
if specific, ok := subresourceOnly[gvk]; ok {
|
||||
subresource = specific
|
||||
}
|
||||
|
||||
var opts []ValidationTestConfig
|
||||
// TODO(API group level configuration): Consider configuring normalization rules at the
|
||||
|
|
@ -85,9 +101,9 @@ func TestVersionedValidationByFuzzing(t *testing.T) {
|
|||
// This would allow each API group to register its own normalization rules independently.
|
||||
allRules := append([]field.NormalizationRule{}, resourcevalidation.ResourceNormalizationRules...)
|
||||
allRules = append(allRules, nodevalidation.NodeNormalizationRules...)
|
||||
opts = append(opts, WithNormalizationRules(allRules...))
|
||||
if gv.Group == "autoscaling" {
|
||||
opts = append(opts, WithIgnoreObjectConversionErrors())
|
||||
opts = append(opts, WithNormalizationRules(allRules...), WithFuzzer(f))
|
||||
if subresource != "" {
|
||||
opts = append(opts, WithSubResources(subresource))
|
||||
}
|
||||
|
||||
VerifyVersionedValidationEquivalence(t, obj, nil, opts...)
|
||||
|
|
@ -96,7 +112,7 @@ func TestVersionedValidationByFuzzing(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("could not create a %v: %s", kind, err)
|
||||
}
|
||||
f.Fill(old)
|
||||
|
||||
VerifyVersionedValidationEquivalence(t, obj, old, opts...)
|
||||
}
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in a new issue