Merge pull request #131616 from jpbetz/typeconverter-cleanup

Reorganize scheme type converter into apimachinery utils
This commit is contained in:
Kubernetes Prow Robot
2025-05-07 18:09:25 -07:00
committed by GitHub
23 changed files with 357 additions and 151 deletions

View File

@@ -20,9 +20,9 @@ import (
"encoding/json"
"fmt"
"os"
"strings"
"k8s.io/kube-openapi/pkg/common"
"k8s.io/kube-openapi/pkg/util"
"k8s.io/kube-openapi/pkg/validation/spec"
"k8s.io/kubernetes/pkg/generated/openapi"
)
@@ -38,7 +38,7 @@ func main() {
func output() error {
refFunc := func(name string) spec.Ref {
return spec.MustCreateRef(fmt.Sprintf("#/definitions/%s", friendlyName(name)))
return spec.MustCreateRef(fmt.Sprintf("#/definitions/%s", util.ToRESTFriendlyName(name)))
}
defs := openapi.GetOpenAPIDefinitions(refFunc)
schemaDefs := make(map[string]spec.Schema, len(defs))
@@ -50,12 +50,12 @@ func output() error {
// the type.
if schema, ok := v.Schema.Extensions[common.ExtensionV2Schema]; ok {
if v2Schema, isOpenAPISchema := schema.(spec.Schema); isOpenAPISchema {
schemaDefs[friendlyName(k)] = v2Schema
schemaDefs[util.ToRESTFriendlyName(k)] = v2Schema
continue
}
}
schemaDefs[friendlyName(k)] = v.Schema
schemaDefs[util.ToRESTFriendlyName(k)] = v.Schema
}
data, err := json.Marshal(&spec.Swagger{
SwaggerProps: spec.SwaggerProps{
@@ -75,17 +75,3 @@ func output() error {
os.Stdout.Write(data)
return nil
}
// From k8s.io/apiserver/pkg/endpoints/openapi/openapi.go
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

@@ -24,7 +24,7 @@ import (
internal "k8s.io/apiextensions-apiserver/examples/client-go/pkg/client/applyconfiguration/internal"
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
testing "k8s.io/client-go/testing"
managedfields "k8s.io/apimachinery/pkg/util/managedfields"
)
// ForKind returns an apply configuration type for the given GroupVersionKind, or nil if no
@@ -43,6 +43,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())
}

View File

@@ -26,7 +26,7 @@ import (
internal "k8s.io/apiextensions-apiserver/pkg/client/applyconfiguration/internal"
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
testing "k8s.io/client-go/testing"
managedfields "k8s.io/apimachinery/pkg/util/managedfields"
)
// ForKind returns an apply configuration type for the given GroupVersionKind, or nil if no
@@ -111,6 +111,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())
}

View File

@@ -743,3 +743,67 @@ func (s *Scheme) Name() string {
// internalPackages are packages that ignored when creating a default reflector name. These packages are in the common
// call chains to NewReflector, so they'd be low entropy names for reflectors
var internalPackages = []string{"k8s.io/apimachinery/pkg/runtime/scheme.go"}
// ToOpenAPIDefinitionName returns the REST-friendly OpenAPI definition name known type identified by groupVersionKind.
// If the groupVersionKind does not identify a known type, an error is returned.
// The Version field of groupVersionKind is required, and the Group and Kind fields are required for unstructured.Unstructured
// types. If a required field is empty, an error is returned.
//
// The OpenAPI definition name is the canonical name of the type, with the group and version removed.
// For example, the OpenAPI definition name of Pod is `io.k8s.api.core.v1.Pod`.
//
// A known type that is registered as an unstructured.Unstructured type is treated as a custom resource and
// which has an OpenAPI definition name of the form `<reversed-group>.<version.<kind>`.
// For example, the OpenAPI definition name of `group: stable.example.com, version: v1, kind: Pod` is
// `com.example.stable.v1.Pod`.
func (s *Scheme) ToOpenAPIDefinitionName(groupVersionKind schema.GroupVersionKind) (string, error) {
if groupVersionKind.Version == "" { // Empty version is not allowed by New() so check it first to avoid a panic.
return "", fmt.Errorf("version is required on all types: %v", groupVersionKind)
}
example, err := s.New(groupVersionKind)
if err != nil {
return "", err
}
if _, ok := example.(Unstructured); ok {
if groupVersionKind.Group == "" || groupVersionKind.Kind == "" {
return "", fmt.Errorf("unable to convert GroupVersionKind with empty fields to unstructured type to an OpenAPI definition name: %v", groupVersionKind)
}
return reverseParts(groupVersionKind.Group) + "." + groupVersionKind.Version + "." + groupVersionKind.Kind, nil
}
rtype := reflect.TypeOf(example).Elem()
name := toOpenAPIDefinitionName(rtype.PkgPath() + "." + rtype.Name())
return name, nil
}
// toOpenAPIDefinitionName converts Golang package/type canonical name into REST friendly OpenAPI name.
// Input is expected to be `PkgPath + "." TypeName.
//
// Examples of REST friendly OpenAPI name:
//
// Input: k8s.io/api/core/v1.Pod
// Output: io.k8s.api.core.v1.Pod
//
// Input: k8s.io/api/core/v1
// Output: io.k8s.api.core.v1
//
// Input: csi.storage.k8s.io/v1alpha1.CSINodeInfo
// Output: io.k8s.storage.csi.v1alpha1.CSINodeInfo
//
// Note that this is a copy of ToRESTFriendlyName from k8s.io/kube-openapi/pkg/util. It is duplicated here to avoid
// a dependency on kube-openapi.
func toOpenAPIDefinitionName(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], ".") {
nameParts[0] = reverseParts(nameParts[0])
}
return strings.Join(nameParts, ".")
}
func reverseParts(dotSeparatedName string) string {
parts := strings.Split(dotSeparatedName, ".")
for i, j := 0, len(parts)-1; i < j; i, j = i+1, j-1 {
parts[i], parts[j] = parts[j], parts[i]
}
return strings.Join(parts, ".")
}

