Wire test-only feature gate for CBOR serving.
To mitigate the risk of introducing a new protocol, integration tests for CBOR will be written using a test-only feature gate instance that is not wired to runtime options. On alpha graduation, the test-only feature gate instance will be replaced by a normal feature gate in the existing apiserver feature gate instance. Kubernetes-commit: 0cad1a89b6721308746cc1a12f12de31a259a0d3
This commit is contained in:
		
							parent
							
								
									781f771b86
								
							
						
					
					
						commit
						f27bb5491e
					
				|  | @ -87,6 +87,15 @@ const ( | |||
| 	// Allows authorization to use field and label selectors.
 | ||||
| 	AuthorizeWithSelectors featuregate.Feature = "AuthorizeWithSelectors" | ||||
| 
 | ||||
| 	// owner: @benluddy
 | ||||
| 	// kep: https://kep.k8s.io/4222
 | ||||
| 	//
 | ||||
| 	// Enables CBOR as a supported encoding for requests and responses, and as the
 | ||||
| 	// preferred storage encoding for custom resources.
 | ||||
| 	//
 | ||||
| 	// This feature is currently PRE-ALPHA and MUST NOT be enabled outside of integration tests.
 | ||||
| 	TestOnlyCBORServingAndStorage featuregate.Feature = "TestOnlyCBORServingAndStorage" | ||||
| 
 | ||||
| 	// owner: @serathius
 | ||||
| 	// Enables concurrent watch object decoding to avoid starving watch cache when conversion webhook is installed.
 | ||||
| 	ConcurrentWatchObjectDecode featuregate.Feature = "ConcurrentWatchObjectDecode" | ||||
|  | @ -238,6 +247,7 @@ const ( | |||
| func init() { | ||||
| 	runtime.Must(utilfeature.DefaultMutableFeatureGate.Add(defaultKubernetesFeatureGates)) | ||||
| 	runtime.Must(utilfeature.DefaultMutableFeatureGate.AddVersioned(defaultVersionedKubernetesFeatureGates)) | ||||
| 	runtime.Must(utilfeature.TestOnlyMutableFeatureGate.AddVersioned(testOnlyVersionedKubernetesFeatureGates)) | ||||
| } | ||||
| 
 | ||||
| // defaultVersionedKubernetesFeatureGates consists of all known Kubernetes-specific feature keys with VersionedSpecs.
 | ||||
|  | @ -410,3 +420,12 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate | |||
| // defaultKubernetesFeatureGates consists of legacy unversioned Kubernetes-specific feature keys.
 | ||||
| // Please do not add to this struct and use defaultVersionedKubernetesFeatureGates instead.
 | ||||
| var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureSpec{} | ||||
| 
 | ||||
| // testOnlyVersionedKubernetesFeatureGates consists of features that require programmatic enablement
 | ||||
| // for integration testing, but have not yet graduated to alpha in a release and must not be enabled
 | ||||
| // by a runtime option.
 | ||||
| var testOnlyVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate.VersionedSpecs{ | ||||
| 	TestOnlyCBORServingAndStorage: { | ||||
| 		{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha}, | ||||
| 	}, | ||||
| } | ||||
|  |  | |||
|  | @ -742,7 +742,7 @@ func (c *RecommendedConfig) Complete() CompletedConfig { | |||
| 	return c.Config.Complete(c.SharedInformerFactory) | ||||
| } | ||||
| 
 | ||||
| var allowedMediaTypes = []string{ | ||||
| var defaultAllowedMediaTypes = []string{ | ||||
| 	runtime.ContentTypeJSON, | ||||
| 	runtime.ContentTypeYAML, | ||||
| 	runtime.ContentTypeProtobuf, | ||||
|  | @ -755,6 +755,10 @@ func (c completedConfig) New(name string, delegationTarget DelegationTarget) (*G | |||
| 	if c.Serializer == nil { | ||||
| 		return nil, fmt.Errorf("Genericapiserver.New() called with config.Serializer == nil") | ||||
| 	} | ||||
| 	allowedMediaTypes := defaultAllowedMediaTypes | ||||
| 	if utilfeature.TestOnlyFeatureGate.Enabled(genericfeatures.TestOnlyCBORServingAndStorage) { | ||||
| 		allowedMediaTypes = append(allowedMediaTypes, runtime.ContentTypeCBOR) | ||||
| 	} | ||||
| 	for _, info := range c.Serializer.SupportedMediaTypes() { | ||||
| 		var ok bool | ||||
| 		for _, mt := range allowedMediaTypes { | ||||
|  |  | |||
|  | @ -29,6 +29,7 @@ import ( | |||
| 	"time" | ||||
| 
 | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| 	"k8s.io/apimachinery/pkg/runtime/serializer" | ||||
| 	"k8s.io/apimachinery/pkg/util/json" | ||||
| 	"k8s.io/apimachinery/pkg/util/sets" | ||||
| 	"k8s.io/apimachinery/pkg/util/wait" | ||||
|  | @ -40,12 +41,14 @@ import ( | |||
| 	"k8s.io/apiserver/pkg/authentication/user" | ||||
| 	"k8s.io/apiserver/pkg/authorization/authorizer" | ||||
| 	"k8s.io/apiserver/pkg/endpoints/request" | ||||
| 	"k8s.io/apiserver/pkg/features" | ||||
| 	"k8s.io/apiserver/pkg/server/healthz" | ||||
| 	utilfeature "k8s.io/apiserver/pkg/util/feature" | ||||
| 	utilversion "k8s.io/apiserver/pkg/util/version" | ||||
| 	"k8s.io/client-go/informers" | ||||
| 	"k8s.io/client-go/kubernetes/fake" | ||||
| 	"k8s.io/client-go/rest" | ||||
| 	featuregatetesting "k8s.io/component-base/featuregate/testing" | ||||
| 	"k8s.io/component-base/tracing" | ||||
| 	"k8s.io/klog/v2/ktesting" | ||||
| 	netutils "k8s.io/utils/net" | ||||
|  | @ -419,3 +422,22 @@ func TestNewErrorForbiddenSerializer(t *testing.T) { | |||
| 		t.Errorf("unexpected error: %v", err) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func TestNewFeatureGatedSerializer(t *testing.T) { | ||||
| 	featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.TestOnlyFeatureGate, features.TestOnlyCBORServingAndStorage, true) | ||||
| 
 | ||||
| 	config := NewConfig(serializer.NewCodecFactory(scheme, serializer.WithSerializer(func(creater runtime.ObjectCreater, typer runtime.ObjectTyper) runtime.SerializerInfo { | ||||
| 		return runtime.SerializerInfo{ | ||||
| 			MediaType:        "application/cbor", | ||||
| 			MediaTypeType:    "application", | ||||
| 			MediaTypeSubType: "cbor", | ||||
| 		} | ||||
| 	}))) | ||||
| 	config.ExternalAddress = "192.168.10.4:443" | ||||
| 	config.EffectiveVersion = utilversion.NewEffectiveVersion("") | ||||
| 	config.LoopbackClientConfig = &rest.Config{} | ||||
| 
 | ||||
| 	if _, err := config.Complete(nil).New("test", NewEmptyDelegate()); err != nil { | ||||
| 		t.Errorf("unexpected error: %v", err) | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -31,3 +31,15 @@ var ( | |||
| 	// Top-level commands/options setup that needs to modify this feature gate should use DefaultMutableFeatureGate.
 | ||||
| 	DefaultFeatureGate featuregate.FeatureGate = DefaultMutableFeatureGate | ||||
| ) | ||||
| 
 | ||||
| var ( | ||||
| 	// TestOnlyMutableFeatureGate is a mutable version of TestOnlyFeatureGate. Only top-level
 | ||||
| 	// commands/options setup and the k8s.io/component-base/featuregate/testing package should
 | ||||
| 	// make use of this.
 | ||||
| 	TestOnlyMutableFeatureGate featuregate.MutableVersionedFeatureGate = featuregate.NewFeatureGate() | ||||
| 
 | ||||
| 	// TestOnlyFeatureGate is a shared global FeatureGate for features that have not yet
 | ||||
| 	// graduated to alpha and require programmatic feature enablement for pre-alpha integration
 | ||||
| 	// testing without exposing the feature as a runtime option.
 | ||||
| 	TestOnlyFeatureGate featuregate.FeatureGate = TestOnlyMutableFeatureGate | ||||
| ) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue