diff --git a/staging/src/k8s.io/client-go/rest/config.go b/staging/src/k8s.io/client-go/rest/config.go index 998a2f8b998..c58e9668b83 100644 --- a/staging/src/k8s.io/client-go/rest/config.go +++ b/staging/src/k8s.io/client-go/rest/config.go @@ -32,6 +32,9 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/apimachinery/pkg/runtime/serializer/cbor" + "k8s.io/client-go/features" "k8s.io/client-go/pkg/version" clientcmdapi "k8s.io/client-go/tools/clientcmd/api" "k8s.io/client-go/transport" @@ -672,3 +675,31 @@ func CopyConfig(config *Config) *Config { } return c } + +// CodecFactoryForGeneratedClient returns the provided CodecFactory if there are no enabled client +// feature gates affecting serialization. Otherwise, it constructs and returns a new CodecFactory +// from the provided Scheme. +// +// This is supported ONLY for use by clients generated with client-gen. The caller is responsible +// for ensuring that the CodecFactory argument was constructed using the Scheme argument. +func CodecFactoryForGeneratedClient(scheme *runtime.Scheme, codecs serializer.CodecFactory) serializer.CodecFactory { + if !features.TestOnlyFeatureGates.Enabled(features.TestOnlyClientAllowsCBOR) { + // NOTE: This assumes client-gen will not generate CBOR-enabled Codecs as long as + // the feature gate exists. + return codecs + } + + return serializer.NewCodecFactory(scheme, serializer.WithSerializer(func(creater runtime.ObjectCreater, typer runtime.ObjectTyper) runtime.SerializerInfo { + return runtime.SerializerInfo{ + MediaType: "application/cbor", + MediaTypeType: "application", + MediaTypeSubType: "cbor", + Serializer: cbor.NewSerializer(creater, typer), + StrictSerializer: cbor.NewSerializer(creater, typer, cbor.Strict(true)), + StreamSerializer: &runtime.StreamSerializerInfo{ + Framer: cbor.NewFramer(), + Serializer: cbor.NewSerializer(creater, typer, cbor.Transcode(false)), + }, + } + })) +} diff --git a/staging/src/k8s.io/code-generator/cmd/client-gen/generators/generator_for_group.go b/staging/src/k8s.io/code-generator/cmd/client-gen/generators/generator_for_group.go index e5915b67724..8196871753f 100644 --- a/staging/src/k8s.io/code-generator/cmd/client-gen/generators/generator_for_group.go +++ b/staging/src/k8s.io/code-generator/cmd/client-gen/generators/generator_for_group.go @@ -83,25 +83,26 @@ func (g *genGroup) GenerateType(c *generator.Context, t *types.Type, w io.Writer } schemePackage := path.Join(g.clientsetPackage, "scheme") m := map[string]interface{}{ - "version": g.version, - "groupName": groupName, - "GroupGoName": g.groupGoName, - "Version": namer.IC(g.version), - "types": g.types, - "apiPath": apiPath, - "httpClient": c.Universe.Type(types.Name{Package: "net/http", Name: "Client"}), - "schemaGroupVersion": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/runtime/schema", Name: "GroupVersion"}), - "runtimeAPIVersionInternal": c.Universe.Variable(types.Name{Package: "k8s.io/apimachinery/pkg/runtime", Name: "APIVersionInternal"}), - "restConfig": c.Universe.Type(types.Name{Package: "k8s.io/client-go/rest", Name: "Config"}), - "restDefaultKubernetesUserAgent": c.Universe.Function(types.Name{Package: "k8s.io/client-go/rest", Name: "DefaultKubernetesUserAgent"}), - "restRESTClientInterface": c.Universe.Type(types.Name{Package: "k8s.io/client-go/rest", Name: "Interface"}), - "RESTHTTPClientFor": c.Universe.Function(types.Name{Package: "k8s.io/client-go/rest", Name: "HTTPClientFor"}), - "restRESTClientFor": c.Universe.Function(types.Name{Package: "k8s.io/client-go/rest", Name: "RESTClientFor"}), - "restRESTClientForConfigAndClient": c.Universe.Function(types.Name{Package: "k8s.io/client-go/rest", Name: "RESTClientForConfigAndClient"}), - "SchemeGroupVersion": c.Universe.Variable(types.Name{Package: g.inputPackage, Name: "SchemeGroupVersion"}), - "SchemePrioritizedVersionsForGroup": c.Universe.Variable(types.Name{Package: schemePackage, Name: "Scheme.PrioritizedVersionsForGroup"}), - "Codecs": c.Universe.Variable(types.Name{Package: schemePackage, Name: "Codecs"}), - "CodecsWithoutConversion": c.Universe.Variable(types.Name{Package: schemePackage, Name: "Codecs.WithoutConversion"}), + "version": g.version, + "groupName": groupName, + "GroupGoName": g.groupGoName, + "Version": namer.IC(g.version), + "types": g.types, + "apiPath": apiPath, + "httpClient": c.Universe.Type(types.Name{Package: "net/http", Name: "Client"}), + "schemaGroupVersion": c.Universe.Type(types.Name{Package: "k8s.io/apimachinery/pkg/runtime/schema", Name: "GroupVersion"}), + "runtimeAPIVersionInternal": c.Universe.Variable(types.Name{Package: "k8s.io/apimachinery/pkg/runtime", Name: "APIVersionInternal"}), + "restConfig": c.Universe.Type(types.Name{Package: "k8s.io/client-go/rest", Name: "Config"}), + "restDefaultKubernetesUserAgent": c.Universe.Function(types.Name{Package: "k8s.io/client-go/rest", Name: "DefaultKubernetesUserAgent"}), + "restRESTClientInterface": c.Universe.Type(types.Name{Package: "k8s.io/client-go/rest", Name: "Interface"}), + "RESTHTTPClientFor": c.Universe.Function(types.Name{Package: "k8s.io/client-go/rest", Name: "HTTPClientFor"}), + "restRESTClientFor": c.Universe.Function(types.Name{Package: "k8s.io/client-go/rest", Name: "RESTClientFor"}), + "restRESTClientForConfigAndClient": c.Universe.Function(types.Name{Package: "k8s.io/client-go/rest", Name: "RESTClientForConfigAndClient"}), + "restCodecFactoryForGeneratedClient": c.Universe.Function(types.Name{Package: "k8s.io/client-go/rest", Name: "CodecFactoryForGeneratedClient"}), + "SchemeGroupVersion": c.Universe.Variable(types.Name{Package: g.inputPackage, Name: "SchemeGroupVersion"}), + "SchemePrioritizedVersionsForGroup": c.Universe.Variable(types.Name{Package: schemePackage, Name: "Scheme.PrioritizedVersionsForGroup"}), + "Codecs": c.Universe.Variable(types.Name{Package: schemePackage, Name: "Codecs"}), + "Scheme": c.Universe.Variable(types.Name{Package: schemePackage, Name: "Scheme"}), } sw.Do(groupInterfaceTemplate, m) sw.Do(groupClientTemplate, m) @@ -235,7 +236,7 @@ func setConfigDefaults(config *$.restConfig|raw$) error { gv := $.SchemePrioritizedVersionsForGroup|raw$("$.groupName$")[0] config.GroupVersion = &gv } - config.NegotiatedSerializer = $.Codecs|raw$ + config.NegotiatedSerializer = $.restCodecFactoryForGeneratedClient|raw$($.Scheme|raw$, $.Codecs|raw$) if config.QPS == 0 { config.QPS = 5 @@ -253,7 +254,7 @@ func setConfigDefaults(config *$.restConfig|raw$) error { gv := $.SchemeGroupVersion|raw$ config.GroupVersion = &gv config.APIPath = $.apiPath$ - config.NegotiatedSerializer = $.CodecsWithoutConversion|raw$() + config.NegotiatedSerializer = $.restCodecFactoryForGeneratedClient|raw$($.Scheme|raw$, $.Codecs|raw$).WithoutConversion() if config.UserAgent == "" { config.UserAgent = $.restDefaultKubernetesUserAgent|raw$()