View File

@@ -27,11 +27,13 @@ import (
"github.com/google/go-cmp/cmp"
"k8s.io/apimachinery/pkg/api/operation"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/conversion"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/runtime/serializer"
runtimetesting "k8s.io/apimachinery/pkg/runtime/testing"
runtimetestingv1 "k8s.io/apimachinery/pkg/runtime/testing/v1"
"k8s.io/apimachinery/pkg/util/diff"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/sets"
@@ -1114,3 +1116,72 @@ type TestType2 struct {
func (TestType2) GetObjectKind() schema.ObjectKind { return schema.EmptyObjectKind }
func (TestType2) DeepCopyObject() runtime.Object { return nil }
func TestToOpenAPIDefinitionName(t *testing.T) {
testCases := []struct {
name string
registerGvk *schema.GroupVersionKind // defaults to gvk unless set
registerObj runtime.Object
gvk schema.GroupVersionKind
out string
wantErr error
}{
{
name: "built-registerObj type",
registerObj: &runtimetestingv1.ExternalSimple{},
gvk: schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Simple"},
out: "io.k8s.apimachinery.pkg.runtime.testing.v1.ExternalSimple",
},
{
name: "unstructured type",
registerObj: &unstructured.Unstructured{},
gvk: schema.GroupVersionKind{Group: "stable.example.com", Version: "v1", Kind: "CronTab"},
out: "com.example.stable.v1.CronTab",
},
{
name: "unregistered type: empty group",
registerObj: &unstructured.Unstructured{},
gvk: schema.GroupVersionKind{Version: "v1", Kind: "CronTab"},
wantErr: fmt.Errorf("unable to convert GroupVersionKind with empty fields to unstructured type to an OpenAPI definition name: %v", schema.GroupVersionKind{Version: "v1", Kind: "CronTab"}),
},
{
name: "unregistered type: empty version",
registerObj: &unstructured.Unstructured{},
registerGvk: &schema.GroupVersionKind{Group: "stable.example.com", Version: "v1", Kind: "CronTab"},
gvk: schema.GroupVersionKind{Group: "stable.example.com", Kind: "CronTab"},
wantErr: fmt.Errorf("version is required on all types: %v", schema.GroupVersionKind{Group: "stable.example.com", Kind: "CronTab"}),
},
{
name: "unregistered type: empty kind",
registerObj: &unstructured.Unstructured{},
gvk: schema.GroupVersionKind{Group: "stable.example.com", Version: "v1"},
wantErr: fmt.Errorf("unable to convert GroupVersionKind with empty fields to unstructured type to an OpenAPI definition name: %v", schema.GroupVersionKind{Group: "stable.example.com", Version: "v1"}),
},
}
for _, test := range testCases {
t.Run(test.name, func(t *testing.T) {
if test.registerGvk == nil {
test.registerGvk = &test.gvk
}
scheme := runtime.NewScheme()
scheme.AddKnownTypeWithName(*test.registerGvk, test.registerObj)
utilruntime.Must(runtimetesting.RegisterConversions(scheme))
out, err := scheme.ToOpenAPIDefinitionName(test.gvk)
if test.wantErr != nil {
if err == nil || err.Error() != test.wantErr.Error() {
t.Errorf("expected error: %v but got %v", test.wantErr, err)
}
return
}
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if out != test.out {
t.Errorf("expected %s, got %s", test.out, out)
}
})
}
}

View File

@@ -0,0 +1,19 @@
/*
Copyright 2025 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.
*/
// +k8s:deepcopy-gen=package
package v1

View File

@@ -0,0 +1,27 @@
/*
Copyright 2025 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 v1
import (
"k8s.io/apimachinery/pkg/runtime"
)
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
type ExternalSimple struct {
runtime.TypeMeta `json:",inline"`
TestString string `json:"testString"`
}

View File

@@ -0,0 +1,51 @@
//go:build !ignore_autogenerated
// +build !ignore_autogenerated
/*
Copyright 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.
*/
// Code generated by deepcopy-gen. DO NOT EDIT.
package v1
import (
runtime "k8s.io/apimachinery/pkg/runtime"
)
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ExternalSimple) DeepCopyInto(out *ExternalSimple) {
*out = *in
out.TypeMeta = in.TypeMeta
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalSimple.
func (in *ExternalSimple) DeepCopy() *ExternalSimple {
if in == nil {
return nil
}
out := new(ExternalSimple)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *ExternalSimple) DeepCopyObject() runtime.Object {
if c := in.DeepCopy(); c != nil {
return c
}
return nil
}

View File

@@ -0,0 +1,62 @@
/*
Copyright 2025 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 internal
import (
"fmt"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/structured-merge-diff/v4/typed"
)
type schemeTypeConverter struct {
scheme *runtime.Scheme
parser *typed.Parser
}
var _ TypeConverter = &schemeTypeConverter{}
// NewSchemeTypeConverter creates a TypeConverter that uses the provided scheme to
// convert between runtime.Objects and TypedValues.
func NewSchemeTypeConverter(scheme *runtime.Scheme, parser *typed.Parser) TypeConverter {
return &schemeTypeConverter{scheme: scheme, parser: parser}
}
func (tc schemeTypeConverter) ObjectToTyped(obj runtime.Object, opts ...typed.ValidationOptions) (*typed.TypedValue, error) {
gvk := obj.GetObjectKind().GroupVersionKind()
name, err := tc.scheme.ToOpenAPIDefinitionName(gvk)
if err != nil {
return nil, err
}
t := tc.parser.Type(name)
switch o := obj.(type) {
case *unstructured.Unstructured:
return t.FromUnstructured(o.UnstructuredContent(), opts...)
default:
return t.FromStructured(obj, opts...)
}
}
func (tc schemeTypeConverter) 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)
}
}

View File

@@ -17,6 +17,9 @@ limitations under the License.
package managedfields
import (
"sigs.k8s.io/structured-merge-diff/v4/typed"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/managedfields/internal"
"k8s.io/kube-openapi/pkg/validation/spec"
)
@@ -45,3 +48,9 @@ func NewDeducedTypeConverter() TypeConverter {
func NewTypeConverter(openapiSpec map[string]*spec.Schema, preserveUnknownFields bool) (TypeConverter, error) {
return internal.NewTypeConverter(openapiSpec, preserveUnknownFields)
}
// NewSchemeTypeConverter creates a TypeConverter that uses the provided scheme to
// convert between runtime.Objects and TypedValues.
func NewSchemeTypeConverter(scheme *runtime.Scheme, parser *typed.Parser) TypeConverter {
return internal.NewSchemeTypeConverter(scheme, parser)
}

View File

@@ -133,19 +133,6 @@ func gvkConvert(gvk schema.GroupVersionKind) v1.GroupVersionKind {
}
}
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, ".")
}
func typeName(t reflect.Type) string {
path := t.PkgPath()
if strings.Contains(path, "/vendor/") {
@@ -183,9 +170,9 @@ func NewDefinitionNamer(schemes ...*runtime.Scheme) *DefinitionNamer {
// GetDefinitionName returns the name and tags for a given definition
func (d *DefinitionNamer) GetDefinitionName(name string) (string, spec.Extensions) {
if groupVersionKinds, ok := d.typeGroupVersionKinds[name]; ok {
return friendlyName(name), spec.Extensions{
return util.ToRESTFriendlyName(name), spec.Extensions{
extensionGVK: groupVersionKinds.JSON(),
}
}
return friendlyName(name), nil
return util.ToRESTFriendlyName(name), nil
}

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())
}

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:

View File

@@ -26,6 +26,7 @@ import (
clientgentypes "k8s.io/code-generator/cmd/client-gen/types"
"k8s.io/gengo/v2/types"
"k8s.io/kube-openapi/pkg/util"
utilproto "k8s.io/kube-openapi/pkg/util/proto"
"k8s.io/kube-openapi/pkg/validation/spec"
)
@@ -62,7 +63,7 @@ func newTypeModels(openAPISchemaFilePath string, pkgTypes map[string]*types.Pack
tags := genclientTags(t)
hasApply := tags.HasVerb("apply") || tags.HasVerb("applyStatus")
if tags.GenerateClient && hasApply {
openAPIType := friendlyName(typeName(t))
openAPIType := util.ToRESTFriendlyName(typeName(t))
gvk := gv.WithKind(clientgentypes.Kind(t.Name.Name))
rootDefs[openAPIType] = openAPISchema.Definitions[openAPIType]
gvkToOpenAPIType[gvk] = openAPIType

View File

@@ -145,19 +145,6 @@ func GetTargets(context *generator.Context, args *args.Args) []generator.Target
return targetList
}
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, ".")
}
func typeName(t *types.Type) string {
typePackage := t.Name.Package
return fmt.Sprintf("%s.%s", typePackage, t.Name.Name)

View File

@@ -19,18 +19,19 @@ package generators
import "k8s.io/gengo/v2/types"
var (
fmtSprintf = types.Ref("fmt", "Sprintf")
syncOnce = types.Ref("sync", "Once")
applyConfiguration = types.Ref("k8s.io/apimachinery/pkg/runtime", "ApplyConfiguration")
groupVersionKind = types.Ref("k8s.io/apimachinery/pkg/runtime/schema", "GroupVersionKind")
typeMeta = types.Ref("k8s.io/apimachinery/pkg/apis/meta/v1", "TypeMeta")
objectMeta = types.Ref("k8s.io/apimachinery/pkg/apis/meta/v1", "ObjectMeta")
rawExtension = types.Ref("k8s.io/apimachinery/pkg/runtime", "RawExtension")
unknown = types.Ref("k8s.io/apimachinery/pkg/runtime", "Unknown")
extractInto = types.Ref("k8s.io/apimachinery/pkg/util/managedfields", "ExtractInto")
runtimeScheme = types.Ref("k8s.io/apimachinery/pkg/runtime", "Scheme")
smdNewParser = types.Ref("sigs.k8s.io/structured-merge-diff/v4/typed", "NewParser")
smdParser = types.Ref("sigs.k8s.io/structured-merge-diff/v4/typed", "Parser")
testingTypeConverter = types.Ref("k8s.io/client-go/testing", "TypeConverter")
yamlObject = types.Ref("sigs.k8s.io/structured-merge-diff/v4/typed", "YAMLObject")
fmtSprintf = types.Ref("fmt", "Sprintf")
syncOnce = types.Ref("sync", "Once")
applyConfiguration = types.Ref("k8s.io/apimachinery/pkg/runtime", "ApplyConfiguration")
groupVersionKind = types.Ref("k8s.io/apimachinery/pkg/runtime/schema", "GroupVersionKind")
typeMeta = types.Ref("k8s.io/apimachinery/pkg/apis/meta/v1", "TypeMeta")
objectMeta = types.Ref("k8s.io/apimachinery/pkg/apis/meta/v1", "ObjectMeta")
rawExtension = types.Ref("k8s.io/apimachinery/pkg/runtime", "RawExtension")
unknown = types.Ref("k8s.io/apimachinery/pkg/runtime", "Unknown")
extractInto = types.Ref("k8s.io/apimachinery/pkg/util/managedfields", "ExtractInto")
typeConverter = types.Ref("k8s.io/apimachinery/pkg/util/managedfields", "TypeConverter")
newSchemeTypeConverter = types.Ref("k8s.io/apimachinery/pkg/util/managedfields", "NewSchemeTypeConverter")
runtimeScheme = types.Ref("k8s.io/apimachinery/pkg/runtime", "Scheme")
smdNewParser = types.Ref("sigs.k8s.io/structured-merge-diff/v4/typed", "NewParser")
smdParser = types.Ref("sigs.k8s.io/structured-merge-diff/v4/typed", "Parser")
yamlObject = types.Ref("sigs.k8s.io/structured-merge-diff/v4/typed", "YAMLObject")
)

View File

@@ -142,17 +142,18 @@ func (g *utilGenerator) GenerateType(c *generator.Context, _ *types.Type, w io.W
"runtimeScheme": runtimeScheme,
"schemeGVs": schemeGVs,
"schemaGroupVersionKind": groupVersionKind,
"testingTypeConverter": testingTypeConverter,
"typeConverter": typeConverter,
"newSchemeTypeConverter": newSchemeTypeConverter,
}
sw.Do(forKindFunc, m)
sw.Do(typeConverter, m)
sw.Do(newTypeConverterFunc, m)
return sw.Error()
}
var typeConverter = `
func NewTypeConverter(scheme *{{.runtimeScheme|raw}}) *{{.testingTypeConverter|raw}} {
return &{{.testingTypeConverter|raw}}{Scheme: scheme, TypeResolver: {{.internalParser|raw}}()}
var newTypeConverterFunc = `
func NewTypeConverter(scheme *{{.runtimeScheme|raw}}) {{.typeConverter|raw}} {
return {{.newSchemeTypeConverter|raw}}(scheme, {{.internalParser|raw}}())
}
`

View File

@@ -21,7 +21,7 @@ package applyconfiguration
import (
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
testing "k8s.io/client-go/testing"
managedfields "k8s.io/apimachinery/pkg/util/managedfields"
v1 "k8s.io/code-generator/examples/HyphenGroup/apis/example/v1"
examplev1 "k8s.io/code-generator/examples/HyphenGroup/applyconfiguration/example/v1"
internal "k8s.io/code-generator/examples/HyphenGroup/applyconfiguration/internal"
@@ -45,6 +45,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())
}

View File

@@ -21,7 +21,7 @@ package applyconfiguration
import (
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
testing "k8s.io/client-go/testing"
managedfields "k8s.io/apimachinery/pkg/util/managedfields"
v1 "k8s.io/code-generator/examples/MixedCase/apis/example/v1"
examplev1 "k8s.io/code-generator/examples/MixedCase/applyconfiguration/example/v1"
internal "k8s.io/code-generator/examples/MixedCase/applyconfiguration/internal"
@@ -45,6 +45,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())
}

View File

@@ -21,7 +21,7 @@ package applyconfiguration
import (
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
testing "k8s.io/client-go/testing"
managedfields "k8s.io/apimachinery/pkg/util/managedfields"
v1 "k8s.io/code-generator/examples/crd/apis/conflicting/v1"
examplev1 "k8s.io/code-generator/examples/crd/apis/example/v1"
example2v1 "k8s.io/code-generator/examples/crd/apis/example2/v1"
@@ -73,6 +73,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())
}

View File

@@ -21,7 +21,7 @@ package applyconfiguration
import (
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
testing "k8s.io/client-go/testing"
managedfields "k8s.io/apimachinery/pkg/util/managedfields"
v1 "k8s.io/code-generator/examples/single/api/v1"
apiv1 "k8s.io/code-generator/examples/single/applyconfiguration/api/v1"
internal "k8s.io/code-generator/examples/single/applyconfiguration/internal"
@@ -45,6 +45,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())
}

View File

@@ -21,7 +21,7 @@ package applyconfiguration
import (
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
testing "k8s.io/client-go/testing"
managedfields "k8s.io/apimachinery/pkg/util/managedfields"
v1alpha1 "k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1"
v1beta1 "k8s.io/sample-apiserver/pkg/apis/wardle/v1beta1"
internal "k8s.io/sample-apiserver/pkg/generated/applyconfiguration/internal"
@@ -51,6 +51,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())
}