mirror of
https://github.com/k3s-io/kubernetes.git
synced 2026-07-18 04:54:54 +00:00
Explicit checking for supported and unsupported types, add test
This commit is contained in:
@@ -46,6 +46,7 @@ const (
|
||||
// from the supported media types list, so error messages only show actually supported types.
|
||||
type flagzCodecFactory struct {
|
||||
serializer.CodecFactory
|
||||
supportedMediaTypes []runtime.SerializerInfo
|
||||
}
|
||||
|
||||
type mux interface {
|
||||
@@ -64,9 +65,19 @@ func Install(m mux, componentName string, flagReader Reader, opts ...Option) {
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
utilruntime.Must(v1alpha1.AddToScheme(scheme))
|
||||
filteredCodecFactory, err := newFlagzCodecFactory(scheme, componentName, reg.reader)
|
||||
if err != nil {
|
||||
utilruntime.HandleError(err)
|
||||
}
|
||||
m.Handle(DefaultFlagzPath, handleFlagz(componentName, reg, filteredCodecFactory, negotiate.FlagzEndpointRestrictions{}))
|
||||
}
|
||||
|
||||
// newFlagzCodecFactory creates a codec factory with the standard serializers for flagz,
|
||||
// filtering out unsupported media types (e.g., protobuf).
|
||||
func newFlagzCodecFactory(scheme *runtime.Scheme, componentName string, flagReader Reader) (*flagzCodecFactory, error) {
|
||||
codecFactoryOpts := []serializer.CodecFactoryOptionsMutator{
|
||||
serializer.WithSerializer(func(_ runtime.ObjectCreater, _ runtime.ObjectTyper) runtime.SerializerInfo {
|
||||
textSerializer := flagzTextSerializer{componentName, reg.reader}
|
||||
textSerializer := flagzTextSerializer{componentName, flagReader}
|
||||
return runtime.SerializerInfo{
|
||||
MediaType: "text/plain",
|
||||
MediaTypeType: "text",
|
||||
@@ -83,21 +94,36 @@ func Install(m mux, componentName string, flagReader Reader, opts ...Option) {
|
||||
}
|
||||
|
||||
codecFactory := serializer.NewCodecFactory(scheme, codecFactoryOpts...)
|
||||
// Wrap to filter out unsupported media types (e.g., protobuf)
|
||||
filteredCodecFactory := &flagzCodecFactory{codecFactory}
|
||||
m.Handle(DefaultFlagzPath, handleFlagz(componentName, reg, filteredCodecFactory, negotiate.FlagzEndpointRestrictions{}))
|
||||
allTypes := codecFactory.SupportedMediaTypes()
|
||||
filtered := make([]runtime.SerializerInfo, 0, len(allTypes))
|
||||
|
||||
var unknownTypes []string
|
||||
for _, info := range allTypes {
|
||||
switch info.MediaType {
|
||||
// Supported media types
|
||||
case "text/plain", runtime.ContentTypeJSON, runtime.ContentTypeYAML, runtime.ContentTypeCBOR:
|
||||
filtered = append(filtered, info)
|
||||
// Unsupported media types
|
||||
case runtime.ContentTypeProtobuf:
|
||||
continue
|
||||
default:
|
||||
unknownTypes = append(unknownTypes, info.MediaType)
|
||||
}
|
||||
}
|
||||
|
||||
var err error
|
||||
if len(unknownTypes) > 0 {
|
||||
err = fmt.Errorf("flagz: unknown media type(s) %v, excluding from supported types", unknownTypes)
|
||||
}
|
||||
|
||||
return &flagzCodecFactory{
|
||||
CodecFactory: codecFactory,
|
||||
supportedMediaTypes: filtered,
|
||||
}, err
|
||||
}
|
||||
|
||||
func (f *flagzCodecFactory) SupportedMediaTypes() []runtime.SerializerInfo {
|
||||
allTypes := f.CodecFactory.SupportedMediaTypes()
|
||||
filtered := make([]runtime.SerializerInfo, 0, len(allTypes))
|
||||
for _, info := range allTypes {
|
||||
if info.MediaType == runtime.ContentTypeProtobuf {
|
||||
continue
|
||||
}
|
||||
filtered = append(filtered, info)
|
||||
}
|
||||
return filtered
|
||||
return f.supportedMediaTypes
|
||||
}
|
||||
|
||||
func handleFlagz(componentName string, reg *registry, serializer runtime.NegotiatedSerializer, restrictions negotiate.FlagzEndpointRestrictions) http.HandlerFunc {
|
||||
|
||||
@@ -27,7 +27,9 @@ import (
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/spf13/pflag"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
cbor "k8s.io/apimachinery/pkg/runtime/serializer/cbor/direct"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
cbordirect "k8s.io/apimachinery/pkg/runtime/serializer/cbor/direct"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apiserver/pkg/features"
|
||||
v1alpha1 "k8s.io/apiserver/pkg/server/flagz/api/v1alpha1"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
@@ -306,7 +308,7 @@ func unmarshalResponse(t *testing.T, contentType string, body []byte, got *v1alp
|
||||
t.Fatalf("unexpected error while unmarshalling YAML response: %v", err)
|
||||
}
|
||||
case strings.Contains(contentType, "application/cbor"):
|
||||
if err := cbor.Unmarshal(body, got); err != nil {
|
||||
if err := cbordirect.Unmarshal(body, got); err != nil {
|
||||
t.Fatalf("unexpected error while unmarshalling CBOR response: %v", err)
|
||||
}
|
||||
default:
|
||||
@@ -360,3 +362,18 @@ func TestCache(t *testing.T) {
|
||||
t.Errorf("Unexpected diff on cached response (-want,+got):\n%s", diff)
|
||||
}
|
||||
}
|
||||
|
||||
// TestNewFlagzCodecFactory ensures all media types in the codec factory
|
||||
// are explicitly handled. If this test fails, a new media type was added
|
||||
// to the codec factory and needs to be explicitly added to the supported
|
||||
// or unsupported list in newFlagzCodecFactory.
|
||||
func TestNewFlagzCodecFactory(t *testing.T) {
|
||||
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CBORServingAndStorage, true)
|
||||
scheme := runtime.NewScheme()
|
||||
utilruntime.Must(v1alpha1.AddToScheme(scheme))
|
||||
|
||||
_, err := newFlagzCodecFactory(scheme, "", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("unknown media type(s) detected - update newFlagzCodecFactory to explicitly handle them: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +67,7 @@ Warning: This endpoint is not meant to be machine parseable, has no formatting c
|
||||
// from the supported media types list, so error messages only show actually supported types.
|
||||
type statuszCodecFactory struct {
|
||||
serializer.CodecFactory
|
||||
supportedMediaTypes []runtime.SerializerInfo
|
||||
}
|
||||
|
||||
type mux interface {
|
||||
@@ -89,6 +90,16 @@ func NewRegistry(effectiveVersion compatibility.EffectiveVersion, opts ...Option
|
||||
func Install(m mux, componentName string, reg statuszRegistry) {
|
||||
scheme := runtime.NewScheme()
|
||||
utilruntime.Must(v1alpha1.AddToScheme(scheme))
|
||||
filteredCodecFactory, err := newStatuszCodecFactory(scheme, componentName, reg)
|
||||
if err != nil {
|
||||
utilruntime.HandleError(err)
|
||||
}
|
||||
m.Handle(DefaultStatuszPath, handleStatusz(componentName, reg, filteredCodecFactory, negotiate.StatuszEndpointRestrictions{}))
|
||||
}
|
||||
|
||||
// newStatuszCodecFactory creates a codec factory with the standard serializers for statusz,
|
||||
// filtering out unsupported media types (e.g., protobuf).
|
||||
func newStatuszCodecFactory(scheme *runtime.Scheme, componentName string, reg statuszRegistry) (*statuszCodecFactory, error) {
|
||||
codecFactoryOpts := []serializer.CodecFactoryOptionsMutator{
|
||||
serializer.WithSerializer(func(_ runtime.ObjectCreater, _ runtime.ObjectTyper) runtime.SerializerInfo {
|
||||
textSerializer := statuszTextSerializer{componentName, reg}
|
||||
@@ -108,21 +119,36 @@ func Install(m mux, componentName string, reg statuszRegistry) {
|
||||
}
|
||||
|
||||
codecFactory := serializer.NewCodecFactory(scheme, codecFactoryOpts...)
|
||||
// Wrap to filter out unsupported media types (e.g., protobuf)
|
||||
filteredCodecFactory := &statuszCodecFactory{codecFactory}
|
||||
m.Handle(DefaultStatuszPath, handleStatusz(componentName, reg, filteredCodecFactory, negotiate.StatuszEndpointRestrictions{}))
|
||||
allTypes := codecFactory.SupportedMediaTypes()
|
||||
filtered := make([]runtime.SerializerInfo, 0, len(allTypes))
|
||||
|
||||
var unknownTypes []string
|
||||
for _, info := range allTypes {
|
||||
switch info.MediaType {
|
||||
// Supported media types
|
||||
case "text/plain", runtime.ContentTypeJSON, runtime.ContentTypeYAML, runtime.ContentTypeCBOR:
|
||||
filtered = append(filtered, info)
|
||||
// Unsupported media types
|
||||
case runtime.ContentTypeProtobuf:
|
||||
continue
|
||||
default:
|
||||
unknownTypes = append(unknownTypes, info.MediaType)
|
||||
}
|
||||
}
|
||||
|
||||
var err error
|
||||
if len(unknownTypes) > 0 {
|
||||
err = fmt.Errorf("statusz: unknown media type(s) %v, excluding from supported types", unknownTypes)
|
||||
}
|
||||
|
||||
return &statuszCodecFactory{
|
||||
CodecFactory: codecFactory,
|
||||
supportedMediaTypes: filtered,
|
||||
}, err
|
||||
}
|
||||
|
||||
func (f *statuszCodecFactory) SupportedMediaTypes() []runtime.SerializerInfo {
|
||||
allTypes := f.CodecFactory.SupportedMediaTypes()
|
||||
filtered := make([]runtime.SerializerInfo, 0, len(allTypes))
|
||||
for _, info := range allTypes {
|
||||
if info.MediaType == runtime.ContentTypeProtobuf {
|
||||
continue
|
||||
}
|
||||
filtered = append(filtered, info)
|
||||
}
|
||||
return filtered
|
||||
return f.supportedMediaTypes
|
||||
}
|
||||
|
||||
func handleStatusz(componentName string, reg statuszRegistry, serializer runtime.NegotiatedSerializer, restrictions negotiate.StatuszEndpointRestrictions) http.HandlerFunc {
|
||||
|
||||
@@ -27,7 +27,9 @@ import (
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
cbor "k8s.io/apimachinery/pkg/runtime/serializer/cbor/direct"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/version"
|
||||
"k8s.io/apimachinery/pkg/util/yaml"
|
||||
"k8s.io/apiserver/pkg/features"
|
||||
@@ -443,3 +445,18 @@ func timeEqual() cmp.Option {
|
||||
return expectedTime.Truncate(time.Second).Equal(actualTime.Truncate(time.Second))
|
||||
})
|
||||
}
|
||||
|
||||
// TestNewStatuszCodecFactory ensures all media types in the codec factory
|
||||
// are explicitly handled. If this test fails, a new media type was added
|
||||
// to the codec factory and needs to be explicitly added to the supported
|
||||
// or unsupported list in newStatuszCodecFactory.
|
||||
func TestNewStatuszCodecFactory(t *testing.T) {
|
||||
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CBORServingAndStorage, true)
|
||||
scheme := runtime.NewScheme()
|
||||
utilruntime.Must(v1alpha1.AddToScheme(scheme))
|
||||
|
||||
_, err := newStatuszCodecFactory(scheme, "", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("unknown media type(s) detected - update newStatuszCodecFactory to explicitly handle them: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user