Merge pull request #131616 from jpbetz/typeconverter-cleanup

Reorganize scheme type converter into apimachinery utils

Kubernetes-commit: 7cb2bd78b22c4ac8d9a401920fbcf7e2b240522d
This commit is contained in:
Kubernetes Publisher 2025-05-07 18:09:25 -07:00
commit 996ce6af9b
5 changed files with 7 additions and 67 deletions

View File

@ -73,6 +73,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
managedfields "k8s.io/apimachinery/pkg/util/managedfields"
admissionregistrationv1 "k8s.io/client-go/applyconfigurations/admissionregistration/v1"
admissionregistrationv1alpha1 "k8s.io/client-go/applyconfigurations/admissionregistration/v1alpha1"
admissionregistrationv1beta1 "k8s.io/client-go/applyconfigurations/admissionregistration/v1beta1"
@ -126,7 +127,6 @@ import (
applyconfigurationsstoragev1alpha1 "k8s.io/client-go/applyconfigurations/storage/v1alpha1"
applyconfigurationsstoragev1beta1 "k8s.io/client-go/applyconfigurations/storage/v1beta1"
applyconfigurationsstoragemigrationv1alpha1 "k8s.io/client-go/applyconfigurations/storagemigration/v1alpha1"
testing "k8s.io/client-go/testing"
)
// ForKind returns an apply configuration type for the given GroupVersionKind, or nil if no
@ -1941,6 +1941,6 @@ func ForKind(kind schema.GroupVersionKind) interface{} {
return nil
}
func NewTypeConverter(scheme *runtime.Scheme) *testing.TypeConverter {
return &testing.TypeConverter{Scheme: scheme, TypeResolver: internal.Parser()}
func NewTypeConverter(scheme *runtime.Scheme) managedfields.TypeConverter {
return managedfields.NewSchemeTypeConverter(scheme, internal.Parser())
}

2
go.mod
View File

@ -26,7 +26,7 @@ require (
google.golang.org/protobuf v1.36.5
gopkg.in/evanphx/json-patch.v4 v4.12.0
k8s.io/api v0.0.0-20250503031400-f7e72be095ee
k8s.io/apimachinery v0.0.0-20250506191157-e07849993d77
k8s.io/apimachinery v0.0.0-20250508031140-d56afd172ac5
k8s.io/klog/v2 v2.130.1
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff
k8s.io/utils v0.0.0-20250502105355-0f33e8f1c979

4
go.sum
View File

@ -148,8 +148,8 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.0.0-20250503031400-f7e72be095ee h1:+YExLdNpiASfnQXQfpyLIGIps0RcJPNt7NdiCVH8Bys=
k8s.io/api v0.0.0-20250503031400-f7e72be095ee/go.mod h1:AsuSCzGYZszSLf5GB+qx8FBGGirk0I/TZUkQJFsPRAQ=
k8s.io/apimachinery v0.0.0-20250506191157-e07849993d77 h1:bwypcAN4gpWZ8VRVrgr0tYmunGNRCD869R3/h5o2Qa4=
k8s.io/apimachinery v0.0.0-20250506191157-e07849993d77/go.mod h1:b+h1nads2hmyfwvvorkgHUriRTTaJ2p2mk0l03sESn8=
k8s.io/apimachinery v0.0.0-20250508031140-d56afd172ac5 h1:JVQ9c90KR8hQpxscK1za1B1u+iSl5FQa4yj8W0IkthQ=
k8s.io/apimachinery v0.0.0-20250508031140-d56afd172ac5/go.mod h1:b+h1nads2hmyfwvvorkgHUriRTTaJ2p2mk0l03sESn8=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20250318190949-c8a335a9a2ff h1:/usPimJzUKKu+m+TE36gUyGcf03XZEP0ZIKgKj35LS4=

View File

@ -19,7 +19,6 @@ package testing
import (
"fmt"
"reflect"
"sigs.k8s.io/structured-merge-diff/v4/typed"
"sigs.k8s.io/yaml"
"sort"
"strings"
@ -945,62 +944,3 @@ func assertOptionalSingleArgument[T any](arguments []T) (T, error) {
return a, fmt.Errorf("expected only one option argument but got %d", len(arguments))
}
}
type TypeResolver interface {
Type(openAPIName string) typed.ParseableType
}
type TypeConverter struct {
Scheme *runtime.Scheme
TypeResolver TypeResolver
}
func (tc TypeConverter) ObjectToTyped(obj runtime.Object, opts ...typed.ValidationOptions) (*typed.TypedValue, error) {
gvk := obj.GetObjectKind().GroupVersionKind()
name, err := tc.openAPIName(gvk)
if err != nil {
return nil, err
}
t := tc.TypeResolver.Type(name)
switch o := obj.(type) {
case *unstructured.Unstructured:
return t.FromUnstructured(o.UnstructuredContent(), opts...)
default:
return t.FromStructured(obj, opts...)
}
}
func (tc TypeConverter) TypedToObject(value *typed.TypedValue) (runtime.Object, error) {
vu := value.AsValue().Unstructured()
switch o := vu.(type) {
case map[string]interface{}:
return &unstructured.Unstructured{Object: o}, nil
default:
return nil, fmt.Errorf("failed to convert value to unstructured for type %T", vu)
}
}
func (tc TypeConverter) openAPIName(kind schema.GroupVersionKind) (string, error) {
example, err := tc.Scheme.New(kind)
if err != nil {
return "", err
}
rtype := reflect.TypeOf(example).Elem()
name := friendlyName(rtype.PkgPath() + "." + rtype.Name())
return name, nil
}
// This is a copy of openapi.friendlyName.
// TODO: consider introducing a shared version of this function in apimachinery.
func friendlyName(name string) string {
nameParts := strings.Split(name, "/")
// Reverse first part. e.g., io.k8s... instead of k8s.io...
if len(nameParts) > 0 && strings.Contains(nameParts[0], ".") {
parts := strings.Split(nameParts[0], ".")
for i, j := 0, len(parts)-1; i < j; i, j = i+1, j-1 {
parts[i], parts[j] = parts[j], parts[i]
}
nameParts[0] = strings.Join(parts, ".")
}
return strings.Join(nameParts, ".")
}

View File

@ -572,7 +572,7 @@ func configMapTypeConverter(scheme *runtime.Scheme) managedfields.TypeConverter
panic(fmt.Sprintf("Failed to parse schema: %v", err))
}
return TypeConverter{Scheme: scheme, TypeResolver: parser}
return managedfields.NewSchemeTypeConverter(scheme, parser)
}
var configMapTypedSchema = typed.YAMLObject(`types: