From 437a2ad693f71c19cb3554871ad9333852bc1bc7 Mon Sep 17 00:00:00 2001 From: yongruilin Date: Tue, 22 Jul 2025 23:23:55 +0000 Subject: [PATCH] feat: Add func to export the supportedVersionedFormats Implemented GetUnrecognizedFormats to identify unrecognized formats in schemas based on compatibility version. Added unit tests to validate various scenarios, including recognized and unrecognized formats across different versions. --- .../pkg/apiserver/validation/formats.go | 16 ++++ .../pkg/apiserver/validation/formats_test.go | 83 +++++++++++++++++++ 2 files changed, 99 insertions(+) diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/validation/formats.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/validation/formats.go index f818010f1b7..c11f1c627a7 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/validation/formats.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/validation/formats.go @@ -105,6 +105,22 @@ func StripUnsupportedFormatsPostProcessorForVersion(compatibilityVersion *versio } } +// GetUnrecognizedFormats returns a list of unrecognized formats found in the given schema. +// It uses the same source of truth as StripUnsupportedFormatsPostProcessorForVersion. +func GetUnrecognizedFormats(schema *spec.Schema, compatibilityVersion *version.Version) []string { + var unrecognizedFormats []string + if len(schema.Format) == 0 { + return unrecognizedFormats + } + + normalized := strings.ReplaceAll(schema.Format, "-", "") // go-openapi default format name normalization + if !supportedFormatsAtVersion(compatibilityVersion).supported.Has(normalized) { + unrecognizedFormats = append(unrecognizedFormats, schema.Format) + } + + return unrecognizedFormats +} + type versionedFormats struct { introducedVersion *version.Version formats sets.Set[string] diff --git a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/validation/formats_test.go b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/validation/formats_test.go index c93a7f74d1d..7558444b218 100644 --- a/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/validation/formats_test.go +++ b/staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/validation/formats_test.go @@ -138,3 +138,86 @@ func TestSupportedFormats(t *testing.T) { }) } } + +func TestGetUnrecognizedFormats(t *testing.T) { + testCases := []struct { + name string + schema *spec.Schema + compatibilityVersion *version.Version + expectedFormats []string + }{ + { + name: "empty format", + schema: &spec.Schema{SchemaProps: spec.SchemaProps{Format: ""}}, + compatibilityVersion: version.MajorMinor(1, 0), + expectedFormats: []string{}, + }, + { + name: "recognized format at version 1.0", + schema: &spec.Schema{SchemaProps: spec.SchemaProps{Format: "email"}}, + compatibilityVersion: version.MajorMinor(1, 0), + expectedFormats: []string{}, + }, + { + name: "unrecognized format at version 1.0", + schema: &spec.Schema{SchemaProps: spec.SchemaProps{Format: "unknown-format"}}, + compatibilityVersion: version.MajorMinor(1, 0), + expectedFormats: []string{"unknown-format"}, + }, + { + name: "recognized format with normalization", + schema: &spec.Schema{SchemaProps: spec.SchemaProps{Format: "k8s-short-name"}}, + compatibilityVersion: version.MajorMinor(1, 34), + expectedFormats: []string{}, + }, + { + name: "unrecognized format with normalization", + schema: &spec.Schema{SchemaProps: spec.SchemaProps{Format: "k8s-long-name"}}, + compatibilityVersion: version.MajorMinor(1, 33), + expectedFormats: []string{"k8s-long-name"}, + }, + { + name: "format introduced in later version", + schema: &spec.Schema{SchemaProps: spec.SchemaProps{Format: "k8s-short-name"}}, + compatibilityVersion: version.MajorMinor(1, 0), + expectedFormats: []string{"k8s-short-name"}, + }, + { + name: "format with dash normalization", + schema: &spec.Schema{SchemaProps: spec.SchemaProps{Format: "k8sshortname"}}, + compatibilityVersion: version.MajorMinor(1, 34), + expectedFormats: []string{}, + }, + { + name: "recognized format at exact version", + schema: &spec.Schema{SchemaProps: spec.SchemaProps{Format: "uuid"}}, + compatibilityVersion: version.MajorMinor(1, 0), + expectedFormats: []string{}, + }, + { + name: "recognized format at higher version", + schema: &spec.Schema{SchemaProps: spec.SchemaProps{Format: "email"}}, + compatibilityVersion: version.MajorMinor(1, 35), + expectedFormats: []string{}, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + got := GetUnrecognizedFormats(tc.schema, tc.compatibilityVersion) + + if len(got) != len(tc.expectedFormats) { + t.Errorf("expected %d unrecognized formats, got %d", len(tc.expectedFormats), len(got)) + return + } + + // Convert to sets for comparison to handle order differences + gotSet := sets.New(got...) + expectedSet := sets.New(tc.expectedFormats...) + + if !gotSet.Equal(expectedSet) { + t.Errorf("expected unrecognized formats %v, got %v", tc.expectedFormats, got) + } + }) + } +}