Refactor compatibility version code
Replace DefaultComponentGlobalsRegistry with new instance of componentGlobalsRegistry in test api server. Signed-off-by: Siyuan Zhang <sizhang@google.com> move kube effective version validation out of component base. Signed-off-by: Siyuan Zhang <sizhang@google.com> move DefaultComponentGlobalsRegistry out of component base. Signed-off-by: Siyuan Zhang <sizhang@google.com> move ComponentGlobalsRegistry out of featuregate pkg. Signed-off-by: Siyuan Zhang <sizhang@google.com> remove usage of DefaultComponentGlobalsRegistry in test files. Signed-off-by: Siyuan Zhang <sizhang@google.com> change non-test DefaultKubeEffectiveVersion to use DefaultBuildEffectiveVersion. Signed-off-by: Siyuan Zhang <sizhang@google.com> Restore useDefaultBuildBinaryVersion in effective version. Signed-off-by: Siyuan Zhang <sizhang@google.com> rename DefaultKubeEffectiveVersion to DefaultKubeEffectiveVersionForTest. Signed-off-by: Siyuan Zhang <sizhang@google.com> pass options.ComponentGlobalsRegistry into config for controller manager and scheduler. Signed-off-by: Siyuan Zhang <sizhang@google.com> Pass apiserver effective version to DefaultResourceEncodingConfig. Signed-off-by: Siyuan Zhang <sizhang@google.com> change statusz registry to take effective version from the components. Signed-off-by: Siyuan Zhang <sizhang@google.com> Address review comments Signed-off-by: Siyuan Zhang <sizhang@google.com> update vendor Signed-off-by: Siyuan Zhang <sizhang@google.com> Kubernetes-commit: 8fc3a33454ba38783bb63de41ecf5343e2ced67c
This commit is contained in:
parent
9bb5fd51d1
commit
9bb4aa730a
|
@ -34,7 +34,6 @@ import (
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
asn1util "k8s.io/apimachinery/pkg/apis/asn1"
|
asn1util "k8s.io/apimachinery/pkg/apis/asn1"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/apimachinery/pkg/util/version"
|
|
||||||
"k8s.io/apiserver/pkg/authentication/authenticator"
|
"k8s.io/apiserver/pkg/authentication/authenticator"
|
||||||
"k8s.io/apiserver/pkg/authentication/user"
|
"k8s.io/apiserver/pkg/authentication/user"
|
||||||
"k8s.io/apiserver/pkg/features"
|
"k8s.io/apiserver/pkg/features"
|
||||||
|
@ -799,9 +798,6 @@ func TestX509(t *testing.T) {
|
||||||
ExpectErr: false,
|
ExpectErr: false,
|
||||||
setupFunc: func(t *testing.T) {
|
setupFunc: func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
// This statement can be removed once utilversion.DefaultKubeEffectiveVersion() is >= 1.33
|
|
||||||
featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, feature.DefaultFeatureGate, version.MustParse("1.33"))
|
|
||||||
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"common name and empty UID with feature gate disabled": {
|
"common name and empty UID with feature gate disabled": {
|
||||||
|
@ -822,8 +818,6 @@ func TestX509(t *testing.T) {
|
||||||
ExpectErr: false,
|
ExpectErr: false,
|
||||||
setupFunc: func(t *testing.T) {
|
setupFunc: func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
// This statement can be removed once utilversion.DefaultKubeEffectiveVersion() is >= 1.33
|
|
||||||
featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, feature.DefaultFeatureGate, version.MustParse("1.33"))
|
|
||||||
featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.AllowParsingUserUIDFromCertAuth, false)
|
featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.AllowParsingUserUIDFromCertAuth, false)
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -836,9 +830,6 @@ func TestX509(t *testing.T) {
|
||||||
ExpectErrMsg: regexp.MustCompile("UID cannot be an empty string"),
|
ExpectErrMsg: regexp.MustCompile("UID cannot be an empty string"),
|
||||||
setupFunc: func(t *testing.T) {
|
setupFunc: func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
// This statement can be removed once utilversion.DefaultKubeEffectiveVersion() is >= 1.33
|
|
||||||
featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, feature.DefaultFeatureGate, version.MustParse("1.33"))
|
|
||||||
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"ca with non-string UID": {
|
"ca with non-string UID": {
|
||||||
|
@ -850,9 +841,6 @@ func TestX509(t *testing.T) {
|
||||||
ExpectErrMsg: regexp.MustCompile("unable to parse UID into a string"),
|
ExpectErrMsg: regexp.MustCompile("unable to parse UID into a string"),
|
||||||
setupFunc: func(t *testing.T) {
|
setupFunc: func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
// This statement can be removed once utilversion.DefaultKubeEffectiveVersion() is >= 1.33
|
|
||||||
featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, feature.DefaultFeatureGate, version.MustParse("1.33"))
|
|
||||||
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"ca with multiple UIDs": {
|
"ca with multiple UIDs": {
|
||||||
|
@ -866,9 +854,6 @@ func TestX509(t *testing.T) {
|
||||||
ExpectErrMsg: regexp.MustCompile("expected 1 UID, but found multiple"),
|
ExpectErrMsg: regexp.MustCompile("expected 1 UID, but found multiple"),
|
||||||
setupFunc: func(t *testing.T) {
|
setupFunc: func(t *testing.T) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
// This statement can be removed once utilversion.DefaultKubeEffectiveVersion() is >= 1.33
|
|
||||||
featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, feature.DefaultFeatureGate, version.MustParse("1.33"))
|
|
||||||
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"ca with multiple organizations": {
|
"ca with multiple organizations": {
|
||||||
|
|
|
@ -32,9 +32,9 @@ import (
|
||||||
celconfig "k8s.io/apiserver/pkg/apis/cel"
|
celconfig "k8s.io/apiserver/pkg/apis/cel"
|
||||||
"k8s.io/apiserver/pkg/cel/library"
|
"k8s.io/apiserver/pkg/cel/library"
|
||||||
genericfeatures "k8s.io/apiserver/pkg/features"
|
genericfeatures "k8s.io/apiserver/pkg/features"
|
||||||
|
"k8s.io/apiserver/pkg/util/compatibility"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/component-base/featuregate"
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
utilversion "k8s.io/component-base/version"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// DefaultCompatibilityVersion returns a default compatibility version for use with EnvSet
|
// DefaultCompatibilityVersion returns a default compatibility version for use with EnvSet
|
||||||
|
@ -50,9 +50,9 @@ import (
|
||||||
// A default version number equal to the current Kubernetes major.minor version
|
// A default version number equal to the current Kubernetes major.minor version
|
||||||
// indicates fast forward CEL features that can be used when rollback is no longer needed.
|
// indicates fast forward CEL features that can be used when rollback is no longer needed.
|
||||||
func DefaultCompatibilityVersion() *version.Version {
|
func DefaultCompatibilityVersion() *version.Version {
|
||||||
effectiveVer := featuregate.DefaultComponentGlobalsRegistry.EffectiveVersionFor(featuregate.DefaultKubeComponent)
|
effectiveVer := compatibility.DefaultComponentGlobalsRegistry.EffectiveVersionFor(basecompatibility.DefaultKubeComponent)
|
||||||
if effectiveVer == nil {
|
if effectiveVer == nil {
|
||||||
effectiveVer = utilversion.DefaultKubeEffectiveVersion()
|
effectiveVer = compatibility.DefaultBuildEffectiveVersion()
|
||||||
}
|
}
|
||||||
return effectiveVer.MinCompatibilityVersion()
|
return effectiveVer.MinCompatibilityVersion()
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,12 +73,12 @@ import (
|
||||||
flowcontrolrequest "k8s.io/apiserver/pkg/util/flowcontrol/request"
|
flowcontrolrequest "k8s.io/apiserver/pkg/util/flowcontrol/request"
|
||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
"k8s.io/component-base/featuregate"
|
"k8s.io/component-base/featuregate"
|
||||||
"k8s.io/component-base/logs"
|
"k8s.io/component-base/logs"
|
||||||
"k8s.io/component-base/metrics/features"
|
"k8s.io/component-base/metrics/features"
|
||||||
"k8s.io/component-base/metrics/prometheus/slis"
|
"k8s.io/component-base/metrics/prometheus/slis"
|
||||||
"k8s.io/component-base/tracing"
|
"k8s.io/component-base/tracing"
|
||||||
utilversion "k8s.io/component-base/version"
|
|
||||||
"k8s.io/component-base/zpages/flagz"
|
"k8s.io/component-base/zpages/flagz"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
openapicommon "k8s.io/kube-openapi/pkg/common"
|
openapicommon "k8s.io/kube-openapi/pkg/common"
|
||||||
|
@ -153,7 +153,7 @@ type Config struct {
|
||||||
|
|
||||||
// EffectiveVersion determines which apis and features are available
|
// EffectiveVersion determines which apis and features are available
|
||||||
// based on when the api/feature lifecyle.
|
// based on when the api/feature lifecyle.
|
||||||
EffectiveVersion utilversion.EffectiveVersion
|
EffectiveVersion basecompatibility.EffectiveVersion
|
||||||
// FeatureGate is a way to plumb feature gate through if you have them.
|
// FeatureGate is a way to plumb feature gate through if you have them.
|
||||||
FeatureGate featuregate.FeatureGate
|
FeatureGate featuregate.FeatureGate
|
||||||
// AuditBackend is where audit events are sent to.
|
// AuditBackend is where audit events are sent to.
|
||||||
|
|
|
@ -47,9 +47,9 @@ import (
|
||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||||
"k8s.io/component-base/tracing"
|
"k8s.io/component-base/tracing"
|
||||||
utilversion "k8s.io/component-base/version"
|
|
||||||
"k8s.io/klog/v2/ktesting"
|
"k8s.io/klog/v2/ktesting"
|
||||||
netutils "k8s.io/utils/net"
|
netutils "k8s.io/utils/net"
|
||||||
)
|
)
|
||||||
|
@ -124,7 +124,7 @@ func TestNewWithDelegate(t *testing.T) {
|
||||||
delegateConfig.PublicAddress = netutils.ParseIPSloppy("192.168.10.4")
|
delegateConfig.PublicAddress = netutils.ParseIPSloppy("192.168.10.4")
|
||||||
delegateConfig.LegacyAPIGroupPrefixes = sets.NewString("/api")
|
delegateConfig.LegacyAPIGroupPrefixes = sets.NewString("/api")
|
||||||
delegateConfig.LoopbackClientConfig = &rest.Config{}
|
delegateConfig.LoopbackClientConfig = &rest.Config{}
|
||||||
delegateConfig.EffectiveVersion = utilversion.NewEffectiveVersion("")
|
delegateConfig.EffectiveVersion = basecompatibility.NewEffectiveVersionFromString("", "", "")
|
||||||
clientset := fake.NewSimpleClientset()
|
clientset := fake.NewSimpleClientset()
|
||||||
if clientset == nil {
|
if clientset == nil {
|
||||||
t.Fatal("unable to create fake client set")
|
t.Fatal("unable to create fake client set")
|
||||||
|
@ -157,7 +157,7 @@ func TestNewWithDelegate(t *testing.T) {
|
||||||
wrappingConfig.PublicAddress = netutils.ParseIPSloppy("192.168.10.4")
|
wrappingConfig.PublicAddress = netutils.ParseIPSloppy("192.168.10.4")
|
||||||
wrappingConfig.LegacyAPIGroupPrefixes = sets.NewString("/api")
|
wrappingConfig.LegacyAPIGroupPrefixes = sets.NewString("/api")
|
||||||
wrappingConfig.LoopbackClientConfig = &rest.Config{}
|
wrappingConfig.LoopbackClientConfig = &rest.Config{}
|
||||||
wrappingConfig.EffectiveVersion = utilversion.NewEffectiveVersion("")
|
wrappingConfig.EffectiveVersion = basecompatibility.NewEffectiveVersionFromString("", "", "")
|
||||||
|
|
||||||
wrappingConfig.HealthzChecks = append(wrappingConfig.HealthzChecks, healthz.NamedCheck("wrapping-health", func(r *http.Request) error {
|
wrappingConfig.HealthzChecks = append(wrappingConfig.HealthzChecks, healthz.NamedCheck("wrapping-health", func(r *http.Request) error {
|
||||||
return fmt.Errorf("wrapping failed healthcheck")
|
return fmt.Errorf("wrapping failed healthcheck")
|
||||||
|
@ -434,7 +434,7 @@ func TestNewFeatureGatedSerializer(t *testing.T) {
|
||||||
}
|
}
|
||||||
})))
|
})))
|
||||||
config.ExternalAddress = "192.168.10.4:443"
|
config.ExternalAddress = "192.168.10.4:443"
|
||||||
config.EffectiveVersion = utilversion.NewEffectiveVersion("")
|
config.EffectiveVersion = basecompatibility.NewEffectiveVersionFromString("", "", "")
|
||||||
config.LoopbackClientConfig = &rest.Config{}
|
config.LoopbackClientConfig = &rest.Config{}
|
||||||
|
|
||||||
if _, err := config.Complete(nil).New("test", NewEmptyDelegate()); err != nil {
|
if _, err := config.Complete(nil).New("test", NewEmptyDelegate()); err != nil {
|
||||||
|
|
|
@ -54,8 +54,8 @@ import (
|
||||||
"k8s.io/apiserver/pkg/storageversion"
|
"k8s.io/apiserver/pkg/storageversion"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
"k8s.io/component-base/featuregate"
|
"k8s.io/component-base/featuregate"
|
||||||
utilversion "k8s.io/component-base/version"
|
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
openapibuilder3 "k8s.io/kube-openapi/pkg/builder3"
|
openapibuilder3 "k8s.io/kube-openapi/pkg/builder3"
|
||||||
openapicommon "k8s.io/kube-openapi/pkg/common"
|
openapicommon "k8s.io/kube-openapi/pkg/common"
|
||||||
|
@ -244,7 +244,7 @@ type GenericAPIServer struct {
|
||||||
|
|
||||||
// EffectiveVersion determines which apis and features are available
|
// EffectiveVersion determines which apis and features are available
|
||||||
// based on when the api/feature lifecyle.
|
// based on when the api/feature lifecyle.
|
||||||
EffectiveVersion utilversion.EffectiveVersion
|
EffectiveVersion basecompatibility.EffectiveVersion
|
||||||
// FeatureGate is a way to plumb feature gate through if you have them.
|
// FeatureGate is a way to plumb feature gate through if you have them.
|
||||||
FeatureGate featuregate.FeatureGate
|
FeatureGate featuregate.FeatureGate
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,7 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
utilversion "k8s.io/apimachinery/pkg/util/version"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
"k8s.io/apimachinery/pkg/version"
|
"k8s.io/apimachinery/pkg/version"
|
||||||
"k8s.io/apiserver/pkg/apis/example"
|
"k8s.io/apiserver/pkg/apis/example"
|
||||||
|
@ -52,7 +53,7 @@ import (
|
||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
utilversion "k8s.io/component-base/version"
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
"k8s.io/klog/v2/ktesting"
|
"k8s.io/klog/v2/ktesting"
|
||||||
kubeopenapi "k8s.io/kube-openapi/pkg/common"
|
kubeopenapi "k8s.io/kube-openapi/pkg/common"
|
||||||
"k8s.io/kube-openapi/pkg/validation/spec"
|
"k8s.io/kube-openapi/pkg/validation/spec"
|
||||||
|
@ -138,7 +139,7 @@ func setUp(t *testing.T) (Config, *assert.Assertions) {
|
||||||
if clientset == nil {
|
if clientset == nil {
|
||||||
t.Fatal("unable to create fake client set")
|
t.Fatal("unable to create fake client set")
|
||||||
}
|
}
|
||||||
config.EffectiveVersion = utilversion.NewEffectiveVersion("")
|
config.EffectiveVersion = basecompatibility.NewEffectiveVersionFromString("", "", "")
|
||||||
config.OpenAPIConfig = DefaultOpenAPIConfig(testGetOpenAPIDefinitions, openapinamer.NewDefinitionNamer(runtime.NewScheme()))
|
config.OpenAPIConfig = DefaultOpenAPIConfig(testGetOpenAPIDefinitions, openapinamer.NewDefinitionNamer(runtime.NewScheme()))
|
||||||
config.OpenAPIConfig.Info.Version = "unversioned"
|
config.OpenAPIConfig.Info.Version = "unversioned"
|
||||||
config.OpenAPIV3Config = DefaultOpenAPIV3Config(testGetOpenAPIDefinitions, openapinamer.NewDefinitionNamer(runtime.NewScheme()))
|
config.OpenAPIV3Config = DefaultOpenAPIV3Config(testGetOpenAPIDefinitions, openapinamer.NewDefinitionNamer(runtime.NewScheme()))
|
||||||
|
@ -460,8 +461,8 @@ func TestNotRestRoutesHaveAuth(t *testing.T) {
|
||||||
config.EnableProfiling = true
|
config.EnableProfiling = true
|
||||||
|
|
||||||
kubeVersion := fakeVersion()
|
kubeVersion := fakeVersion()
|
||||||
effectiveVersion := utilversion.NewEffectiveVersion(kubeVersion.String())
|
binaryVersion := utilversion.MustParse(kubeVersion.String())
|
||||||
effectiveVersion.Set(effectiveVersion.BinaryVersion().WithInfo(kubeVersion), effectiveVersion.EmulationVersion(), effectiveVersion.MinCompatibilityVersion())
|
effectiveVersion := basecompatibility.NewEffectiveVersion(binaryVersion, false, binaryVersion, binaryVersion.SubtractMinor(1))
|
||||||
config.EffectiveVersion = effectiveVersion
|
config.EffectiveVersion = effectiveVersion
|
||||||
|
|
||||||
s, err := config.Complete(nil).New("test", NewEmptyDelegate())
|
s, err := config.Complete(nil).New("test", NewEmptyDelegate())
|
||||||
|
|
|
@ -27,9 +27,9 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/util/errors"
|
"k8s.io/apimachinery/pkg/util/errors"
|
||||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
"k8s.io/apiserver/pkg/server"
|
"k8s.io/apiserver/pkg/server"
|
||||||
|
"k8s.io/apiserver/pkg/util/compatibility"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/component-base/featuregate"
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
utilversion "k8s.io/component-base/version"
|
|
||||||
|
|
||||||
"github.com/spf13/pflag"
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
@ -95,22 +95,22 @@ type ServerRunOptions struct {
|
||||||
ShutdownWatchTerminationGracePeriod time.Duration
|
ShutdownWatchTerminationGracePeriod time.Duration
|
||||||
|
|
||||||
// ComponentGlobalsRegistry is the registry where the effective versions and feature gates for all components are stored.
|
// ComponentGlobalsRegistry is the registry where the effective versions and feature gates for all components are stored.
|
||||||
ComponentGlobalsRegistry featuregate.ComponentGlobalsRegistry
|
ComponentGlobalsRegistry basecompatibility.ComponentGlobalsRegistry
|
||||||
// ComponentName is name under which the server's global variabled are registered in the ComponentGlobalsRegistry.
|
// ComponentName is name under which the server's global variabled are registered in the ComponentGlobalsRegistry.
|
||||||
ComponentName string
|
ComponentName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServerRunOptions() *ServerRunOptions {
|
func NewServerRunOptions() *ServerRunOptions {
|
||||||
if featuregate.DefaultComponentGlobalsRegistry.EffectiveVersionFor(featuregate.DefaultKubeComponent) == nil {
|
if compatibility.DefaultComponentGlobalsRegistry.EffectiveVersionFor(basecompatibility.DefaultKubeComponent) == nil {
|
||||||
featureGate := utilfeature.DefaultMutableFeatureGate
|
featureGate := utilfeature.DefaultMutableFeatureGate
|
||||||
effectiveVersion := utilversion.DefaultKubeEffectiveVersion()
|
effectiveVersion := compatibility.DefaultBuildEffectiveVersion()
|
||||||
utilruntime.Must(featuregate.DefaultComponentGlobalsRegistry.Register(featuregate.DefaultKubeComponent, effectiveVersion, featureGate))
|
utilruntime.Must(compatibility.DefaultComponentGlobalsRegistry.Register(basecompatibility.DefaultKubeComponent, effectiveVersion, featureGate))
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewServerRunOptionsForComponent(featuregate.DefaultKubeComponent, featuregate.DefaultComponentGlobalsRegistry)
|
return NewServerRunOptionsForComponent(basecompatibility.DefaultKubeComponent, compatibility.DefaultComponentGlobalsRegistry)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServerRunOptionsForComponent(componentName string, componentGlobalsRegistry featuregate.ComponentGlobalsRegistry) *ServerRunOptions {
|
func NewServerRunOptionsForComponent(componentName string, componentGlobalsRegistry basecompatibility.ComponentGlobalsRegistry) *ServerRunOptions {
|
||||||
defaults := server.NewConfig(serializer.CodecFactory{})
|
defaults := server.NewConfig(serializer.CodecFactory{})
|
||||||
return &ServerRunOptions{
|
return &ServerRunOptions{
|
||||||
MaxRequestsInFlight: defaults.MaxRequestsInFlight,
|
MaxRequestsInFlight: defaults.MaxRequestsInFlight,
|
||||||
|
|
|
@ -26,15 +26,15 @@ import (
|
||||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/version"
|
"k8s.io/apimachinery/pkg/util/version"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/component-base/featuregate"
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
utilversion "k8s.io/component-base/version"
|
|
||||||
netutils "k8s.io/utils/net"
|
netutils "k8s.io/utils/net"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestServerRunOptionsValidate(t *testing.T) {
|
func TestServerRunOptionsValidate(t *testing.T) {
|
||||||
testRegistry := featuregate.NewComponentGlobalsRegistry()
|
defaultComponentGlobalsRegistry := basecompatibility.NewComponentGlobalsRegistry()
|
||||||
|
testRegistry := basecompatibility.NewComponentGlobalsRegistry()
|
||||||
featureGate := utilfeature.DefaultFeatureGate.DeepCopy()
|
featureGate := utilfeature.DefaultFeatureGate.DeepCopy()
|
||||||
effectiveVersion := utilversion.NewEffectiveVersion("1.35")
|
effectiveVersion := basecompatibility.NewEffectiveVersionFromString("1.35", "1.32", "1.32")
|
||||||
effectiveVersion.SetEmulationVersion(version.MajorMinor(1, 31))
|
effectiveVersion.SetEmulationVersion(version.MajorMinor(1, 31))
|
||||||
testComponent := "test"
|
testComponent := "test"
|
||||||
utilruntime.Must(testRegistry.Register(testComponent, effectiveVersion, featureGate))
|
utilruntime.Must(testRegistry.Register(testComponent, effectiveVersion, featureGate))
|
||||||
|
@ -55,7 +55,7 @@ func TestServerRunOptionsValidate(t *testing.T) {
|
||||||
MinRequestTimeout: 1800,
|
MinRequestTimeout: 1800,
|
||||||
JSONPatchMaxCopyBytes: 10 * 1024 * 1024,
|
JSONPatchMaxCopyBytes: 10 * 1024 * 1024,
|
||||||
MaxRequestBodyBytes: 10 * 1024 * 1024,
|
MaxRequestBodyBytes: 10 * 1024 * 1024,
|
||||||
ComponentGlobalsRegistry: featuregate.DefaultComponentGlobalsRegistry,
|
ComponentGlobalsRegistry: defaultComponentGlobalsRegistry,
|
||||||
},
|
},
|
||||||
expectErr: "--max-requests-inflight can not be negative value",
|
expectErr: "--max-requests-inflight can not be negative value",
|
||||||
},
|
},
|
||||||
|
@ -70,7 +70,7 @@ func TestServerRunOptionsValidate(t *testing.T) {
|
||||||
MinRequestTimeout: 1800,
|
MinRequestTimeout: 1800,
|
||||||
JSONPatchMaxCopyBytes: 10 * 1024 * 1024,
|
JSONPatchMaxCopyBytes: 10 * 1024 * 1024,
|
||||||
MaxRequestBodyBytes: 10 * 1024 * 1024,
|
MaxRequestBodyBytes: 10 * 1024 * 1024,
|
||||||
ComponentGlobalsRegistry: featuregate.DefaultComponentGlobalsRegistry,
|
ComponentGlobalsRegistry: defaultComponentGlobalsRegistry,
|
||||||
},
|
},
|
||||||
expectErr: "--max-mutating-requests-inflight can not be negative value",
|
expectErr: "--max-mutating-requests-inflight can not be negative value",
|
||||||
},
|
},
|
||||||
|
@ -85,7 +85,7 @@ func TestServerRunOptionsValidate(t *testing.T) {
|
||||||
MinRequestTimeout: 1800,
|
MinRequestTimeout: 1800,
|
||||||
JSONPatchMaxCopyBytes: 10 * 1024 * 1024,
|
JSONPatchMaxCopyBytes: 10 * 1024 * 1024,
|
||||||
MaxRequestBodyBytes: 10 * 1024 * 1024,
|
MaxRequestBodyBytes: 10 * 1024 * 1024,
|
||||||
ComponentGlobalsRegistry: featuregate.DefaultComponentGlobalsRegistry,
|
ComponentGlobalsRegistry: defaultComponentGlobalsRegistry,
|
||||||
},
|
},
|
||||||
expectErr: "--request-timeout can not be negative value",
|
expectErr: "--request-timeout can not be negative value",
|
||||||
},
|
},
|
||||||
|
@ -100,7 +100,7 @@ func TestServerRunOptionsValidate(t *testing.T) {
|
||||||
MinRequestTimeout: -1800,
|
MinRequestTimeout: -1800,
|
||||||
JSONPatchMaxCopyBytes: 10 * 1024 * 1024,
|
JSONPatchMaxCopyBytes: 10 * 1024 * 1024,
|
||||||
MaxRequestBodyBytes: 10 * 1024 * 1024,
|
MaxRequestBodyBytes: 10 * 1024 * 1024,
|
||||||
ComponentGlobalsRegistry: featuregate.DefaultComponentGlobalsRegistry,
|
ComponentGlobalsRegistry: defaultComponentGlobalsRegistry,
|
||||||
},
|
},
|
||||||
expectErr: "--min-request-timeout can not be negative value",
|
expectErr: "--min-request-timeout can not be negative value",
|
||||||
},
|
},
|
||||||
|
@ -115,7 +115,7 @@ func TestServerRunOptionsValidate(t *testing.T) {
|
||||||
MinRequestTimeout: 1800,
|
MinRequestTimeout: 1800,
|
||||||
JSONPatchMaxCopyBytes: -10 * 1024 * 1024,
|
JSONPatchMaxCopyBytes: -10 * 1024 * 1024,
|
||||||
MaxRequestBodyBytes: 10 * 1024 * 1024,
|
MaxRequestBodyBytes: 10 * 1024 * 1024,
|
||||||
ComponentGlobalsRegistry: featuregate.DefaultComponentGlobalsRegistry,
|
ComponentGlobalsRegistry: defaultComponentGlobalsRegistry,
|
||||||
},
|
},
|
||||||
expectErr: "ServerRunOptions.JSONPatchMaxCopyBytes can not be negative value",
|
expectErr: "ServerRunOptions.JSONPatchMaxCopyBytes can not be negative value",
|
||||||
},
|
},
|
||||||
|
@ -130,7 +130,7 @@ func TestServerRunOptionsValidate(t *testing.T) {
|
||||||
MinRequestTimeout: 1800,
|
MinRequestTimeout: 1800,
|
||||||
JSONPatchMaxCopyBytes: 10 * 1024 * 1024,
|
JSONPatchMaxCopyBytes: 10 * 1024 * 1024,
|
||||||
MaxRequestBodyBytes: -10 * 1024 * 1024,
|
MaxRequestBodyBytes: -10 * 1024 * 1024,
|
||||||
ComponentGlobalsRegistry: featuregate.DefaultComponentGlobalsRegistry,
|
ComponentGlobalsRegistry: defaultComponentGlobalsRegistry,
|
||||||
},
|
},
|
||||||
expectErr: "ServerRunOptions.MaxRequestBodyBytes can not be negative value",
|
expectErr: "ServerRunOptions.MaxRequestBodyBytes can not be negative value",
|
||||||
},
|
},
|
||||||
|
@ -146,7 +146,7 @@ func TestServerRunOptionsValidate(t *testing.T) {
|
||||||
JSONPatchMaxCopyBytes: 10 * 1024 * 1024,
|
JSONPatchMaxCopyBytes: 10 * 1024 * 1024,
|
||||||
MaxRequestBodyBytes: 10 * 1024 * 1024,
|
MaxRequestBodyBytes: 10 * 1024 * 1024,
|
||||||
LivezGracePeriod: -time.Second,
|
LivezGracePeriod: -time.Second,
|
||||||
ComponentGlobalsRegistry: featuregate.DefaultComponentGlobalsRegistry,
|
ComponentGlobalsRegistry: defaultComponentGlobalsRegistry,
|
||||||
},
|
},
|
||||||
expectErr: "--livez-grace-period can not be a negative value",
|
expectErr: "--livez-grace-period can not be a negative value",
|
||||||
},
|
},
|
||||||
|
@ -162,7 +162,7 @@ func TestServerRunOptionsValidate(t *testing.T) {
|
||||||
JSONPatchMaxCopyBytes: 10 * 1024 * 1024,
|
JSONPatchMaxCopyBytes: 10 * 1024 * 1024,
|
||||||
MaxRequestBodyBytes: 10 * 1024 * 1024,
|
MaxRequestBodyBytes: 10 * 1024 * 1024,
|
||||||
ShutdownDelayDuration: -time.Second,
|
ShutdownDelayDuration: -time.Second,
|
||||||
ComponentGlobalsRegistry: featuregate.DefaultComponentGlobalsRegistry,
|
ComponentGlobalsRegistry: defaultComponentGlobalsRegistry,
|
||||||
},
|
},
|
||||||
expectErr: "--shutdown-delay-duration can not be negative value",
|
expectErr: "--shutdown-delay-duration can not be negative value",
|
||||||
},
|
},
|
||||||
|
@ -178,7 +178,7 @@ func TestServerRunOptionsValidate(t *testing.T) {
|
||||||
MinRequestTimeout: 1800,
|
MinRequestTimeout: 1800,
|
||||||
JSONPatchMaxCopyBytes: 10 * 1024 * 1024,
|
JSONPatchMaxCopyBytes: 10 * 1024 * 1024,
|
||||||
MaxRequestBodyBytes: 10 * 1024 * 1024,
|
MaxRequestBodyBytes: 10 * 1024 * 1024,
|
||||||
ComponentGlobalsRegistry: featuregate.DefaultComponentGlobalsRegistry,
|
ComponentGlobalsRegistry: defaultComponentGlobalsRegistry,
|
||||||
},
|
},
|
||||||
expectErr: "--strict-transport-security-directives invalid, allowed values: max-age=expireTime, includeSubDomains, preload. see https://tools.ietf.org/html/rfc6797#section-6.1 for more information",
|
expectErr: "--strict-transport-security-directives invalid, allowed values: max-age=expireTime, includeSubDomains, preload. see https://tools.ietf.org/html/rfc6797#section-6.1 for more information",
|
||||||
},
|
},
|
||||||
|
@ -211,7 +211,7 @@ func TestServerRunOptionsValidate(t *testing.T) {
|
||||||
MinRequestTimeout: 1800,
|
MinRequestTimeout: 1800,
|
||||||
JSONPatchMaxCopyBytes: 10 * 1024 * 1024,
|
JSONPatchMaxCopyBytes: 10 * 1024 * 1024,
|
||||||
MaxRequestBodyBytes: 10 * 1024 * 1024,
|
MaxRequestBodyBytes: 10 * 1024 * 1024,
|
||||||
ComponentGlobalsRegistry: featuregate.DefaultComponentGlobalsRegistry,
|
ComponentGlobalsRegistry: defaultComponentGlobalsRegistry,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ import (
|
||||||
"k8s.io/client-go/discovery"
|
"k8s.io/client-go/discovery"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
cliflag "k8s.io/component-base/cli/flag"
|
cliflag "k8s.io/component-base/cli/flag"
|
||||||
utilversion "k8s.io/component-base/version"
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
"k8s.io/klog/v2/ktesting"
|
"k8s.io/klog/v2/ktesting"
|
||||||
netutils "k8s.io/utils/net"
|
netutils "k8s.io/utils/net"
|
||||||
)
|
)
|
||||||
|
@ -278,7 +278,7 @@ func TestServerRunWithSNI(t *testing.T) {
|
||||||
// launch server
|
// launch server
|
||||||
config := setUp(t)
|
config := setUp(t)
|
||||||
v := fakeVersion()
|
v := fakeVersion()
|
||||||
config.EffectiveVersion = utilversion.NewEffectiveVersion(v.String())
|
config.EffectiveVersion = basecompatibility.NewEffectiveVersionFromString(v.String(), "", "")
|
||||||
|
|
||||||
config.EnableIndex = true
|
config.EnableIndex = true
|
||||||
secureOptions := (&SecureServingOptions{
|
secureOptions := (&SecureServingOptions{
|
||||||
|
|
|
@ -22,7 +22,8 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
apimachineryversion "k8s.io/apimachinery/pkg/util/version"
|
apimachineryversion "k8s.io/apimachinery/pkg/util/version"
|
||||||
version "k8s.io/component-base/version"
|
"k8s.io/apiserver/pkg/util/compatibility"
|
||||||
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ResourceEncodingConfig interface {
|
type ResourceEncodingConfig interface {
|
||||||
|
@ -43,7 +44,7 @@ type DefaultResourceEncodingConfig struct {
|
||||||
// resources records the overriding encoding configs for individual resources.
|
// resources records the overriding encoding configs for individual resources.
|
||||||
resources map[schema.GroupResource]*OverridingResourceEncoding
|
resources map[schema.GroupResource]*OverridingResourceEncoding
|
||||||
scheme *runtime.Scheme
|
scheme *runtime.Scheme
|
||||||
effectiveVersion version.EffectiveVersion
|
effectiveVersion basecompatibility.EffectiveVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
type OverridingResourceEncoding struct {
|
type OverridingResourceEncoding struct {
|
||||||
|
@ -54,7 +55,11 @@ type OverridingResourceEncoding struct {
|
||||||
var _ ResourceEncodingConfig = &DefaultResourceEncodingConfig{}
|
var _ ResourceEncodingConfig = &DefaultResourceEncodingConfig{}
|
||||||
|
|
||||||
func NewDefaultResourceEncodingConfig(scheme *runtime.Scheme) *DefaultResourceEncodingConfig {
|
func NewDefaultResourceEncodingConfig(scheme *runtime.Scheme) *DefaultResourceEncodingConfig {
|
||||||
return &DefaultResourceEncodingConfig{resources: map[schema.GroupResource]*OverridingResourceEncoding{}, scheme: scheme, effectiveVersion: version.DefaultKubeEffectiveVersion()}
|
return NewDefaultResourceEncodingConfigForEffectiveVersion(scheme, compatibility.DefaultComponentGlobalsRegistry.EffectiveVersionFor(basecompatibility.DefaultKubeComponent))
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDefaultResourceEncodingConfigForEffectiveVersion(scheme *runtime.Scheme, effectiveVersion basecompatibility.EffectiveVersion) *DefaultResourceEncodingConfig {
|
||||||
|
return &DefaultResourceEncodingConfig{resources: map[schema.GroupResource]*OverridingResourceEncoding{}, scheme: scheme, effectiveVersion: effectiveVersion}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *DefaultResourceEncodingConfig) SetResourceEncoding(resourceBeingStored schema.GroupResource, externalEncodingVersion, internalVersion schema.GroupVersion) {
|
func (o *DefaultResourceEncodingConfig) SetResourceEncoding(resourceBeingStored schema.GroupResource, externalEncodingVersion, internalVersion schema.GroupVersion) {
|
||||||
|
@ -64,7 +69,7 @@ func (o *DefaultResourceEncodingConfig) SetResourceEncoding(resourceBeingStored
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *DefaultResourceEncodingConfig) SetEffectiveVersion(effectiveVersion version.EffectiveVersion) {
|
func (o *DefaultResourceEncodingConfig) SetEffectiveVersion(effectiveVersion basecompatibility.EffectiveVersion) {
|
||||||
o.effectiveVersion = effectiveVersion
|
o.effectiveVersion = effectiveVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,7 +126,7 @@ type replacementInterface interface {
|
||||||
APILifecycleReplacement() schema.GroupVersionKind
|
APILifecycleReplacement() schema.GroupVersionKind
|
||||||
}
|
}
|
||||||
|
|
||||||
func emulatedStorageVersion(binaryVersionOfResource schema.GroupVersion, example runtime.Object, effectiveVersion version.EffectiveVersion, scheme *runtime.Scheme) (schema.GroupVersion, error) {
|
func emulatedStorageVersion(binaryVersionOfResource schema.GroupVersion, example runtime.Object, effectiveVersion basecompatibility.EffectiveVersion, scheme *runtime.Scheme) (schema.GroupVersion, error) {
|
||||||
if example == nil || effectiveVersion == nil {
|
if example == nil || effectiveVersion == nil {
|
||||||
return binaryVersionOfResource, nil
|
return binaryVersionOfResource, nil
|
||||||
}
|
}
|
||||||
|
@ -172,7 +177,7 @@ func emulatedStorageVersion(binaryVersionOfResource schema.GroupVersion, example
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it was introduced after current compatibility version, don't use it
|
// If it was introduced after current compatibility version, don't use it
|
||||||
// skip the introduced check for test when currentVersion is 0.0 to test all apis
|
// skip the introduced check for test when current compatibility version is 0.0 to test all apis
|
||||||
if introduced, hasIntroduced := exampleOfGVK.(introducedInterface); hasIntroduced && (compatibilityVersion.Major() > 0 || compatibilityVersion.Minor() > 0) {
|
if introduced, hasIntroduced := exampleOfGVK.(introducedInterface); hasIntroduced && (compatibilityVersion.Major() > 0 || compatibilityVersion.Minor() > 0) {
|
||||||
|
|
||||||
// Skip versions that have a replacement.
|
// Skip versions that have a replacement.
|
||||||
|
|
|
@ -25,7 +25,7 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/test"
|
"k8s.io/apimachinery/pkg/test"
|
||||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
utilversion "k8s.io/apimachinery/pkg/util/version"
|
utilversion "k8s.io/apimachinery/pkg/util/version"
|
||||||
"k8s.io/component-base/version"
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEmulatedStorageVersion(t *testing.T) {
|
func TestEmulatedStorageVersion(t *testing.T) {
|
||||||
|
@ -33,21 +33,21 @@ func TestEmulatedStorageVersion(t *testing.T) {
|
||||||
name string
|
name string
|
||||||
scheme *runtime.Scheme
|
scheme *runtime.Scheme
|
||||||
binaryVersion schema.GroupVersion
|
binaryVersion schema.GroupVersion
|
||||||
effectiveVersion version.EffectiveVersion
|
effectiveVersion basecompatibility.EffectiveVersion
|
||||||
want schema.GroupVersion
|
want schema.GroupVersion
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "pick compatible",
|
name: "pick compatible",
|
||||||
scheme: AlphaBetaScheme(utilversion.MustParse("1.31"), utilversion.MustParse("1.32")),
|
scheme: AlphaBetaScheme(utilversion.MustParse("1.31"), utilversion.MustParse("1.32")),
|
||||||
binaryVersion: v1beta1,
|
binaryVersion: v1beta1,
|
||||||
effectiveVersion: version.NewEffectiveVersion("1.32"),
|
effectiveVersion: basecompatibility.NewEffectiveVersionFromString("1.32", "", ""),
|
||||||
want: v1alpha1,
|
want: v1alpha1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "alpha has been replaced, pick binary version",
|
name: "alpha has been replaced, pick binary version",
|
||||||
scheme: AlphaReplacedBetaScheme(utilversion.MustParse("1.31"), utilversion.MustParse("1.32")),
|
scheme: AlphaReplacedBetaScheme(utilversion.MustParse("1.31"), utilversion.MustParse("1.32")),
|
||||||
binaryVersion: v1beta1,
|
binaryVersion: v1beta1,
|
||||||
effectiveVersion: version.NewEffectiveVersion("1.32"),
|
effectiveVersion: basecompatibility.NewEffectiveVersionFromString("1.32", "", ""),
|
||||||
want: v1beta1,
|
want: v1beta1,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ import (
|
||||||
"k8s.io/apiserver/pkg/apis/example2"
|
"k8s.io/apiserver/pkg/apis/example2"
|
||||||
example2install "k8s.io/apiserver/pkg/apis/example2/install"
|
example2install "k8s.io/apiserver/pkg/apis/example2/install"
|
||||||
"k8s.io/apiserver/pkg/storage/storagebackend"
|
"k8s.io/apiserver/pkg/storage/storagebackend"
|
||||||
version "k8s.io/component-base/version"
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -569,8 +569,7 @@ func TestStorageFactoryCompatibilityVersion(t *testing.T) {
|
||||||
|
|
||||||
gvk := gvks[0]
|
gvk := gvks[0]
|
||||||
t.Run(gvk.GroupKind().String()+"@"+tc.effectiveVersion, func(t *testing.T) {
|
t.Run(gvk.GroupKind().String()+"@"+tc.effectiveVersion, func(t *testing.T) {
|
||||||
config := NewDefaultResourceEncodingConfig(sch)
|
config := NewDefaultResourceEncodingConfigForEffectiveVersion(sch, basecompatibility.NewEffectiveVersionFromString(tc.effectiveVersion, "", ""))
|
||||||
config.SetEffectiveVersion(version.NewEffectiveVersion(tc.effectiveVersion))
|
|
||||||
f := NewDefaultStorageFactory(
|
f := NewDefaultStorageFactory(
|
||||||
storagebackend.Config{},
|
storagebackend.Config{},
|
||||||
"",
|
"",
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
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 compatibility
|
||||||
|
|
||||||
|
import (
|
||||||
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
|
)
|
||||||
|
|
||||||
|
// DefaultComponentGlobalsRegistry is the global var to store the effective versions and feature gates for all components for easy access.
|
||||||
|
// Example usage:
|
||||||
|
// // register the component effective version and feature gate first
|
||||||
|
// wardleEffectiveVersion := basecompatibility.NewEffectiveVersion("1.2")
|
||||||
|
// wardleFeatureGate := featuregate.NewFeatureGate()
|
||||||
|
// utilruntime.Must(compatibility.DefaultComponentGlobalsRegistry.Register(apiserver.WardleComponentName, wardleEffectiveVersion, wardleFeatureGate, false))
|
||||||
|
//
|
||||||
|
// cmd := &cobra.Command{
|
||||||
|
// ...
|
||||||
|
// // call DefaultComponentGlobalsRegistry.Set() in PersistentPreRunE to ensure the feature gates are set based on emulation version right after parsing the flags.
|
||||||
|
// PersistentPreRunE: func(*cobra.Command, []string) error {
|
||||||
|
// if err := compatibility.DefaultComponentGlobalsRegistry.Set(); err != nil {
|
||||||
|
// return err
|
||||||
|
// }
|
||||||
|
// ...
|
||||||
|
// },
|
||||||
|
// RunE: func(c *cobra.Command, args []string) error {
|
||||||
|
// // call compatibility.DefaultComponentGlobalsRegistry.Validate() somewhere
|
||||||
|
// },
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// flags := cmd.Flags()
|
||||||
|
// // add flags
|
||||||
|
// compatibility.DefaultComponentGlobalsRegistry.AddFlags(flags)
|
||||||
|
var DefaultComponentGlobalsRegistry basecompatibility.ComponentGlobalsRegistry = basecompatibility.NewComponentGlobalsRegistry()
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
utilruntime.Must(DefaultComponentGlobalsRegistry.Register(basecompatibility.DefaultKubeComponent, DefaultBuildEffectiveVersion(), utilfeature.DefaultMutableFeatureGate))
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
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 compatibility
|
||||||
|
|
||||||
|
import (
|
||||||
|
"k8s.io/apimachinery/pkg/util/version"
|
||||||
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
|
baseversion "k8s.io/component-base/version"
|
||||||
|
)
|
||||||
|
|
||||||
|
// minimumKubeEmulationVersion is the first release emulation version is introduced,
|
||||||
|
// so the emulation version cannot go lower than that.
|
||||||
|
var minimumKubeEmulationVersion *version.Version = version.MajorMinor(1, 31)
|
||||||
|
|
||||||
|
// DefaultBuildEffectiveVersion returns the MutableEffectiveVersion based on the
|
||||||
|
// current build information.
|
||||||
|
func DefaultBuildEffectiveVersion() basecompatibility.MutableEffectiveVersion {
|
||||||
|
binaryVersion := defaultBuildBinaryVersion()
|
||||||
|
useDefaultBuildBinaryVersion := true
|
||||||
|
// fall back to the hard coded kube version only when the git tag is not available for local unit tests.
|
||||||
|
if binaryVersion.Major() == 0 && binaryVersion.Minor() == 0 {
|
||||||
|
useDefaultBuildBinaryVersion = false
|
||||||
|
binaryVersion = version.MustParse(baseversion.DefaultKubeBinaryVersion)
|
||||||
|
}
|
||||||
|
versionFloor := kubeEffectiveVersionFloors(binaryVersion)
|
||||||
|
return basecompatibility.NewEffectiveVersion(binaryVersion, useDefaultBuildBinaryVersion, versionFloor, versionFloor)
|
||||||
|
}
|
||||||
|
|
||||||
|
func kubeEffectiveVersionFloors(binaryVersion *version.Version) *version.Version {
|
||||||
|
// both emulationVersion and minCompatibilityVersion can be set to binaryVersion - 3
|
||||||
|
versionFloor := binaryVersion.WithPatch(0).SubtractMinor(3)
|
||||||
|
if versionFloor.LessThan(minimumKubeEmulationVersion) {
|
||||||
|
versionFloor = minimumKubeEmulationVersion
|
||||||
|
}
|
||||||
|
return versionFloor
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultKubeEffectiveVersionForTest returns the MutableEffectiveVersion based on the
|
||||||
|
// latest K8s release hardcoded in DefaultKubeBinaryVersion.
|
||||||
|
// DefaultKubeBinaryVersion is hard coded because defaultBuildBinaryVersion would return 0.0 when test is run without a git tag.
|
||||||
|
// We do not enforce the N-3..N emulation version range in tests so that the tests would not automatically fail when there is a version bump.
|
||||||
|
// Only used in tests.
|
||||||
|
func DefaultKubeEffectiveVersionForTest() basecompatibility.MutableEffectiveVersion {
|
||||||
|
binaryVersion := version.MustParse(baseversion.DefaultKubeBinaryVersion).WithInfo(baseversion.Get())
|
||||||
|
return basecompatibility.NewEffectiveVersion(binaryVersion, false, version.MustParse("0.0"), version.MustParse("0.0"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func defaultBuildBinaryVersion() *version.Version {
|
||||||
|
verInfo := baseversion.Get()
|
||||||
|
return version.MustParse(verInfo.String()).WithInfo(verInfo)
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
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 compatibility
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/util/version"
|
||||||
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestValidateKubeEffectiveVersion(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
emulationVersion string
|
||||||
|
minCompatibilityVersion string
|
||||||
|
expectErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "valid versions",
|
||||||
|
emulationVersion: "v1.32.0",
|
||||||
|
minCompatibilityVersion: "v1.31.0",
|
||||||
|
expectErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "emulationVersion too low",
|
||||||
|
emulationVersion: "v1.30.0",
|
||||||
|
minCompatibilityVersion: "v1.31.0",
|
||||||
|
expectErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "minCompatibilityVersion too low",
|
||||||
|
emulationVersion: "v1.31.0",
|
||||||
|
minCompatibilityVersion: "v1.30.0",
|
||||||
|
expectErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "both versions too low",
|
||||||
|
emulationVersion: "v1.30.0",
|
||||||
|
minCompatibilityVersion: "v1.29.0",
|
||||||
|
expectErr: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
binaryVersion := version.MustParseGeneric("1.33")
|
||||||
|
versionFloor := kubeEffectiveVersionFloors(binaryVersion)
|
||||||
|
effective := basecompatibility.NewEffectiveVersion(binaryVersion, false, versionFloor, versionFloor)
|
||||||
|
effective.SetEmulationVersion(version.MustParseGeneric(test.emulationVersion))
|
||||||
|
effective.SetMinCompatibilityVersion(version.MustParseGeneric(test.minCompatibilityVersion))
|
||||||
|
|
||||||
|
err := effective.Validate()
|
||||||
|
if test.expectErr && err == nil {
|
||||||
|
t.Error("expected error, but got nil")
|
||||||
|
}
|
||||||
|
if !test.expectErr && err != nil {
|
||||||
|
t.Errorf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue