mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-02 00:07:50 +00:00
add emulated-version flag to kube-scheduler to control the feature gate.
Signed-off-by: Siyuan Zhang <sizhang@google.com>
This commit is contained in:
parent
bb089b9374
commit
40cddbe215
@ -24,9 +24,9 @@ import (
|
||||
|
||||
genericoptions "k8s.io/apiserver/pkg/server/options"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
utilversion "k8s.io/apiserver/pkg/util/version"
|
||||
netutils "k8s.io/utils/net"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/version"
|
||||
controlplaneapiserver "k8s.io/kubernetes/pkg/controlplane/apiserver/options"
|
||||
"k8s.io/kubernetes/pkg/controlplane/reconcilers"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
@ -142,13 +142,10 @@ func (s CompletedOptions) Validate() []error {
|
||||
errs = append(errs, fmt.Errorf("--apiserver-count should be a positive number, but value '%d' provided", s.MasterCount))
|
||||
}
|
||||
|
||||
// TODO: remove in 1.32
|
||||
// emulationVersion is introduced in 1.31, so it is only allowed to be equal to the binary version at 1.31.
|
||||
// TODO(#125980): remove in 1.32
|
||||
effectiveVersion := s.GenericServerRunOptions.ComponentGlobalsRegistry.EffectiveVersionFor(s.GenericServerRunOptions.ComponentName)
|
||||
binaryVersion := version.MajorMinor(effectiveVersion.BinaryVersion().Major(), effectiveVersion.BinaryVersion().Minor())
|
||||
if binaryVersion.EqualTo(version.MajorMinor(1, 31)) && !effectiveVersion.EmulationVersion().EqualTo(binaryVersion) {
|
||||
errs = append(errs, fmt.Errorf("emulation version needs to be equal to binary version(%s) in compatibility-version alpha, got %s",
|
||||
binaryVersion.String(), effectiveVersion.EmulationVersion().String()))
|
||||
if err := utilversion.ValidateKubeEffectiveVersion(effectiveVersion); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
|
||||
return errs
|
||||
|
@ -25,9 +25,11 @@ import (
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/uuid"
|
||||
apiserveroptions "k8s.io/apiserver/pkg/server/options"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
utilversion "k8s.io/apiserver/pkg/util/version"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/dynamic/dynamicinformer"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
@ -72,12 +74,21 @@ type Options struct {
|
||||
|
||||
Master string
|
||||
|
||||
// ComponentGlobalsRegistry is the registry where the effective versions and feature gates for all components are stored.
|
||||
ComponentGlobalsRegistry utilversion.ComponentGlobalsRegistry
|
||||
|
||||
// Flags hold the parsed CLI flags.
|
||||
Flags *cliflag.NamedFlagSets
|
||||
}
|
||||
|
||||
// NewOptions returns default scheduler app options.
|
||||
func NewOptions() *Options {
|
||||
// make sure DefaultKubeComponent is registered in the DefaultComponentGlobalsRegistry.
|
||||
if utilversion.DefaultComponentGlobalsRegistry.EffectiveVersionFor(utilversion.DefaultKubeComponent) == nil {
|
||||
featureGate := utilfeature.DefaultMutableFeatureGate
|
||||
effectiveVersion := utilversion.DefaultKubeEffectiveVersion()
|
||||
utilruntime.Must(utilversion.DefaultComponentGlobalsRegistry.Register(utilversion.DefaultKubeComponent, effectiveVersion, featureGate))
|
||||
}
|
||||
o := &Options{
|
||||
SecureServing: apiserveroptions.NewSecureServingOptions().WithLoopback(),
|
||||
Authentication: apiserveroptions.NewDelegatingAuthenticationOptions(),
|
||||
@ -94,8 +105,9 @@ func NewOptions() *Options {
|
||||
ResourceName: "kube-scheduler",
|
||||
ResourceNamespace: "kube-system",
|
||||
},
|
||||
Metrics: metrics.NewOptions(),
|
||||
Logs: logs.NewOptions(),
|
||||
Metrics: metrics.NewOptions(),
|
||||
Logs: logs.NewOptions(),
|
||||
ComponentGlobalsRegistry: utilversion.DefaultComponentGlobalsRegistry,
|
||||
}
|
||||
|
||||
o.Authentication.TolerateInClusterLookupFailure = true
|
||||
@ -189,7 +201,7 @@ func (o *Options) initFlags() {
|
||||
o.Authorization.AddFlags(nfs.FlagSet("authorization"))
|
||||
o.Deprecated.AddFlags(nfs.FlagSet("deprecated"))
|
||||
options.BindLeaderElectionFlags(o.LeaderElection, nfs.FlagSet("leader election"))
|
||||
utilfeature.DefaultMutableFeatureGate.AddFlag(nfs.FlagSet("feature gate"))
|
||||
o.ComponentGlobalsRegistry.AddFlags(nfs.FlagSet("feature gate"))
|
||||
o.Metrics.AddFlags(nfs.FlagSet("metrics"))
|
||||
logsapi.AddFlags(o.Logs, nfs.FlagSet("logs"))
|
||||
|
||||
@ -198,6 +210,9 @@ func (o *Options) initFlags() {
|
||||
|
||||
// ApplyTo applies the scheduler options to the given scheduler app configuration.
|
||||
func (o *Options) ApplyTo(logger klog.Logger, c *schedulerappconfig.Config) error {
|
||||
if err := o.ComponentGlobalsRegistry.SetFallback(); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(o.ConfigFile) == 0 {
|
||||
// If the --config arg is not specified, honor the deprecated as well as leader election CLI args.
|
||||
o.ApplyDeprecated()
|
||||
@ -251,7 +266,11 @@ func (o *Options) ApplyTo(logger klog.Logger, c *schedulerappconfig.Config) erro
|
||||
// Validate validates all the required options.
|
||||
func (o *Options) Validate() []error {
|
||||
var errs []error
|
||||
|
||||
if err := o.ComponentGlobalsRegistry.SetFallback(); err != nil {
|
||||
errs = append(errs, err)
|
||||
} else {
|
||||
errs = append(errs, o.ComponentGlobalsRegistry.Validate()...)
|
||||
}
|
||||
if err := validation.ValidateKubeSchedulerConfiguration(o.ComponentConfig); err != nil {
|
||||
errs = append(errs, err.Errors()...)
|
||||
}
|
||||
@ -260,6 +279,12 @@ func (o *Options) Validate() []error {
|
||||
errs = append(errs, o.Authorization.Validate()...)
|
||||
errs = append(errs, o.Metrics.Validate()...)
|
||||
|
||||
// TODO(#125980): remove in 1.32
|
||||
effectiveVersion := o.ComponentGlobalsRegistry.EffectiveVersionFor(utilversion.DefaultKubeComponent)
|
||||
if err := utilversion.ValidateKubeEffectiveVersion(effectiveVersion); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
|
||||
return errs
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
apiserveroptions "k8s.io/apiserver/pkg/server/options"
|
||||
utilversion "k8s.io/apiserver/pkg/util/version"
|
||||
componentbaseconfig "k8s.io/component-base/config"
|
||||
"k8s.io/component-base/logs"
|
||||
"k8s.io/klog/v2/ktesting"
|
||||
@ -321,7 +322,8 @@ profiles:
|
||||
AlwaysAllowPaths: []string{"/healthz", "/readyz", "/livez"}, // note: this does not match /healthz/ or /healthz/*
|
||||
AlwaysAllowGroups: []string{"system:masters"},
|
||||
},
|
||||
Logs: logs.NewOptions(),
|
||||
Logs: logs.NewOptions(),
|
||||
ComponentGlobalsRegistry: utilversion.DefaultComponentGlobalsRegistry,
|
||||
},
|
||||
expectedUsername: "config",
|
||||
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
|
||||
@ -372,23 +374,26 @@ profiles:
|
||||
}
|
||||
return cfg
|
||||
}(),
|
||||
Logs: logs.NewOptions(),
|
||||
Logs: logs.NewOptions(),
|
||||
ComponentGlobalsRegistry: utilversion.DefaultComponentGlobalsRegistry,
|
||||
},
|
||||
expectedError: "no kind \"KubeSchedulerConfiguration\" is registered for version \"componentconfig/v1alpha1\"",
|
||||
},
|
||||
{
|
||||
name: "unknown version kubescheduler.config.k8s.io/unknown",
|
||||
options: &Options{
|
||||
ConfigFile: unknownVersionConfig,
|
||||
Logs: logs.NewOptions(),
|
||||
ConfigFile: unknownVersionConfig,
|
||||
Logs: logs.NewOptions(),
|
||||
ComponentGlobalsRegistry: utilversion.DefaultComponentGlobalsRegistry,
|
||||
},
|
||||
expectedError: "no kind \"KubeSchedulerConfiguration\" is registered for version \"kubescheduler.config.k8s.io/unknown\"",
|
||||
},
|
||||
{
|
||||
name: "config file with no version",
|
||||
options: &Options{
|
||||
ConfigFile: noVersionConfig,
|
||||
Logs: logs.NewOptions(),
|
||||
ConfigFile: noVersionConfig,
|
||||
Logs: logs.NewOptions(),
|
||||
ComponentGlobalsRegistry: utilversion.DefaultComponentGlobalsRegistry,
|
||||
},
|
||||
expectedError: "Object 'apiVersion' is missing",
|
||||
},
|
||||
@ -424,7 +429,8 @@ profiles:
|
||||
AlwaysAllowPaths: []string{"/healthz", "/readyz", "/livez"}, // note: this does not match /healthz/ or /healthz/*
|
||||
AlwaysAllowGroups: []string{"system:masters"},
|
||||
},
|
||||
Logs: logs.NewOptions(),
|
||||
Logs: logs.NewOptions(),
|
||||
ComponentGlobalsRegistry: utilversion.DefaultComponentGlobalsRegistry,
|
||||
},
|
||||
expectedUsername: "flag",
|
||||
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
|
||||
@ -496,7 +502,8 @@ profiles:
|
||||
AlwaysAllowPaths: []string{"/healthz", "/readyz", "/livez"}, // note: this does not match /healthz/ or /healthz/*
|
||||
AlwaysAllowGroups: []string{"system:masters"},
|
||||
},
|
||||
Logs: logs.NewOptions(),
|
||||
Logs: logs.NewOptions(),
|
||||
ComponentGlobalsRegistry: utilversion.DefaultComponentGlobalsRegistry,
|
||||
},
|
||||
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
@ -539,8 +546,9 @@ profiles:
|
||||
{
|
||||
name: "plugin config",
|
||||
options: &Options{
|
||||
ConfigFile: pluginConfigFile,
|
||||
Logs: logs.NewOptions(),
|
||||
ConfigFile: pluginConfigFile,
|
||||
Logs: logs.NewOptions(),
|
||||
ComponentGlobalsRegistry: utilversion.DefaultComponentGlobalsRegistry,
|
||||
},
|
||||
expectedUsername: "config",
|
||||
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
|
||||
@ -659,8 +667,9 @@ profiles:
|
||||
{
|
||||
name: "multiple profiles",
|
||||
options: &Options{
|
||||
ConfigFile: multiProfilesConfig,
|
||||
Logs: logs.NewOptions(),
|
||||
ConfigFile: multiProfilesConfig,
|
||||
Logs: logs.NewOptions(),
|
||||
ComponentGlobalsRegistry: utilversion.DefaultComponentGlobalsRegistry,
|
||||
},
|
||||
expectedUsername: "config",
|
||||
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
|
||||
@ -774,15 +783,17 @@ profiles:
|
||||
{
|
||||
name: "no config",
|
||||
options: &Options{
|
||||
Logs: logs.NewOptions(),
|
||||
Logs: logs.NewOptions(),
|
||||
ComponentGlobalsRegistry: utilversion.DefaultComponentGlobalsRegistry,
|
||||
},
|
||||
expectedError: "no configuration has been provided",
|
||||
},
|
||||
{
|
||||
name: "unknown field",
|
||||
options: &Options{
|
||||
ConfigFile: unknownFieldConfig,
|
||||
Logs: logs.NewOptions(),
|
||||
ConfigFile: unknownFieldConfig,
|
||||
Logs: logs.NewOptions(),
|
||||
ComponentGlobalsRegistry: utilversion.DefaultComponentGlobalsRegistry,
|
||||
},
|
||||
expectedError: `unknown field "foo"`,
|
||||
checkErrFn: runtime.IsStrictDecodingError,
|
||||
@ -790,8 +801,9 @@ profiles:
|
||||
{
|
||||
name: "duplicate fields",
|
||||
options: &Options{
|
||||
ConfigFile: duplicateFieldConfig,
|
||||
Logs: logs.NewOptions(),
|
||||
ConfigFile: duplicateFieldConfig,
|
||||
Logs: logs.NewOptions(),
|
||||
ComponentGlobalsRegistry: utilversion.DefaultComponentGlobalsRegistry,
|
||||
},
|
||||
expectedError: `key "leaderElect" already set`,
|
||||
checkErrFn: runtime.IsStrictDecodingError,
|
||||
@ -799,8 +811,9 @@ profiles:
|
||||
{
|
||||
name: "high throughput profile",
|
||||
options: &Options{
|
||||
ConfigFile: highThroughputProfileConfig,
|
||||
Logs: logs.NewOptions(),
|
||||
ConfigFile: highThroughputProfileConfig,
|
||||
Logs: logs.NewOptions(),
|
||||
ComponentGlobalsRegistry: utilversion.DefaultComponentGlobalsRegistry,
|
||||
},
|
||||
expectedUsername: "config",
|
||||
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
|
||||
|
@ -38,6 +38,7 @@ import (
|
||||
"k8s.io/apiserver/pkg/server/mux"
|
||||
"k8s.io/apiserver/pkg/server/routes"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
utilversion "k8s.io/apiserver/pkg/util/version"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
"k8s.io/client-go/tools/events"
|
||||
@ -45,6 +46,7 @@ import (
|
||||
cliflag "k8s.io/component-base/cli/flag"
|
||||
"k8s.io/component-base/cli/globalflag"
|
||||
"k8s.io/component-base/configz"
|
||||
"k8s.io/component-base/featuregate"
|
||||
"k8s.io/component-base/logs"
|
||||
logsapi "k8s.io/component-base/logs/api/v1"
|
||||
"k8s.io/component-base/metrics/features"
|
||||
@ -74,6 +76,10 @@ type Option func(runtime.Registry) error
|
||||
|
||||
// NewSchedulerCommand creates a *cobra.Command object with default parameters and registryOptions
|
||||
func NewSchedulerCommand(registryOptions ...Option) *cobra.Command {
|
||||
// explicitly register (if not already registered) the kube effective version and feature gate in DefaultComponentGlobalsRegistry,
|
||||
// which will be used in NewOptions.
|
||||
_, _ = utilversion.DefaultComponentGlobalsRegistry.ComponentGlobalsOrRegister(
|
||||
utilversion.DefaultKubeComponent, utilversion.DefaultBuildEffectiveVersion(), utilfeature.DefaultMutableFeatureGate)
|
||||
opts := options.NewOptions()
|
||||
|
||||
cmd := &cobra.Command{
|
||||
@ -86,6 +92,10 @@ suitable Node. Multiple different schedulers may be used within a cluster;
|
||||
kube-scheduler is the reference implementation.
|
||||
See [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/)
|
||||
for more information about scheduling and the kube-scheduler component.`,
|
||||
PersistentPreRunE: func(*cobra.Command, []string) error {
|
||||
// makes sure feature gates are set before RunE.
|
||||
return opts.ComponentGlobalsRegistry.Set()
|
||||
},
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runCommand(cmd, opts, registryOptions...)
|
||||
},
|
||||
@ -120,10 +130,10 @@ for more information about scheduling and the kube-scheduler component.`,
|
||||
// runCommand runs the scheduler.
|
||||
func runCommand(cmd *cobra.Command, opts *options.Options, registryOptions ...Option) error {
|
||||
verflag.PrintAndExitIfRequested()
|
||||
|
||||
fg := opts.ComponentGlobalsRegistry.FeatureGateFor(utilversion.DefaultKubeComponent)
|
||||
// Activate logging as soon as possible, after that
|
||||
// show flags with the final logging configuration.
|
||||
if err := logsapi.ValidateAndApply(opts.Logs, utilfeature.DefaultFeatureGate); err != nil {
|
||||
if err := logsapi.ValidateAndApply(opts.Logs, fg); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "%v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
@ -142,7 +152,7 @@ func runCommand(cmd *cobra.Command, opts *options.Options, registryOptions ...Op
|
||||
return err
|
||||
}
|
||||
// add feature enablement metrics
|
||||
utilfeature.DefaultMutableFeatureGate.AddMetrics()
|
||||
fg.(featuregate.MutableFeatureGate).AddMetrics()
|
||||
return Run(ctx, cc, sched)
|
||||
}
|
||||
|
||||
|
@ -32,7 +32,10 @@ import (
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/version"
|
||||
"k8s.io/apiserver/pkg/util/feature"
|
||||
utilversion "k8s.io/apiserver/pkg/util/version"
|
||||
componentbaseconfig "k8s.io/component-base/config"
|
||||
"k8s.io/component-base/featuregate"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
@ -215,6 +218,8 @@ leaderElection:
|
||||
wantPlugins map[string]*config.Plugins
|
||||
wantLeaderElection *componentbaseconfig.LeaderElectionConfiguration
|
||||
wantClientConnection *componentbaseconfig.ClientConnectionConfiguration
|
||||
wantErr bool
|
||||
wantFeaturesGates map[string]bool
|
||||
}{
|
||||
{
|
||||
name: "default config with an alpha feature enabled",
|
||||
@ -376,6 +381,46 @@ leaderElection:
|
||||
ResourceNamespace: configv1.SchedulerDefaultLockObjectNamespace,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "emulated version out of range",
|
||||
flags: []string{
|
||||
"--kubeconfig", configKubeconfig,
|
||||
"--emulated-version=1.28",
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "default feature gates at binary version",
|
||||
flags: []string{
|
||||
"--kubeconfig", configKubeconfig,
|
||||
},
|
||||
wantFeaturesGates: map[string]bool{"kubeA": true, "kubeB": false},
|
||||
},
|
||||
{
|
||||
name: "default feature gates at emulated version",
|
||||
flags: []string{
|
||||
"--kubeconfig", configKubeconfig,
|
||||
"--emulated-version=1.31",
|
||||
},
|
||||
wantFeaturesGates: map[string]bool{"kubeA": false, "kubeB": false},
|
||||
},
|
||||
{
|
||||
name: "set feature gates at emulated version",
|
||||
flags: []string{
|
||||
"--kubeconfig", configKubeconfig,
|
||||
"--emulated-version=1.31",
|
||||
"--feature-gates=kubeA=false,kubeB=true",
|
||||
},
|
||||
wantFeaturesGates: map[string]bool{"kubeA": false, "kubeB": true},
|
||||
},
|
||||
{
|
||||
name: "cannot set locked feature gate",
|
||||
flags: []string{
|
||||
"--kubeconfig", configKubeconfig,
|
||||
"--feature-gates=kubeA=false,kubeB=true",
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
makeListener := func(t *testing.T) net.Listener {
|
||||
@ -392,6 +437,23 @@ leaderElection:
|
||||
for k, v := range tc.restoreFeatures {
|
||||
featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, k, v)
|
||||
}
|
||||
componentGlobalsRegistry := utilversion.DefaultComponentGlobalsRegistry
|
||||
t.Cleanup(func() {
|
||||
componentGlobalsRegistry.Reset()
|
||||
})
|
||||
componentGlobalsRegistry.Reset()
|
||||
verKube := utilversion.NewEffectiveVersion("1.32")
|
||||
fg := feature.DefaultFeatureGate.DeepCopy()
|
||||
utilruntime.Must(fg.AddVersioned(map[featuregate.Feature]featuregate.VersionedSpecs{
|
||||
"kubeA": {
|
||||
{Version: version.MustParse("1.32"), Default: true, LockToDefault: true, PreRelease: featuregate.GA},
|
||||
{Version: version.MustParse("1.30"), Default: false, PreRelease: featuregate.Beta},
|
||||
},
|
||||
"kubeB": {
|
||||
{Version: version.MustParse("1.31"), Default: false, PreRelease: featuregate.Alpha},
|
||||
},
|
||||
}))
|
||||
utilruntime.Must(componentGlobalsRegistry.Register(utilversion.DefaultKubeComponent, verKube, fg))
|
||||
|
||||
fs := pflag.NewFlagSet("test", pflag.PanicOnError)
|
||||
opts := options.NewOptions()
|
||||
@ -415,6 +477,12 @@ leaderElection:
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
_, sched, err := Setup(ctx, opts, tc.registryOptions...)
|
||||
if tc.wantErr {
|
||||
if err == nil {
|
||||
t.Fatal("expected Setup error, got nil")
|
||||
}
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -443,6 +511,12 @@ leaderElection:
|
||||
t.Errorf("Unexpected clientConnection diff (-want, +got): %s", diff)
|
||||
}
|
||||
}
|
||||
for f, v := range tc.wantFeaturesGates {
|
||||
enabled := fg.Enabled(featuregate.Feature(f))
|
||||
if enabled != v {
|
||||
t.Errorf("expected featuregate.Enabled(%s)=%v, got %v", f, v, enabled)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -103,6 +103,9 @@ func StartTestServer(ctx context.Context, customFlags []string) (result TestServ
|
||||
fs.AddFlagSet(f)
|
||||
}
|
||||
fs.Parse(customFlags)
|
||||
if err := opts.ComponentGlobalsRegistry.Set(); err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
if opts.SecureServing.BindPort != 0 {
|
||||
opts.SecureServing.Listener, opts.SecureServing.BindPort, err = createListenerOnFreePort()
|
||||
|
@ -155,3 +155,15 @@ func DefaultKubeEffectiveVersion() MutableEffectiveVersion {
|
||||
binaryVersion := version.MustParse(baseversion.DefaultKubeBinaryVersion).WithInfo(baseversion.Get())
|
||||
return newEffectiveVersion(binaryVersion)
|
||||
}
|
||||
|
||||
// ValidateKubeEffectiveVersion validates the EmulationVersion is equal to the binary version at 1.31 for kube components.
|
||||
// TODO: remove in 1.32
|
||||
// emulationVersion is introduced in 1.31, so it is only allowed to be equal to the binary version at 1.31.
|
||||
func ValidateKubeEffectiveVersion(effectiveVersion EffectiveVersion) error {
|
||||
binaryVersion := version.MajorMinor(effectiveVersion.BinaryVersion().Major(), effectiveVersion.BinaryVersion().Minor())
|
||||
if binaryVersion.EqualTo(version.MajorMinor(1, 31)) && !effectiveVersion.EmulationVersion().EqualTo(binaryVersion) {
|
||||
return fmt.Errorf("emulation version needs to be equal to binary version(%s) in compatibility-version alpha, got %s",
|
||||
binaryVersion.String(), effectiveVersion.EmulationVersion().String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user