Skip to content

Commit 439d2f7

Browse files
committed
Wire serving codecs to CBOR feature gate.
Integration testing has to this point relied on patching serving codecs for built-in APIs. The test-only patching is removed and replaced by feature gated checks at runtime.
1 parent e2bf630 commit 439d2f7

File tree

19 files changed

+86
-112
lines changed

19 files changed

+86
-112
lines changed

pkg/registry/core/rest/storage_core_generic.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ import (
3333
"k8s.io/client-go/informers"
3434
restclient "k8s.io/client-go/rest"
3535

36+
"k8s.io/apimachinery/pkg/runtime/serializer"
37+
"k8s.io/apimachinery/pkg/runtime/serializer/cbor"
38+
"k8s.io/apiserver/pkg/features"
39+
utilfeature "k8s.io/apiserver/pkg/util/feature"
3640
"k8s.io/kubernetes/pkg/api/legacyscheme"
3741
api "k8s.io/kubernetes/pkg/apis/core"
3842
configmapstore "k8s.io/kubernetes/pkg/registry/core/configmap/storage"
@@ -68,6 +72,9 @@ func (c *GenericConfig) NewRESTStorage(apiResourceConfigSource serverstorage.API
6872
ParameterCodec: legacyscheme.ParameterCodec,
6973
NegotiatedSerializer: legacyscheme.Codecs,
7074
}
75+
if utilfeature.DefaultFeatureGate.Enabled(features.CBORServingAndStorage) {
76+
apiGroupInfo.NegotiatedSerializer = serializer.NewCodecFactory(legacyscheme.Scheme, serializer.WithSerializer(cbor.NewSerializerInfo))
77+
}
7178

7279
eventStorage, err := eventstore.NewREST(restOptionsGetter, uint64(c.EventTTL.Seconds()))
7380
if err != nil {

staging/src/k8s.io/apiextensions-apiserver/pkg/apiserver/customresource_handler.go

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -606,20 +606,6 @@ func (r *crdHandler) GetCustomResourceListerCollectionDeleter(crd *apiextensions
606606
return info.storages[info.storageVersion].CustomResource, nil
607607
}
608608

609-
func newCBORSerializerInfo(creater runtime.ObjectCreater, typer runtime.ObjectTyper) runtime.SerializerInfo {
610-
return runtime.SerializerInfo{
611-
MediaType: "application/cbor",
612-
MediaTypeType: "application",
613-
MediaTypeSubType: "cbor",
614-
Serializer: cbor.NewSerializer(creater, typer),
615-
StrictSerializer: cbor.NewSerializer(creater, typer, cbor.Strict(true)),
616-
StreamSerializer: &runtime.StreamSerializerInfo{
617-
Framer: cbor.NewFramer(),
618-
Serializer: cbor.NewSerializer(creater, typer, cbor.Transcode(false)),
619-
},
620-
}
621-
}
622-
623609
// getOrCreateServingInfoFor gets the CRD serving info for the given CRD UID if the key exists in the storage map.
624610
// Otherwise the function fetches the up-to-date CRD using the given CRD name and creates CRD serving info.
625611
func (r *crdHandler) getOrCreateServingInfoFor(uid types.UID, name string) (*crdInfo, error) {
@@ -914,7 +900,7 @@ func (r *crdHandler) getOrCreateServingInfoFor(uid types.UID, name string) (*crd
914900
}
915901

916902
if utilfeature.DefaultFeatureGate.Enabled(features.CBORServingAndStorage) {
917-
negotiatedSerializer.supportedMediaTypes = append(negotiatedSerializer.supportedMediaTypes, newCBORSerializerInfo(creator, typer))
903+
negotiatedSerializer.supportedMediaTypes = append(negotiatedSerializer.supportedMediaTypes, cbor.NewSerializerInfo(creator, typer))
918904
}
919905

920906
var standardSerializers []runtime.SerializerInfo
@@ -982,7 +968,7 @@ func (r *crdHandler) getOrCreateServingInfoFor(uid types.UID, name string) (*crd
982968
scaleScope.Subresource = "scale"
983969
var opts []serializer.CodecFactoryOptionsMutator
984970
if utilfeature.DefaultFeatureGate.Enabled(features.CBORServingAndStorage) {
985-
opts = append(opts, serializer.WithSerializer(newCBORSerializerInfo))
971+
opts = append(opts, serializer.WithSerializer(cbor.NewSerializerInfo))
986972
}
987973
scaleScope.Serializer = serializer.NewCodecFactory(scaleConverter.Scheme(), opts...)
988974
scaleScope.Kind = autoscalingv1.SchemeGroupVersion.WithKind("Scale")

staging/src/k8s.io/apimachinery/pkg/runtime/serializer/cbor/cbor.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,3 +372,18 @@ var selfDescribedCBOR = []byte{0xd9, 0xd9, 0xf7}
372372
func (s *serializer) RecognizesData(data []byte) (ok, unknown bool, err error) {
373373
return bytes.HasPrefix(data, selfDescribedCBOR), false, nil
374374
}
375+
376+
// NewSerializerInfo returns a default SerializerInfo for CBOR using the given creater and typer.
377+
func NewSerializerInfo(creater runtime.ObjectCreater, typer runtime.ObjectTyper) runtime.SerializerInfo {
378+
return runtime.SerializerInfo{
379+
MediaType: "application/cbor",
380+
MediaTypeType: "application",
381+
MediaTypeSubType: "cbor",
382+
Serializer: NewSerializer(creater, typer),
383+
StrictSerializer: NewSerializer(creater, typer, Strict(true)),
384+
StreamSerializer: &runtime.StreamSerializerInfo{
385+
Framer: NewFramer(),
386+
Serializer: NewSerializer(creater, typer, Transcode(false)),
387+
},
388+
}
389+
}

staging/src/k8s.io/apiserver/pkg/endpoints/handlers/delete.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import (
4040
"k8s.io/apiserver/pkg/endpoints/request"
4141
"k8s.io/apiserver/pkg/features"
4242
"k8s.io/apiserver/pkg/registry/rest"
43+
"k8s.io/apiserver/pkg/util/apihelpers"
4344
"k8s.io/apiserver/pkg/util/dryrun"
4445
utilfeature "k8s.io/apiserver/pkg/util/feature"
4546
"k8s.io/component-base/tracing"
@@ -85,15 +86,15 @@ func DeleteResource(r rest.GracefulDeleter, allowsOptions bool, scope *RequestSc
8586
}
8687
span.AddEvent("limitedReadBody succeeded", attribute.Int("len", len(body)))
8788
if len(body) > 0 {
88-
s, err := negotiation.NegotiateInputSerializer(req, false, metainternalversionscheme.Codecs)
89+
s, err := negotiation.NegotiateInputSerializer(req, false, apihelpers.GetMetaInternalVersionCodecs())
8990
if err != nil {
9091
scope.err(err, w, req)
9192
return
9293
}
9394
// For backwards compatibility, we need to allow existing clients to submit per group DeleteOptions
9495
// It is also allowed to pass a body with meta.k8s.io/v1.DeleteOptions
9596
defaultGVK := scope.MetaGroupVersion.WithKind("DeleteOptions")
96-
obj, gvk, err := metainternalversionscheme.Codecs.DecoderToVersion(s.Serializer, defaultGVK.GroupVersion()).Decode(body, &defaultGVK, options)
97+
obj, gvk, err := apihelpers.GetMetaInternalVersionCodecs().DecoderToVersion(s.Serializer, defaultGVK.GroupVersion()).Decode(body, &defaultGVK, options)
9798
if err != nil {
9899
scope.err(err, w, req)
99100
return
@@ -105,7 +106,7 @@ func DeleteResource(r rest.GracefulDeleter, allowsOptions bool, scope *RequestSc
105106
span.AddEvent("Decoded delete options")
106107

107108
objGV := gvk.GroupVersion()
108-
audit.LogRequestObject(req.Context(), obj, objGV, scope.Resource, scope.Subresource, metainternalversionscheme.Codecs)
109+
audit.LogRequestObject(req.Context(), obj, objGV, scope.Resource, scope.Subresource, apihelpers.GetMetaInternalVersionCodecs())
109110
span.AddEvent("Recorded the audit event")
110111
} else {
111112
if err := metainternalversionscheme.ParameterCodec.DecodeParameters(req.URL.Query(), scope.MetaGroupVersion, options); err != nil {
@@ -231,15 +232,15 @@ func DeleteCollection(r rest.CollectionDeleter, checkBody bool, scope *RequestSc
231232
}
232233
span.AddEvent("limitedReadBody succeeded", attribute.Int("len", len(body)))
233234
if len(body) > 0 {
234-
s, err := negotiation.NegotiateInputSerializer(req, false, metainternalversionscheme.Codecs)
235+
s, err := negotiation.NegotiateInputSerializer(req, false, apihelpers.GetMetaInternalVersionCodecs())
235236
if err != nil {
236237
scope.err(err, w, req)
237238
return
238239
}
239240
// For backwards compatibility, we need to allow existing clients to submit per group DeleteOptions
240241
// It is also allowed to pass a body with meta.k8s.io/v1.DeleteOptions
241242
defaultGVK := scope.MetaGroupVersion.WithKind("DeleteOptions")
242-
obj, gvk, err := metainternalversionscheme.Codecs.DecoderToVersion(s.Serializer, defaultGVK.GroupVersion()).Decode(body, &defaultGVK, options)
243+
obj, gvk, err := apihelpers.GetMetaInternalVersionCodecs().DecoderToVersion(s.Serializer, defaultGVK.GroupVersion()).Decode(body, &defaultGVK, options)
243244
if err != nil {
244245
scope.err(err, w, req)
245246
return
@@ -250,7 +251,7 @@ func DeleteCollection(r rest.CollectionDeleter, checkBody bool, scope *RequestSc
250251
}
251252

252253
objGV := gvk.GroupVersion()
253-
audit.LogRequestObject(req.Context(), obj, objGV, scope.Resource, scope.Subresource, metainternalversionscheme.Codecs)
254+
audit.LogRequestObject(req.Context(), obj, objGV, scope.Resource, scope.Subresource, apihelpers.GetMetaInternalVersionCodecs())
254255
} else {
255256
if err := metainternalversionscheme.ParameterCodec.DecodeParameters(req.URL.Query(), scope.MetaGroupVersion, options); err != nil {
256257
err = errors.NewBadRequest(err.Error())

staging/src/k8s.io/apiserver/pkg/endpoints/handlers/response.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ import (
4040
"k8s.io/apiserver/pkg/endpoints/metrics"
4141
endpointsrequest "k8s.io/apiserver/pkg/endpoints/request"
4242
"k8s.io/apiserver/pkg/storage"
43-
43+
"k8s.io/apiserver/pkg/util/apihelpers"
4444
"k8s.io/klog/v2"
4545
)
4646

@@ -281,7 +281,7 @@ func doTransformObject(ctx context.Context, obj runtime.Object, opts interface{}
281281
return asTable(ctx, obj, options, scope, target.GroupVersion())
282282

283283
default:
284-
accepted, _ := negotiation.MediaTypesForSerializer(metainternalversionscheme.Codecs)
284+
accepted, _ := negotiation.MediaTypesForSerializer(apihelpers.GetMetaInternalVersionCodecs())
285285
err := negotiation.NewNotAcceptableError(accepted)
286286
return nil, err
287287
}
@@ -315,7 +315,7 @@ func targetEncodingForTransform(scope *RequestScope, mediaType negotiation.Media
315315
case target == nil:
316316
case (target.Kind == "PartialObjectMetadata" || target.Kind == "PartialObjectMetadataList" || target.Kind == "Table") &&
317317
(target.GroupVersion() == metav1beta1.SchemeGroupVersion || target.GroupVersion() == metav1.SchemeGroupVersion):
318-
return *target, metainternalversionscheme.Codecs, true
318+
return *target, apihelpers.GetMetaInternalVersionCodecs(), true
319319
}
320320
return scope.Kind, scope.Serializer, false
321321
}

staging/src/k8s.io/apiserver/pkg/server/genericapiserver.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import (
3535
"k8s.io/apimachinery/pkg/runtime"
3636
"k8s.io/apimachinery/pkg/runtime/schema"
3737
"k8s.io/apimachinery/pkg/runtime/serializer"
38+
"k8s.io/apimachinery/pkg/runtime/serializer/cbor"
3839
"k8s.io/apimachinery/pkg/util/managedfields"
3940
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
4041
"k8s.io/apimachinery/pkg/util/sets"
@@ -51,6 +52,7 @@ import (
5152
"k8s.io/apiserver/pkg/server/healthz"
5253
"k8s.io/apiserver/pkg/server/routes"
5354
"k8s.io/apiserver/pkg/storageversion"
55+
utilfeature "k8s.io/apiserver/pkg/util/feature"
5456
restclient "k8s.io/client-go/rest"
5557
"k8s.io/component-base/featuregate"
5658
utilversion "k8s.io/component-base/version"
@@ -989,6 +991,9 @@ func (s *GenericAPIServer) newAPIGroupVersion(apiGroupInfo *APIGroupInfo, groupV
989991
// NewDefaultAPIGroupInfo returns an APIGroupInfo stubbed with "normal" values
990992
// exposed for easier composition from other packages
991993
func NewDefaultAPIGroupInfo(group string, scheme *runtime.Scheme, parameterCodec runtime.ParameterCodec, codecs serializer.CodecFactory) APIGroupInfo {
994+
if utilfeature.DefaultFeatureGate.Enabled(features.CBORServingAndStorage) {
995+
codecs = serializer.NewCodecFactory(scheme, serializer.WithSerializer(cbor.NewSerializerInfo))
996+
}
992997
return APIGroupInfo{
993998
PrioritizedVersions: scheme.PrioritizedVersionsForGroup(group),
994999
VersionedResourcesStorageMap: map[string]map[string]rest.Storage{},

staging/src/k8s.io/apiserver/pkg/util/apihelpers/helpers.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ import (
2020
"sort"
2121

2222
flowcontrol "k8s.io/api/flowcontrol/v1"
23+
metainternalversionscheme "k8s.io/apimachinery/pkg/apis/meta/internalversion/scheme"
24+
"k8s.io/apimachinery/pkg/runtime"
25+
"k8s.io/apimachinery/pkg/runtime/serializer"
26+
"k8s.io/apimachinery/pkg/runtime/serializer/cbor"
27+
"k8s.io/apiserver/pkg/features"
28+
utilfeature "k8s.io/apiserver/pkg/util/feature"
2329
)
2430

2531
// SetFlowSchemaCondition sets conditions.
@@ -98,3 +104,15 @@ func (s FlowSchemaSequence) Less(i, j int) bool {
98104
func (s FlowSchemaSequence) Swap(i, j int) {
99105
s[i], s[j] = s[j], s[i]
100106
}
107+
108+
var metaInternalVersionCodecsWithCBOR = serializer.NewCodecFactory(metainternalversionscheme.Scheme, serializer.WithSerializer(cbor.NewSerializerInfo))
109+
110+
// GetMetaInternalVersionCodecs returns a negotiated serializer that recognizes the types from
111+
// k8s.io/apimachinery/pkg/apis/meta/internalversion/scheme.Scheme. It will or will include a CBOR
112+
// serializer if CBOR is enabled.
113+
func GetMetaInternalVersionCodecs() runtime.NegotiatedSerializer {
114+
if utilfeature.DefaultFeatureGate.Enabled(features.CBORServingAndStorage) {
115+
return metaInternalVersionCodecsWithCBOR
116+
}
117+
return metainternalversionscheme.Codecs
118+
}

staging/src/k8s.io/client-go/rest/config.go

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -689,17 +689,5 @@ func CodecFactoryForGeneratedClient(scheme *runtime.Scheme, codecs serializer.Co
689689
return codecs
690690
}
691691

692-
return serializer.NewCodecFactory(scheme, serializer.WithSerializer(func(creater runtime.ObjectCreater, typer runtime.ObjectTyper) runtime.SerializerInfo {
693-
return runtime.SerializerInfo{
694-
MediaType: "application/cbor",
695-
MediaTypeType: "application",
696-
MediaTypeSubType: "cbor",
697-
Serializer: cbor.NewSerializer(creater, typer),
698-
StrictSerializer: cbor.NewSerializer(creater, typer, cbor.Strict(true)),
699-
StreamSerializer: &runtime.StreamSerializerInfo{
700-
Framer: cbor.NewFramer(),
701-
Serializer: cbor.NewSerializer(creater, typer, cbor.Transcode(false)),
702-
},
703-
}
704-
}))
692+
return serializer.NewCodecFactory(scheme, serializer.WithSerializer(cbor.NewSerializerInfo))
705693
}

test/integration/apiserver/admissionwebhook/admission_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,15 @@ import (
5252
"k8s.io/apimachinery/pkg/util/sets"
5353
"k8s.io/apimachinery/pkg/util/wait"
5454
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
55+
"k8s.io/apiserver/pkg/features"
56+
utilfeature "k8s.io/apiserver/pkg/util/feature"
5557
"k8s.io/client-go/dynamic"
5658
clientfeatures "k8s.io/client-go/features"
5759
clientfeaturestesting "k8s.io/client-go/features/testing"
5860
clientset "k8s.io/client-go/kubernetes"
5961
"k8s.io/client-go/rest"
6062
"k8s.io/client-go/util/retry"
63+
featuregatetesting "k8s.io/component-base/featuregate/testing"
6164
kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing"
6265
apisv1beta1 "k8s.io/kubernetes/pkg/apis/admissionregistration/v1beta1"
6366
"k8s.io/kubernetes/test/integration/etcd"
@@ -459,7 +462,7 @@ func TestWebhookAdmissionWithoutWatchCache(t *testing.T) {
459462
}
460463

461464
func TestWebhookAdmissionWithCBOR(t *testing.T) {
462-
framework.EnableCBORServingAndStorageForTest(t)
465+
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CBORServingAndStorage, true)
463466
clientfeaturestesting.SetFeatureDuringTest(t, clientfeatures.ClientsAllowCBOR, true)
464467
clientfeaturestesting.SetFeatureDuringTest(t, clientfeatures.ClientsPreferCBOR, true)
465468
testWebhookAdmission(t, false, func(t testing.TB, config *rest.Config) {

test/integration/apiserver/apiserver_test.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,6 @@ import (
6363
utilfeature "k8s.io/apiserver/pkg/util/feature"
6464
"k8s.io/client-go/discovery/cached/memory"
6565
"k8s.io/client-go/dynamic"
66-
clientfeatures "k8s.io/client-go/features"
67-
clientfeaturestesting "k8s.io/client-go/features/testing"
6866
clientset "k8s.io/client-go/kubernetes"
6967
appsv1 "k8s.io/client-go/kubernetes/typed/apps/v1"
7068
"k8s.io/client-go/metadata"
@@ -3367,9 +3365,6 @@ func TestDefaultStorageEncoding(t *testing.T) {
33673365
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, "AllAlpha", true)
33683366
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, "AllBeta", true)
33693367

3370-
// TODO: Remove this override when the codecs used for serving all built-in APIs are wired to the apiserver feature gate.
3371-
clientfeaturestesting.SetFeatureDuringTest(t, clientfeatures.ClientsPreferCBOR, false)
3372-
33733368
protobufRecognizer := protobuf.NewSerializer(runtime.NewScheme(), runtime.NewScheme())
33743369
var recognizersByGroup map[string]recognizer.RecognizingDecoder
33753370
{

0 commit comments

Comments
 (0)