mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-07-17 20:00:07 +00:00
Add ignoreConversionErrors option to validation testing
This commit adds an 'IgnoreObjectConversionErrors' option to the validation testing framework in 'k8s.io/apimachinery' and exposes it via 'pkg/api/testing'. This is useful for fuzzing tests where we might want to skip object versions that cannot be converted from the internal version (e.g. due to missing fields or incompatible types in older versions) but still want to test validation for the versions that *can* be converted. The 'autoscaling' group versions are added to 'TestVersionedValidationByFuzzing' with this option enabled.
This commit is contained in:
@@ -89,7 +89,7 @@ func VerifyVersionedValidationEquivalence(t *testing.T, obj, old runtime.Object,
|
||||
return
|
||||
}
|
||||
if old == nil {
|
||||
runtimetest.RunValidationForEachVersion(t, legacyscheme.Scheme, []string{}, internalObj, accumulate, opts.SubResources...)
|
||||
runtimetest.RunValidationForEachVersion(t, legacyscheme.Scheme, []string{}, internalObj, accumulate, opts.IgnoreObjectConversionErrors, opts.SubResources...)
|
||||
} else {
|
||||
// Convert old versioned object to internal format before validation.
|
||||
// runtimetest.RunUpdateValidationForEachVersion requires unversioned (internal) objects as input.
|
||||
@@ -100,7 +100,7 @@ func VerifyVersionedValidationEquivalence(t *testing.T, obj, old runtime.Object,
|
||||
if internalOld == nil {
|
||||
return
|
||||
}
|
||||
runtimetest.RunUpdateValidationForEachVersion(t, legacyscheme.Scheme, []string{}, internalObj, internalOld, accumulate, opts.SubResources...)
|
||||
runtimetest.RunUpdateValidationForEachVersion(t, legacyscheme.Scheme, []string{}, internalObj, internalOld, accumulate, opts.IgnoreObjectConversionErrors, opts.SubResources...)
|
||||
}
|
||||
|
||||
// Make a copy so we can modify it.
|
||||
@@ -201,6 +201,9 @@ type validationOption struct {
|
||||
SubResources []string
|
||||
// NormalizationRules are the rules to apply to field paths before comparison.
|
||||
NormalizationRules []field.NormalizationRule
|
||||
|
||||
// IgnoreObjectConversions skips the tests if the conversion between object fails.
|
||||
IgnoreObjectConversionErrors bool
|
||||
}
|
||||
|
||||
func WithSubResources(subResources ...string) ValidationTestConfig {
|
||||
@@ -215,6 +218,12 @@ func WithNormalizationRules(rules ...field.NormalizationRule) ValidationTestConf
|
||||
}
|
||||
}
|
||||
|
||||
func WithIgnoreObjectConversionErrors() ValidationTestConfig {
|
||||
return func(o *validationOption) {
|
||||
o.IgnoreObjectConversionErrors = true
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
|
||||
@@ -47,6 +47,10 @@ func TestVersionedValidationByFuzzing(t *testing.T) {
|
||||
{Group: "node.k8s.io", Version: "v1beta1"},
|
||||
{Group: "node.k8s.io", Version: "v1"},
|
||||
{Group: "node.k8s.io", Version: "v1alpha1"},
|
||||
{Group: "autoscaling", Version: "v1"},
|
||||
{Group: "autoscaling", Version: "v1beta1"},
|
||||
{Group: "autoscaling", Version: "v1beta2"},
|
||||
{Group: "autoscaling", Version: "v2"},
|
||||
}
|
||||
|
||||
fuzzIters := *roundtrip.FuzzIters / 10 // TODO: Find a better way to manage test running time
|
||||
@@ -70,6 +74,7 @@ func TestVersionedValidationByFuzzing(t *testing.T) {
|
||||
allRules := append([]field.NormalizationRule{}, resourcevalidation.ResourceNormalizationRules...)
|
||||
allRules = append(allRules, nodevalidation.NodeNormalizationRules...)
|
||||
opts = append(opts, WithNormalizationRules(allRules...))
|
||||
opts = append(opts, WithIgnoreObjectConversionErrors())
|
||||
|
||||
VerifyVersionedValidationEquivalence(t, obj, nil, opts...)
|
||||
|
||||
|
||||
@@ -37,16 +37,16 @@ type VersionValidationRunner func(t *testing.T, gv string, versionValidationErro
|
||||
// errs = append(errs, versionValidationErrors...) // generated declarative validation
|
||||
// // Validate that the errors are what was expected for this test case.
|
||||
// })
|
||||
func RunValidationForEachVersion(t *testing.T, scheme *runtime.Scheme, options []string, unversioned runtime.Object, fn VersionValidationRunner, subresources ...string) {
|
||||
runValidation(t, scheme, options, unversioned, fn, subresources...)
|
||||
func RunValidationForEachVersion(t *testing.T, scheme *runtime.Scheme, options []string, unversioned runtime.Object, fn VersionValidationRunner, ignoreConversionErrors bool, subresources ...string) {
|
||||
runValidation(t, scheme, options, unversioned, fn, ignoreConversionErrors, subresources...)
|
||||
}
|
||||
|
||||
// RunUpdateValidationForEachVersion is like RunValidationForEachVersion but for update validation.
|
||||
func RunUpdateValidationForEachVersion(t *testing.T, scheme *runtime.Scheme, options []string, unversioned, unversionedOld runtime.Object, fn VersionValidationRunner, subresources ...string) {
|
||||
runUpdateValidation(t, scheme, options, unversioned, unversionedOld, fn, subresources...)
|
||||
func RunUpdateValidationForEachVersion(t *testing.T, scheme *runtime.Scheme, options []string, unversioned, unversionedOld runtime.Object, fn VersionValidationRunner, ignoreConversionErrors bool, subresources ...string) {
|
||||
runUpdateValidation(t, scheme, options, unversioned, unversionedOld, fn, ignoreConversionErrors, subresources...)
|
||||
}
|
||||
|
||||
func runValidation(t *testing.T, scheme *runtime.Scheme, options []string, unversioned runtime.Object, fn VersionValidationRunner, subresources ...string) {
|
||||
func runValidation(t *testing.T, scheme *runtime.Scheme, options []string, unversioned runtime.Object, fn VersionValidationRunner, ignoreConversionErrors bool, subresources ...string) {
|
||||
unversionedGVKs, _, err := scheme.ObjectKinds(unversioned)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -66,7 +66,9 @@ func runValidation(t *testing.T, scheme *runtime.Scheme, options []string, unver
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = scheme.Convert(unversioned, versioned, nil)
|
||||
if err != nil {
|
||||
if ignoreConversionErrors && err != nil {
|
||||
t.Skipf("Failed to convert object from internal type to %s: %v", gvk.Version, err)
|
||||
} else if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
fn(t, gv.String(), scheme.Validate(context.Background(), options, versioned, subresources...))
|
||||
@@ -76,7 +78,7 @@ func runValidation(t *testing.T, scheme *runtime.Scheme, options []string, unver
|
||||
}
|
||||
}
|
||||
|
||||
func runUpdateValidation(t *testing.T, scheme *runtime.Scheme, options []string, unversionedNew, unversionedOld runtime.Object, fn VersionValidationRunner, subresources ...string) {
|
||||
func runUpdateValidation(t *testing.T, scheme *runtime.Scheme, options []string, unversionedNew, unversionedOld runtime.Object, fn VersionValidationRunner, ignoreConversionErrors bool, subresources ...string) {
|
||||
unversionedGVKs, _, err := scheme.ObjectKinds(unversionedNew)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -96,10 +98,11 @@ func runUpdateValidation(t *testing.T, scheme *runtime.Scheme, options []string,
|
||||
t.Fatal(err)
|
||||
}
|
||||
err = scheme.Convert(unversionedNew, versionedNew, nil)
|
||||
if err != nil {
|
||||
if err != nil && ignoreConversionErrors {
|
||||
t.Skipf("Failed to convert object from internal type to %s: %v", gvk.Version, err)
|
||||
} else if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var versionedOld runtime.Object
|
||||
if unversionedOld != nil {
|
||||
versionedOld, err = scheme.New(gvk)
|
||||
@@ -108,7 +111,9 @@ func runUpdateValidation(t *testing.T, scheme *runtime.Scheme, options []string,
|
||||
}
|
||||
|
||||
err = scheme.Convert(unversionedOld, versionedOld, nil)
|
||||
if err != nil {
|
||||
if err != nil && ignoreConversionErrors {
|
||||
t.Skipf("Failed to convert object from internal type to %s: %v", gvk.Version, err)
|
||||
} else if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user