mirror of
https://github.com/optim-enterprises-bv/kubernetes.git
synced 2025-11-02 19:28:16 +00:00
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>
This commit is contained in:
@@ -35,10 +35,10 @@ import (
|
|||||||
auditbuffered "k8s.io/apiserver/plugin/pkg/audit/buffered"
|
auditbuffered "k8s.io/apiserver/plugin/pkg/audit/buffered"
|
||||||
audittruncate "k8s.io/apiserver/plugin/pkg/audit/truncate"
|
audittruncate "k8s.io/apiserver/plugin/pkg/audit/truncate"
|
||||||
cliflag "k8s.io/component-base/cli/flag"
|
cliflag "k8s.io/component-base/cli/flag"
|
||||||
|
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"
|
"k8s.io/component-base/metrics"
|
||||||
utilversion "k8s.io/component-base/version"
|
|
||||||
kapi "k8s.io/kubernetes/pkg/apis/core"
|
kapi "k8s.io/kubernetes/pkg/apis/core"
|
||||||
controlplaneapiserver "k8s.io/kubernetes/pkg/controlplane/apiserver/options"
|
controlplaneapiserver "k8s.io/kubernetes/pkg/controlplane/apiserver/options"
|
||||||
"k8s.io/kubernetes/pkg/controlplane/reconcilers"
|
"k8s.io/kubernetes/pkg/controlplane/reconcilers"
|
||||||
@@ -49,14 +49,12 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestAddFlags(t *testing.T) {
|
func TestAddFlags(t *testing.T) {
|
||||||
componentGlobalsRegistry := featuregate.DefaultComponentGlobalsRegistry
|
componentGlobalsRegistry := basecompatibility.NewComponentGlobalsRegistry()
|
||||||
t.Cleanup(func() {
|
|
||||||
componentGlobalsRegistry.Reset()
|
|
||||||
})
|
|
||||||
fs := pflag.NewFlagSet("addflagstest", pflag.PanicOnError)
|
fs := pflag.NewFlagSet("addflagstest", pflag.PanicOnError)
|
||||||
|
|
||||||
utilruntime.Must(componentGlobalsRegistry.Register("test", utilversion.NewEffectiveVersion("1.32"), featuregate.NewFeatureGate()))
|
utilruntime.Must(componentGlobalsRegistry.Register("test", basecompatibility.NewEffectiveVersionFromString("1.32", "1.31", "1.31"), featuregate.NewFeatureGate()))
|
||||||
s := NewServerRunOptions()
|
s := NewServerRunOptions()
|
||||||
|
s.GenericServerRunOptions.ComponentGlobalsRegistry = componentGlobalsRegistry
|
||||||
for _, f := range s.Flags().FlagSets {
|
for _, f := range s.Flags().FlagSets {
|
||||||
fs.AddFlagSet(f)
|
fs.AddFlagSet(f)
|
||||||
}
|
}
|
||||||
@@ -150,7 +148,7 @@ func TestAddFlags(t *testing.T) {
|
|||||||
JSONPatchMaxCopyBytes: int64(3 * 1024 * 1024),
|
JSONPatchMaxCopyBytes: int64(3 * 1024 * 1024),
|
||||||
MaxRequestBodyBytes: int64(3 * 1024 * 1024),
|
MaxRequestBodyBytes: int64(3 * 1024 * 1024),
|
||||||
ComponentGlobalsRegistry: componentGlobalsRegistry,
|
ComponentGlobalsRegistry: componentGlobalsRegistry,
|
||||||
ComponentName: featuregate.DefaultKubeComponent,
|
ComponentName: basecompatibility.DefaultKubeComponent,
|
||||||
},
|
},
|
||||||
Admission: &kubeoptions.AdmissionOptions{
|
Admission: &kubeoptions.AdmissionOptions{
|
||||||
GenericAdmission: &apiserveroptions.AdmissionOptions{
|
GenericAdmission: &apiserveroptions.AdmissionOptions{
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import (
|
|||||||
|
|
||||||
genericoptions "k8s.io/apiserver/pkg/server/options"
|
genericoptions "k8s.io/apiserver/pkg/server/options"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
utilversion "k8s.io/component-base/version"
|
|
||||||
netutils "k8s.io/utils/net"
|
netutils "k8s.io/utils/net"
|
||||||
|
|
||||||
controlplaneapiserver "k8s.io/kubernetes/pkg/controlplane/apiserver/options"
|
controlplaneapiserver "k8s.io/kubernetes/pkg/controlplane/apiserver/options"
|
||||||
@@ -142,10 +141,5 @@ func (s CompletedOptions) Validate() []error {
|
|||||||
errs = append(errs, fmt.Errorf("--apiserver-count should be a positive number, but value '%d' provided", s.MasterCount))
|
errs = append(errs, fmt.Errorf("--apiserver-count should be a positive number, but value '%d' provided", s.MasterCount))
|
||||||
}
|
}
|
||||||
|
|
||||||
effectiveVersion := s.GenericServerRunOptions.ComponentGlobalsRegistry.EffectiveVersionFor(s.GenericServerRunOptions.ComponentName)
|
|
||||||
if err := utilversion.ValidateKubeEffectiveVersion(effectiveVersion); err != nil {
|
|
||||||
errs = append(errs, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return errs
|
return errs
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import (
|
|||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
cliflag "k8s.io/component-base/cli/flag"
|
cliflag "k8s.io/component-base/cli/flag"
|
||||||
"k8s.io/component-base/cli/globalflag"
|
"k8s.io/component-base/cli/globalflag"
|
||||||
|
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"
|
||||||
logsapi "k8s.io/component-base/logs/api/v1"
|
logsapi "k8s.io/component-base/logs/api/v1"
|
||||||
@@ -64,10 +65,9 @@ func init() {
|
|||||||
|
|
||||||
// NewAPIServerCommand creates a *cobra.Command object with default parameters
|
// NewAPIServerCommand creates a *cobra.Command object with default parameters
|
||||||
func NewAPIServerCommand() *cobra.Command {
|
func NewAPIServerCommand() *cobra.Command {
|
||||||
_, featureGate := featuregate.DefaultComponentGlobalsRegistry.ComponentGlobalsOrRegister(
|
|
||||||
featuregate.DefaultKubeComponent, utilversion.DefaultBuildEffectiveVersion(), utilfeature.DefaultMutableFeatureGate)
|
|
||||||
s := options.NewServerRunOptions()
|
s := options.NewServerRunOptions()
|
||||||
ctx := genericapiserver.SetupSignalContext()
|
ctx := genericapiserver.SetupSignalContext()
|
||||||
|
featureGate := s.GenericServerRunOptions.ComponentGlobalsRegistry.FeatureGateFor(basecompatibility.DefaultKubeComponent)
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "kube-apiserver",
|
Use: "kube-apiserver",
|
||||||
@@ -79,7 +79,7 @@ cluster's shared state through which all other components interact.`,
|
|||||||
// stop printing usage when the command errors
|
// stop printing usage when the command errors
|
||||||
SilenceUsage: true,
|
SilenceUsage: true,
|
||||||
PersistentPreRunE: func(*cobra.Command, []string) error {
|
PersistentPreRunE: func(*cobra.Command, []string) error {
|
||||||
if err := featuregate.DefaultComponentGlobalsRegistry.Set(); err != nil {
|
if err := s.GenericServerRunOptions.ComponentGlobalsRegistry.Set(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// silence client-go warnings.
|
// silence client-go warnings.
|
||||||
@@ -108,7 +108,7 @@ cluster's shared state through which all other components interact.`,
|
|||||||
return utilerrors.NewAggregate(errs)
|
return utilerrors.NewAggregate(errs)
|
||||||
}
|
}
|
||||||
// add feature enablement metrics
|
// add feature enablement metrics
|
||||||
featureGate.AddMetrics()
|
featureGate.(featuregate.MutableFeatureGate).AddMetrics()
|
||||||
return Run(ctx, completedOptions)
|
return Run(ctx, completedOptions)
|
||||||
},
|
},
|
||||||
Args: func(cmd *cobra.Command, args []string) error {
|
Args: func(cmd *cobra.Command, args []string) error {
|
||||||
|
|||||||
@@ -43,22 +43,20 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
|
||||||
"k8s.io/apimachinery/pkg/util/version"
|
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
serveroptions "k8s.io/apiserver/pkg/server/options"
|
serveroptions "k8s.io/apiserver/pkg/server/options"
|
||||||
"k8s.io/apiserver/pkg/storage/storagebackend"
|
"k8s.io/apiserver/pkg/storage/storagebackend"
|
||||||
"k8s.io/apiserver/pkg/storageversion"
|
"k8s.io/apiserver/pkg/storageversion"
|
||||||
|
"k8s.io/apiserver/pkg/util/compatibility"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
clientgotransport "k8s.io/client-go/transport"
|
clientgotransport "k8s.io/client-go/transport"
|
||||||
"k8s.io/client-go/util/cert"
|
"k8s.io/client-go/util/cert"
|
||||||
"k8s.io/client-go/util/keyutil"
|
"k8s.io/client-go/util/keyutil"
|
||||||
"k8s.io/component-base/featuregate"
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||||
logsapi "k8s.io/component-base/logs/api/v1"
|
logsapi "k8s.io/component-base/logs/api/v1"
|
||||||
utilversion "k8s.io/component-base/version"
|
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
"k8s.io/kube-aggregator/pkg/apiserver"
|
"k8s.io/kube-aggregator/pkg/apiserver"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
"k8s.io/kubernetes/pkg/features"
|
||||||
@@ -104,11 +102,8 @@ type TestServerInstanceOptions struct {
|
|||||||
// an apiserver version skew scenario where all apiservers use the same proxyCA to verify client connections.
|
// an apiserver version skew scenario where all apiservers use the same proxyCA to verify client connections.
|
||||||
ProxyCA *ProxyCA
|
ProxyCA *ProxyCA
|
||||||
// Set the BinaryVersion of server effective version.
|
// Set the BinaryVersion of server effective version.
|
||||||
// If empty, effective version will default to version.DefaultKubeBinaryVersion.
|
// If empty, effective version will default to DefaultKubeEffectiveVersion.
|
||||||
BinaryVersion string
|
BinaryVersion string
|
||||||
// Set the EmulationVersion of server effective version.
|
|
||||||
// If empty, emulation version will default to the effective version.
|
|
||||||
EmulationVersion string
|
|
||||||
// Set non-default request timeout in the server.
|
// Set non-default request timeout in the server.
|
||||||
RequestTimeout time.Duration
|
RequestTimeout time.Duration
|
||||||
}
|
}
|
||||||
@@ -194,21 +189,20 @@ func StartTestServer(t ktesting.TB, instanceOptions *TestServerInstanceOptions,
|
|||||||
|
|
||||||
fs := pflag.NewFlagSet("test", pflag.PanicOnError)
|
fs := pflag.NewFlagSet("test", pflag.PanicOnError)
|
||||||
|
|
||||||
featureGate := utilfeature.DefaultMutableFeatureGate
|
featureGate := utilfeature.DefaultMutableFeatureGate.DeepCopy()
|
||||||
featureGate.AddMetrics()
|
effectiveVersion := compatibility.DefaultKubeEffectiveVersionForTest()
|
||||||
effectiveVersion := utilversion.DefaultKubeEffectiveVersion()
|
|
||||||
if instanceOptions.BinaryVersion != "" {
|
if instanceOptions.BinaryVersion != "" {
|
||||||
effectiveVersion = utilversion.NewEffectiveVersion(instanceOptions.BinaryVersion)
|
effectiveVersion = basecompatibility.NewEffectiveVersionFromString(instanceOptions.BinaryVersion, "", "")
|
||||||
}
|
}
|
||||||
if instanceOptions.EmulationVersion != "" {
|
effectiveVersion.SetEmulationVersion(featureGate.EmulationVersion())
|
||||||
effectiveVersion.SetEmulationVersion(version.MustParse(instanceOptions.EmulationVersion))
|
componentGlobalsRegistry := basecompatibility.NewComponentGlobalsRegistry()
|
||||||
|
if err := componentGlobalsRegistry.Register(basecompatibility.DefaultKubeComponent, effectiveVersion, featureGate); err != nil {
|
||||||
|
return result, err
|
||||||
}
|
}
|
||||||
// need to call SetFeatureGateEmulationVersionDuringTest to reset the feature gate emulation version at the end of the test.
|
|
||||||
featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, featureGate, effectiveVersion.EmulationVersion())
|
|
||||||
featuregate.DefaultComponentGlobalsRegistry.Reset()
|
|
||||||
utilruntime.Must(featuregate.DefaultComponentGlobalsRegistry.Register(featuregate.DefaultKubeComponent, effectiveVersion, featureGate))
|
|
||||||
|
|
||||||
s := options.NewServerRunOptions()
|
s := options.NewServerRunOptions()
|
||||||
|
// set up new instance of ComponentGlobalsRegistry instead of using the DefaultComponentGlobalsRegistry to avoid contention in parallel tests.
|
||||||
|
s.Options.GenericServerRunOptions.ComponentGlobalsRegistry = componentGlobalsRegistry
|
||||||
if instanceOptions.RequestTimeout > 0 {
|
if instanceOptions.RequestTimeout > 0 {
|
||||||
s.GenericServerRunOptions.RequestTimeout = instanceOptions.RequestTimeout
|
s.GenericServerRunOptions.RequestTimeout = instanceOptions.RequestTimeout
|
||||||
}
|
}
|
||||||
@@ -330,15 +324,6 @@ func StartTestServer(t ktesting.TB, instanceOptions *TestServerInstanceOptions,
|
|||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
s.Authentication.ClientCert.ClientCA = clientCACertFile
|
s.Authentication.ClientCert.ClientCA = clientCACertFile
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.UnknownVersionInteroperabilityProxy) {
|
|
||||||
// TODO: set up a general clean up for testserver
|
|
||||||
if clientgotransport.DialerStopCh == wait.NeverStop {
|
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Hour)
|
|
||||||
t.Cleanup(cancel)
|
|
||||||
clientgotransport.DialerStopCh = ctx.Done()
|
|
||||||
}
|
|
||||||
s.PeerCAFile = filepath.Join(s.SecureServing.ServerCert.CertDirectory, s.SecureServing.ServerCert.PairName+".crt")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s.SecureServing.ExternalAddress = s.SecureServing.Listener.Addr().(*net.TCPAddr).IP // use listener addr although it is a loopback device
|
s.SecureServing.ExternalAddress = s.SecureServing.Listener.Addr().(*net.TCPAddr).IP // use listener addr although it is a loopback device
|
||||||
@@ -374,8 +359,32 @@ func StartTestServer(t ktesting.TB, instanceOptions *TestServerInstanceOptions,
|
|||||||
s.Authentication.RequestHeader.ExtraHeaderPrefixes = extraHeaders
|
s.Authentication.RequestHeader.ExtraHeaderPrefixes = extraHeaders
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := featuregate.DefaultComponentGlobalsRegistry.Set(); err != nil {
|
if err := componentGlobalsRegistry.Set(); err != nil {
|
||||||
return result, err
|
return result, fmt.Errorf("%w\nIf you are using SetFeatureGate*DuringTest, try using --emulated-version and --feature-gates flags instead", err)
|
||||||
|
}
|
||||||
|
// If the local ComponentGlobalsRegistry is changed by the flags,
|
||||||
|
// we need to copy the new feature values back to the DefaultFeatureGate because most feature checks still use the DefaultFeatureGate.
|
||||||
|
// We cannot directly use DefaultFeatureGate in ComponentGlobalsRegistry because the changes done by ComponentGlobalsRegistry.Set() will not be undone at the end of the test.
|
||||||
|
if !featureGate.EmulationVersion().EqualTo(utilfeature.DefaultMutableFeatureGate.EmulationVersion()) {
|
||||||
|
featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultMutableFeatureGate, effectiveVersion.EmulationVersion())
|
||||||
|
}
|
||||||
|
for f := range utilfeature.DefaultMutableFeatureGate.GetAll() {
|
||||||
|
if featureGate.Enabled(f) != utilfeature.DefaultFeatureGate.Enabled(f) {
|
||||||
|
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, f, featureGate.Enabled(f))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
utilfeature.DefaultMutableFeatureGate.AddMetrics()
|
||||||
|
|
||||||
|
if instanceOptions.EnableCertAuth {
|
||||||
|
if featureGate.Enabled(features.UnknownVersionInteroperabilityProxy) {
|
||||||
|
// TODO: set up a general clean up for testserver
|
||||||
|
if clientgotransport.DialerStopCh == wait.NeverStop {
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), time.Hour)
|
||||||
|
t.Cleanup(cancel)
|
||||||
|
clientgotransport.DialerStopCh = ctx.Done()
|
||||||
|
}
|
||||||
|
s.PeerCAFile = filepath.Join(s.SecureServing.ServerCert.CertDirectory, s.SecureServing.ServerCert.PairName+".crt")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
saSigningKeyFile, err := os.CreateTemp("/tmp", "insecure_test_key")
|
saSigningKeyFile, err := os.CreateTemp("/tmp", "insecure_test_key")
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import (
|
|||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/tools/record"
|
"k8s.io/client-go/tools/record"
|
||||||
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
kubectrlmgrconfig "k8s.io/kubernetes/pkg/controller/apis/config"
|
kubectrlmgrconfig "k8s.io/kubernetes/pkg/controller/apis/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -43,6 +44,9 @@ type Config struct {
|
|||||||
|
|
||||||
EventBroadcaster record.EventBroadcaster
|
EventBroadcaster record.EventBroadcaster
|
||||||
EventRecorder record.EventRecorder
|
EventRecorder record.EventRecorder
|
||||||
|
|
||||||
|
// ComponentGlobalsRegistry is the registry where the effective versions and feature gates for all components are stored.
|
||||||
|
ComponentGlobalsRegistry basecompatibility.ComponentGlobalsRegistry
|
||||||
}
|
}
|
||||||
|
|
||||||
type completedConfig struct {
|
type completedConfig struct {
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ import (
|
|||||||
"k8s.io/client-go/util/keyutil"
|
"k8s.io/client-go/util/keyutil"
|
||||||
cliflag "k8s.io/component-base/cli/flag"
|
cliflag "k8s.io/component-base/cli/flag"
|
||||||
"k8s.io/component-base/cli/globalflag"
|
"k8s.io/component-base/cli/globalflag"
|
||||||
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
"k8s.io/component-base/configz"
|
"k8s.io/component-base/configz"
|
||||||
"k8s.io/component-base/featuregate"
|
"k8s.io/component-base/featuregate"
|
||||||
"k8s.io/component-base/logs"
|
"k8s.io/component-base/logs"
|
||||||
@@ -99,9 +100,6 @@ const (
|
|||||||
|
|
||||||
// NewControllerManagerCommand creates a *cobra.Command object with default parameters
|
// NewControllerManagerCommand creates a *cobra.Command object with default parameters
|
||||||
func NewControllerManagerCommand() *cobra.Command {
|
func NewControllerManagerCommand() *cobra.Command {
|
||||||
_, _ = featuregate.DefaultComponentGlobalsRegistry.ComponentGlobalsOrRegister(
|
|
||||||
featuregate.DefaultKubeComponent, utilversion.DefaultBuildEffectiveVersion(), utilfeature.DefaultMutableFeatureGate)
|
|
||||||
|
|
||||||
s, err := options.NewKubeControllerManagerOptions()
|
s, err := options.NewKubeControllerManagerOptions()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Background().Error(err, "Unable to initialize command options")
|
klog.Background().Error(err, "Unable to initialize command options")
|
||||||
@@ -142,7 +140,7 @@ controller, and serviceaccounts controller.`,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add feature enablement metrics
|
// add feature enablement metrics
|
||||||
fg := s.ComponentGlobalsRegistry.FeatureGateFor(featuregate.DefaultKubeComponent)
|
fg := s.ComponentGlobalsRegistry.FeatureGateFor(basecompatibility.DefaultKubeComponent)
|
||||||
fg.(featuregate.MutableFeatureGate).AddMetrics()
|
fg.(featuregate.MutableFeatureGate).AddMetrics()
|
||||||
return Run(context.Background(), c.Complete())
|
return Run(context.Background(), c.Complete())
|
||||||
},
|
},
|
||||||
@@ -218,7 +216,7 @@ func Run(ctx context.Context, c *config.CompletedConfig) error {
|
|||||||
slis.SLIMetricsWithReset{}.Install(unsecuredMux)
|
slis.SLIMetricsWithReset{}.Install(unsecuredMux)
|
||||||
|
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(zpagesfeatures.ComponentStatusz) {
|
if utilfeature.DefaultFeatureGate.Enabled(zpagesfeatures.ComponentStatusz) {
|
||||||
statusz.Install(unsecuredMux, kubeControllerManager, statusz.NewRegistry())
|
statusz.Install(unsecuredMux, kubeControllerManager, statusz.NewRegistry(c.ComponentGlobalsRegistry.EffectiveVersionFor(basecompatibility.DefaultKubeComponent)))
|
||||||
}
|
}
|
||||||
|
|
||||||
handler := genericcontrollermanager.BuildHandlerChain(unsecuredMux, &c.Authorization, &c.Authentication)
|
handler := genericcontrollermanager.BuildHandlerChain(unsecuredMux, &c.Authorization, &c.Authentication)
|
||||||
@@ -289,11 +287,11 @@ func Run(ctx context.Context, c *config.CompletedConfig) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(kubefeatures.CoordinatedLeaderElection) {
|
if utilfeature.DefaultFeatureGate.Enabled(kubefeatures.CoordinatedLeaderElection) {
|
||||||
binaryVersion, err := semver.ParseTolerant(featuregate.DefaultComponentGlobalsRegistry.EffectiveVersionFor(featuregate.DefaultKubeComponent).BinaryVersion().String())
|
binaryVersion, err := semver.ParseTolerant(c.ComponentGlobalsRegistry.EffectiveVersionFor(basecompatibility.DefaultKubeComponent).BinaryVersion().String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
emulationVersion, err := semver.ParseTolerant(featuregate.DefaultComponentGlobalsRegistry.EffectiveVersionFor(featuregate.DefaultKubeComponent).EmulationVersion().String())
|
emulationVersion, err := semver.ParseTolerant(c.ComponentGlobalsRegistry.EffectiveVersionFor(basecompatibility.DefaultKubeComponent).EmulationVersion().String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import (
|
|||||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
apiserveroptions "k8s.io/apiserver/pkg/server/options"
|
apiserveroptions "k8s.io/apiserver/pkg/server/options"
|
||||||
|
"k8s.io/apiserver/pkg/util/compatibility"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
clientgofeaturegate "k8s.io/client-go/features"
|
clientgofeaturegate "k8s.io/client-go/features"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
@@ -36,11 +37,11 @@ import (
|
|||||||
cpnames "k8s.io/cloud-provider/names"
|
cpnames "k8s.io/cloud-provider/names"
|
||||||
cpoptions "k8s.io/cloud-provider/options"
|
cpoptions "k8s.io/cloud-provider/options"
|
||||||
cliflag "k8s.io/component-base/cli/flag"
|
cliflag "k8s.io/component-base/cli/flag"
|
||||||
|
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"
|
||||||
logsapi "k8s.io/component-base/logs/api/v1"
|
logsapi "k8s.io/component-base/logs/api/v1"
|
||||||
"k8s.io/component-base/metrics"
|
"k8s.io/component-base/metrics"
|
||||||
utilversion "k8s.io/component-base/version"
|
|
||||||
cmoptions "k8s.io/controller-manager/options"
|
cmoptions "k8s.io/controller-manager/options"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
kubectrlmgrconfigv1alpha1 "k8s.io/kube-controller-manager/config/v1alpha1"
|
kubectrlmgrconfigv1alpha1 "k8s.io/kube-controller-manager/config/v1alpha1"
|
||||||
@@ -106,7 +107,7 @@ type KubeControllerManagerOptions struct {
|
|||||||
ShowHiddenMetricsForVersion string
|
ShowHiddenMetricsForVersion string
|
||||||
|
|
||||||
// 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
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewKubeControllerManagerOptions creates a new KubeControllerManagerOptions with a default config.
|
// NewKubeControllerManagerOptions creates a new KubeControllerManagerOptions with a default config.
|
||||||
@@ -116,10 +117,12 @@ func NewKubeControllerManagerOptions() (*KubeControllerManagerOptions, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if featuregate.DefaultComponentGlobalsRegistry.EffectiveVersionFor(featuregate.DefaultKubeComponent) == nil {
|
componentGlobalsRegistry := compatibility.DefaultComponentGlobalsRegistry
|
||||||
|
|
||||||
|
if componentGlobalsRegistry.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(componentGlobalsRegistry.Register(basecompatibility.DefaultKubeComponent, effectiveVersion, featureGate))
|
||||||
}
|
}
|
||||||
|
|
||||||
s := KubeControllerManagerOptions{
|
s := KubeControllerManagerOptions{
|
||||||
@@ -211,7 +214,7 @@ func NewKubeControllerManagerOptions() (*KubeControllerManagerOptions, error) {
|
|||||||
Authorization: apiserveroptions.NewDelegatingAuthorizationOptions(),
|
Authorization: apiserveroptions.NewDelegatingAuthorizationOptions(),
|
||||||
Metrics: metrics.NewOptions(),
|
Metrics: metrics.NewOptions(),
|
||||||
Logs: logs.NewOptions(),
|
Logs: logs.NewOptions(),
|
||||||
ComponentGlobalsRegistry: featuregate.DefaultComponentGlobalsRegistry,
|
ComponentGlobalsRegistry: componentGlobalsRegistry,
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Authentication.RemoteKubeConfigFileOptional = true
|
s.Authentication.RemoteKubeConfigFileOptional = true
|
||||||
@@ -230,7 +233,6 @@ func NewKubeControllerManagerOptions() (*KubeControllerManagerOptions, error) {
|
|||||||
s.GarbageCollectorController.GCIgnoredResources = gcIgnoredResources
|
s.GarbageCollectorController.GCIgnoredResources = gcIgnoredResources
|
||||||
s.Generic.LeaderElection.ResourceName = "kube-controller-manager"
|
s.Generic.LeaderElection.ResourceName = "kube-controller-manager"
|
||||||
s.Generic.LeaderElection.ResourceNamespace = "kube-system"
|
s.Generic.LeaderElection.ResourceNamespace = "kube-system"
|
||||||
|
|
||||||
return &s, nil
|
return &s, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -452,7 +454,6 @@ func (s *KubeControllerManagerOptions) Validate(allControllers []string, disable
|
|||||||
errs = append(errs, s.Authentication.Validate()...)
|
errs = append(errs, s.Authentication.Validate()...)
|
||||||
errs = append(errs, s.Authorization.Validate()...)
|
errs = append(errs, s.Authorization.Validate()...)
|
||||||
errs = append(errs, s.Metrics.Validate()...)
|
errs = append(errs, s.Metrics.Validate()...)
|
||||||
errs = append(errs, utilversion.ValidateKubeEffectiveVersion(s.ComponentGlobalsRegistry.EffectiveVersionFor(featuregate.DefaultKubeComponent)))
|
|
||||||
|
|
||||||
// in-tree cloud providers are disabled since v1.31 (KEP-2395)
|
// in-tree cloud providers are disabled since v1.31 (KEP-2395)
|
||||||
if len(s.KubeCloudShared.CloudProvider.Name) > 0 && !cloudprovider.IsExternal(s.KubeCloudShared.CloudProvider.Name) {
|
if len(s.KubeCloudShared.CloudProvider.Name) > 0 && !cloudprovider.IsExternal(s.KubeCloudShared.CloudProvider.Name) {
|
||||||
@@ -502,6 +503,7 @@ func (s KubeControllerManagerOptions) Config(allControllers []string, disabledBy
|
|||||||
Kubeconfig: kubeconfig,
|
Kubeconfig: kubeconfig,
|
||||||
EventBroadcaster: eventBroadcaster,
|
EventBroadcaster: eventBroadcaster,
|
||||||
EventRecorder: eventRecorder,
|
EventRecorder: eventRecorder,
|
||||||
|
ComponentGlobalsRegistry: s.ComponentGlobalsRegistry,
|
||||||
}
|
}
|
||||||
if err := s.ApplyTo(c, allControllers, disabledByDefaultControllers, controllerAliases); err != nil {
|
if err := s.ApplyTo(c, allControllers, disabledByDefaultControllers, controllerAliases); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ import (
|
|||||||
|
|
||||||
"k8s.io/apiserver/pkg/apis/apiserver"
|
"k8s.io/apiserver/pkg/apis/apiserver"
|
||||||
apiserveroptions "k8s.io/apiserver/pkg/server/options"
|
apiserveroptions "k8s.io/apiserver/pkg/server/options"
|
||||||
utilversion "k8s.io/component-base/version"
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
|
|
||||||
componentbaseconfig "k8s.io/component-base/config"
|
componentbaseconfig "k8s.io/component-base/config"
|
||||||
"k8s.io/component-base/featuregate"
|
"k8s.io/component-base/featuregate"
|
||||||
@@ -450,7 +450,8 @@ func TestAddFlags(t *testing.T) {
|
|||||||
Master: "192.168.4.20",
|
Master: "192.168.4.20",
|
||||||
Metrics: &metrics.Options{},
|
Metrics: &metrics.Options{},
|
||||||
Logs: logs.NewOptions(),
|
Logs: logs.NewOptions(),
|
||||||
ComponentGlobalsRegistry: featuregate.DefaultComponentGlobalsRegistry,
|
// ignores comparing ComponentGlobalsRegistry in this test.
|
||||||
|
ComponentGlobalsRegistry: s.ComponentGlobalsRegistry,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort GCIgnoredResources because it's built from a map, which means the
|
// Sort GCIgnoredResources because it's built from a map, which means the
|
||||||
@@ -736,27 +737,6 @@ func TestApplyTo(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestEmulatedVersion(t *testing.T) {
|
func TestEmulatedVersion(t *testing.T) {
|
||||||
var cleanupAndSetupFunc = func() featuregate.FeatureGate {
|
|
||||||
componentGlobalsRegistry := featuregate.DefaultComponentGlobalsRegistry
|
|
||||||
componentGlobalsRegistry.Reset() // make sure this test have a clean state
|
|
||||||
t.Cleanup(func() {
|
|
||||||
componentGlobalsRegistry.Reset() // make sure this test doesn't leak a dirty state
|
|
||||||
})
|
|
||||||
|
|
||||||
verKube := utilversion.NewEffectiveVersion("1.32")
|
|
||||||
fg := featuregate.NewVersionedFeatureGate(version.MustParse("1.32"))
|
|
||||||
utilruntime.Must(fg.AddVersioned(map[featuregate.Feature]featuregate.VersionedSpecs{
|
|
||||||
"kubeA": {
|
|
||||||
{Version: version.MustParse("1.30"), Default: false, PreRelease: featuregate.Beta},
|
|
||||||
{Version: version.MustParse("1.32"), Default: true, LockToDefault: true, PreRelease: featuregate.GA},
|
|
||||||
},
|
|
||||||
"kubeB": {
|
|
||||||
{Version: version.MustParse("1.31"), Default: false, PreRelease: featuregate.Alpha},
|
|
||||||
},
|
|
||||||
}))
|
|
||||||
utilruntime.Must(componentGlobalsRegistry.Register(featuregate.DefaultKubeComponent, verKube, fg))
|
|
||||||
return fg
|
|
||||||
}
|
|
||||||
|
|
||||||
testcases := []struct {
|
testcases := []struct {
|
||||||
name string
|
name string
|
||||||
@@ -808,9 +788,8 @@ func TestEmulatedVersion(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range testcases {
|
for _, tc := range testcases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
fg := cleanupAndSetupFunc()
|
|
||||||
|
|
||||||
fs, s := setupControllerManagerFlagSet(t)
|
fs, s := setupControllerManagerFlagSet(t)
|
||||||
|
fg := s.ComponentGlobalsRegistry.FeatureGateFor(basecompatibility.DefaultKubeComponent)
|
||||||
err := fs.Parse(tc.flags)
|
err := fs.Parse(tc.flags)
|
||||||
checkTestError(t, err, false, "")
|
checkTestError(t, err, false, "")
|
||||||
err = s.Validate([]string{""}, []string{""}, nil)
|
err = s.Validate([]string{""}, []string{""}, nil)
|
||||||
@@ -1558,6 +1537,22 @@ func setupControllerManagerFlagSet(t *testing.T) (*pflag.FlagSet, *KubeControlle
|
|||||||
t.Fatal(fmt.Errorf("NewKubeControllerManagerOptions failed with %w", err))
|
t.Fatal(fmt.Errorf("NewKubeControllerManagerOptions failed with %w", err))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
componentGlobalsRegistry := basecompatibility.NewComponentGlobalsRegistry()
|
||||||
|
|
||||||
|
verKube := basecompatibility.NewEffectiveVersionFromString("1.32", "1.31", "1.31")
|
||||||
|
fg := featuregate.NewVersionedFeatureGate(version.MustParse("1.32"))
|
||||||
|
utilruntime.Must(fg.AddVersioned(map[featuregate.Feature]featuregate.VersionedSpecs{
|
||||||
|
"kubeA": {
|
||||||
|
{Version: version.MustParse("1.30"), Default: false, PreRelease: featuregate.Beta},
|
||||||
|
{Version: version.MustParse("1.32"), Default: true, LockToDefault: true, PreRelease: featuregate.GA},
|
||||||
|
},
|
||||||
|
"kubeB": {
|
||||||
|
{Version: version.MustParse("1.31"), Default: false, PreRelease: featuregate.Alpha},
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
utilruntime.Must(componentGlobalsRegistry.Register(basecompatibility.DefaultKubeComponent, verKube, fg))
|
||||||
|
s.ComponentGlobalsRegistry = componentGlobalsRegistry
|
||||||
|
|
||||||
for _, f := range s.Flags([]string{""}, []string{""}, nil).FlagSets {
|
for _, f := range s.Flags([]string{""}, []string{""}, nil).FlagSets {
|
||||||
fs.AddFlagSet(f)
|
fs.AddFlagSet(f)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import (
|
|||||||
"k8s.io/apiserver/pkg/server/healthz"
|
"k8s.io/apiserver/pkg/server/healthz"
|
||||||
"k8s.io/apiserver/pkg/server/mux"
|
"k8s.io/apiserver/pkg/server/mux"
|
||||||
"k8s.io/apiserver/pkg/server/routes"
|
"k8s.io/apiserver/pkg/server/routes"
|
||||||
|
"k8s.io/apiserver/pkg/util/compatibility"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
@@ -474,7 +475,7 @@ func serveMetrics(ctx context.Context, bindAddress string, proxyMode kubeproxyco
|
|||||||
}
|
}
|
||||||
|
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(zpagesfeatures.ComponentStatusz) {
|
if utilfeature.DefaultFeatureGate.Enabled(zpagesfeatures.ComponentStatusz) {
|
||||||
statusz.Install(proxyMux, kubeProxy, statusz.NewRegistry())
|
statusz.Install(proxyMux, kubeProxy, statusz.NewRegistry(compatibility.DefaultBuildEffectiveVersion()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn := func() {
|
fn := func() {
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import (
|
|||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/tools/events"
|
"k8s.io/client-go/tools/events"
|
||||||
"k8s.io/client-go/tools/leaderelection"
|
"k8s.io/client-go/tools/leaderelection"
|
||||||
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
"k8s.io/component-base/zpages/flagz"
|
"k8s.io/component-base/zpages/flagz"
|
||||||
kubeschedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config"
|
kubeschedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||||
)
|
)
|
||||||
@@ -61,6 +62,9 @@ type Config struct {
|
|||||||
// value, the pod will be moved from unschedulablePods to backoffQ or activeQ.
|
// value, the pod will be moved from unschedulablePods to backoffQ or activeQ.
|
||||||
// If this value is empty, the default value (5min) will be used.
|
// If this value is empty, the default value (5min) will be used.
|
||||||
PodMaxInUnschedulablePodsDuration time.Duration
|
PodMaxInUnschedulablePodsDuration time.Duration
|
||||||
|
|
||||||
|
// ComponentGlobalsRegistry is the registry where the effective versions and feature gates for all components are stored.
|
||||||
|
ComponentGlobalsRegistry basecompatibility.ComponentGlobalsRegistry
|
||||||
}
|
}
|
||||||
|
|
||||||
type completedConfig struct {
|
type completedConfig struct {
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import (
|
|||||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||||
"k8s.io/apimachinery/pkg/util/uuid"
|
"k8s.io/apimachinery/pkg/util/uuid"
|
||||||
apiserveroptions "k8s.io/apiserver/pkg/server/options"
|
apiserveroptions "k8s.io/apiserver/pkg/server/options"
|
||||||
|
"k8s.io/apiserver/pkg/util/compatibility"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/client-go/dynamic"
|
"k8s.io/client-go/dynamic"
|
||||||
"k8s.io/client-go/dynamic/dynamicinformer"
|
"k8s.io/client-go/dynamic/dynamicinformer"
|
||||||
@@ -39,13 +40,12 @@ import (
|
|||||||
"k8s.io/client-go/tools/leaderelection/resourcelock"
|
"k8s.io/client-go/tools/leaderelection/resourcelock"
|
||||||
"k8s.io/client-go/tools/record"
|
"k8s.io/client-go/tools/record"
|
||||||
cliflag "k8s.io/component-base/cli/flag"
|
cliflag "k8s.io/component-base/cli/flag"
|
||||||
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
componentbaseconfig "k8s.io/component-base/config"
|
componentbaseconfig "k8s.io/component-base/config"
|
||||||
"k8s.io/component-base/config/options"
|
"k8s.io/component-base/config/options"
|
||||||
"k8s.io/component-base/featuregate"
|
|
||||||
"k8s.io/component-base/logs"
|
"k8s.io/component-base/logs"
|
||||||
logsapi "k8s.io/component-base/logs/api/v1"
|
logsapi "k8s.io/component-base/logs/api/v1"
|
||||||
"k8s.io/component-base/metrics"
|
"k8s.io/component-base/metrics"
|
||||||
utilversion "k8s.io/component-base/version"
|
|
||||||
zpagesfeatures "k8s.io/component-base/zpages/features"
|
zpagesfeatures "k8s.io/component-base/zpages/features"
|
||||||
"k8s.io/component-base/zpages/flagz"
|
"k8s.io/component-base/zpages/flagz"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
@@ -78,7 +78,7 @@ type Options struct {
|
|||||||
Master string
|
Master string
|
||||||
|
|
||||||
// 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
|
||||||
|
|
||||||
// Flags hold the parsed CLI flags.
|
// Flags hold the parsed CLI flags.
|
||||||
Flags *cliflag.NamedFlagSets
|
Flags *cliflag.NamedFlagSets
|
||||||
@@ -86,12 +86,17 @@ type Options struct {
|
|||||||
|
|
||||||
// NewOptions returns default scheduler app options.
|
// NewOptions returns default scheduler app options.
|
||||||
func NewOptions() *Options {
|
func NewOptions() *Options {
|
||||||
|
componentGlobalsRegistry := compatibility.DefaultComponentGlobalsRegistry
|
||||||
// make sure DefaultKubeComponent is registered in the DefaultComponentGlobalsRegistry.
|
// make sure DefaultKubeComponent is registered in the DefaultComponentGlobalsRegistry.
|
||||||
if featuregate.DefaultComponentGlobalsRegistry.EffectiveVersionFor(featuregate.DefaultKubeComponent) == nil {
|
if componentGlobalsRegistry.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(componentGlobalsRegistry.Register(basecompatibility.DefaultKubeComponent, effectiveVersion, featureGate))
|
||||||
}
|
}
|
||||||
|
return NewOptionsWithComponentGlobalsRegistry(componentGlobalsRegistry)
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewOptionsWithComponentGlobalsRegistry(componentGlobalsRegistry basecompatibility.ComponentGlobalsRegistry) *Options {
|
||||||
o := &Options{
|
o := &Options{
|
||||||
SecureServing: apiserveroptions.NewSecureServingOptions().WithLoopback(),
|
SecureServing: apiserveroptions.NewSecureServingOptions().WithLoopback(),
|
||||||
Authentication: apiserveroptions.NewDelegatingAuthenticationOptions(),
|
Authentication: apiserveroptions.NewDelegatingAuthenticationOptions(),
|
||||||
@@ -110,7 +115,7 @@ func NewOptions() *Options {
|
|||||||
},
|
},
|
||||||
Metrics: metrics.NewOptions(),
|
Metrics: metrics.NewOptions(),
|
||||||
Logs: logs.NewOptions(),
|
Logs: logs.NewOptions(),
|
||||||
ComponentGlobalsRegistry: featuregate.DefaultComponentGlobalsRegistry,
|
ComponentGlobalsRegistry: componentGlobalsRegistry,
|
||||||
}
|
}
|
||||||
|
|
||||||
o.Authentication.TolerateInClusterLookupFailure = true
|
o.Authentication.TolerateInClusterLookupFailure = true
|
||||||
@@ -287,11 +292,6 @@ func (o *Options) Validate() []error {
|
|||||||
errs = append(errs, o.Authorization.Validate()...)
|
errs = append(errs, o.Authorization.Validate()...)
|
||||||
errs = append(errs, o.Metrics.Validate()...)
|
errs = append(errs, o.Metrics.Validate()...)
|
||||||
|
|
||||||
effectiveVersion := o.ComponentGlobalsRegistry.EffectiveVersionFor(featuregate.DefaultKubeComponent)
|
|
||||||
if err := utilversion.ValidateKubeEffectiveVersion(effectiveVersion); err != nil {
|
|
||||||
errs = append(errs, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return errs
|
return errs
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,6 +337,7 @@ func (o *Options) Config(ctx context.Context) (*schedulerappconfig.Config, error
|
|||||||
dynClient := dynamic.NewForConfigOrDie(c.KubeConfig)
|
dynClient := dynamic.NewForConfigOrDie(c.KubeConfig)
|
||||||
c.DynInformerFactory = dynamicinformer.NewFilteredDynamicSharedInformerFactory(dynClient, 0, corev1.NamespaceAll, nil)
|
c.DynInformerFactory = dynamicinformer.NewFilteredDynamicSharedInformerFactory(dynClient, 0, corev1.NamespaceAll, nil)
|
||||||
c.LeaderElection = leaderElectionConfig
|
c.LeaderElection = leaderElectionConfig
|
||||||
|
c.ComponentGlobalsRegistry = o.ComponentGlobalsRegistry
|
||||||
|
|
||||||
return c, nil
|
return c, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,8 +32,8 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
apiserveroptions "k8s.io/apiserver/pkg/server/options"
|
apiserveroptions "k8s.io/apiserver/pkg/server/options"
|
||||||
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
componentbaseconfig "k8s.io/component-base/config"
|
componentbaseconfig "k8s.io/component-base/config"
|
||||||
"k8s.io/component-base/featuregate"
|
|
||||||
"k8s.io/component-base/logs"
|
"k8s.io/component-base/logs"
|
||||||
"k8s.io/klog/v2/ktesting"
|
"k8s.io/klog/v2/ktesting"
|
||||||
v1 "k8s.io/kube-scheduler/config/v1"
|
v1 "k8s.io/kube-scheduler/config/v1"
|
||||||
@@ -282,6 +282,8 @@ profiles:
|
|||||||
defaultPodMaxBackoffSeconds := int64(10)
|
defaultPodMaxBackoffSeconds := int64(10)
|
||||||
defaultPercentageOfNodesToScore := ptr.To[int32](0)
|
defaultPercentageOfNodesToScore := ptr.To[int32](0)
|
||||||
|
|
||||||
|
componentGlobalsRegistry := basecompatibility.NewComponentGlobalsRegistry()
|
||||||
|
|
||||||
testcases := []struct {
|
testcases := []struct {
|
||||||
name string
|
name string
|
||||||
options *Options
|
options *Options
|
||||||
@@ -323,7 +325,7 @@ profiles:
|
|||||||
AlwaysAllowGroups: []string{"system:masters"},
|
AlwaysAllowGroups: []string{"system:masters"},
|
||||||
},
|
},
|
||||||
Logs: logs.NewOptions(),
|
Logs: logs.NewOptions(),
|
||||||
ComponentGlobalsRegistry: featuregate.DefaultComponentGlobalsRegistry,
|
ComponentGlobalsRegistry: componentGlobalsRegistry,
|
||||||
},
|
},
|
||||||
expectedUsername: "config",
|
expectedUsername: "config",
|
||||||
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
|
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
|
||||||
@@ -375,7 +377,7 @@ profiles:
|
|||||||
return cfg
|
return cfg
|
||||||
}(),
|
}(),
|
||||||
Logs: logs.NewOptions(),
|
Logs: logs.NewOptions(),
|
||||||
ComponentGlobalsRegistry: featuregate.DefaultComponentGlobalsRegistry,
|
ComponentGlobalsRegistry: componentGlobalsRegistry,
|
||||||
},
|
},
|
||||||
expectedError: "no kind \"KubeSchedulerConfiguration\" is registered for version \"componentconfig/v1alpha1\"",
|
expectedError: "no kind \"KubeSchedulerConfiguration\" is registered for version \"componentconfig/v1alpha1\"",
|
||||||
},
|
},
|
||||||
@@ -384,7 +386,7 @@ profiles:
|
|||||||
options: &Options{
|
options: &Options{
|
||||||
ConfigFile: unknownVersionConfig,
|
ConfigFile: unknownVersionConfig,
|
||||||
Logs: logs.NewOptions(),
|
Logs: logs.NewOptions(),
|
||||||
ComponentGlobalsRegistry: featuregate.DefaultComponentGlobalsRegistry,
|
ComponentGlobalsRegistry: componentGlobalsRegistry,
|
||||||
},
|
},
|
||||||
expectedError: "no kind \"KubeSchedulerConfiguration\" is registered for version \"kubescheduler.config.k8s.io/unknown\"",
|
expectedError: "no kind \"KubeSchedulerConfiguration\" is registered for version \"kubescheduler.config.k8s.io/unknown\"",
|
||||||
},
|
},
|
||||||
@@ -393,7 +395,7 @@ profiles:
|
|||||||
options: &Options{
|
options: &Options{
|
||||||
ConfigFile: noVersionConfig,
|
ConfigFile: noVersionConfig,
|
||||||
Logs: logs.NewOptions(),
|
Logs: logs.NewOptions(),
|
||||||
ComponentGlobalsRegistry: featuregate.DefaultComponentGlobalsRegistry,
|
ComponentGlobalsRegistry: componentGlobalsRegistry,
|
||||||
},
|
},
|
||||||
expectedError: "Object 'apiVersion' is missing",
|
expectedError: "Object 'apiVersion' is missing",
|
||||||
},
|
},
|
||||||
@@ -430,7 +432,7 @@ profiles:
|
|||||||
AlwaysAllowGroups: []string{"system:masters"},
|
AlwaysAllowGroups: []string{"system:masters"},
|
||||||
},
|
},
|
||||||
Logs: logs.NewOptions(),
|
Logs: logs.NewOptions(),
|
||||||
ComponentGlobalsRegistry: featuregate.DefaultComponentGlobalsRegistry,
|
ComponentGlobalsRegistry: componentGlobalsRegistry,
|
||||||
},
|
},
|
||||||
expectedUsername: "flag",
|
expectedUsername: "flag",
|
||||||
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
|
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
|
||||||
@@ -503,7 +505,7 @@ profiles:
|
|||||||
AlwaysAllowGroups: []string{"system:masters"},
|
AlwaysAllowGroups: []string{"system:masters"},
|
||||||
},
|
},
|
||||||
Logs: logs.NewOptions(),
|
Logs: logs.NewOptions(),
|
||||||
ComponentGlobalsRegistry: featuregate.DefaultComponentGlobalsRegistry,
|
ComponentGlobalsRegistry: componentGlobalsRegistry,
|
||||||
},
|
},
|
||||||
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
|
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
|
||||||
TypeMeta: metav1.TypeMeta{
|
TypeMeta: metav1.TypeMeta{
|
||||||
@@ -548,7 +550,7 @@ profiles:
|
|||||||
options: &Options{
|
options: &Options{
|
||||||
ConfigFile: pluginConfigFile,
|
ConfigFile: pluginConfigFile,
|
||||||
Logs: logs.NewOptions(),
|
Logs: logs.NewOptions(),
|
||||||
ComponentGlobalsRegistry: featuregate.DefaultComponentGlobalsRegistry,
|
ComponentGlobalsRegistry: componentGlobalsRegistry,
|
||||||
},
|
},
|
||||||
expectedUsername: "config",
|
expectedUsername: "config",
|
||||||
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
|
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
|
||||||
@@ -669,7 +671,7 @@ profiles:
|
|||||||
options: &Options{
|
options: &Options{
|
||||||
ConfigFile: multiProfilesConfig,
|
ConfigFile: multiProfilesConfig,
|
||||||
Logs: logs.NewOptions(),
|
Logs: logs.NewOptions(),
|
||||||
ComponentGlobalsRegistry: featuregate.DefaultComponentGlobalsRegistry,
|
ComponentGlobalsRegistry: componentGlobalsRegistry,
|
||||||
},
|
},
|
||||||
expectedUsername: "config",
|
expectedUsername: "config",
|
||||||
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
|
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
|
||||||
@@ -784,7 +786,7 @@ profiles:
|
|||||||
name: "no config",
|
name: "no config",
|
||||||
options: &Options{
|
options: &Options{
|
||||||
Logs: logs.NewOptions(),
|
Logs: logs.NewOptions(),
|
||||||
ComponentGlobalsRegistry: featuregate.DefaultComponentGlobalsRegistry,
|
ComponentGlobalsRegistry: componentGlobalsRegistry,
|
||||||
},
|
},
|
||||||
expectedError: "no configuration has been provided",
|
expectedError: "no configuration has been provided",
|
||||||
},
|
},
|
||||||
@@ -793,7 +795,7 @@ profiles:
|
|||||||
options: &Options{
|
options: &Options{
|
||||||
ConfigFile: unknownFieldConfig,
|
ConfigFile: unknownFieldConfig,
|
||||||
Logs: logs.NewOptions(),
|
Logs: logs.NewOptions(),
|
||||||
ComponentGlobalsRegistry: featuregate.DefaultComponentGlobalsRegistry,
|
ComponentGlobalsRegistry: componentGlobalsRegistry,
|
||||||
},
|
},
|
||||||
expectedError: `unknown field "foo"`,
|
expectedError: `unknown field "foo"`,
|
||||||
checkErrFn: runtime.IsStrictDecodingError,
|
checkErrFn: runtime.IsStrictDecodingError,
|
||||||
@@ -803,7 +805,7 @@ profiles:
|
|||||||
options: &Options{
|
options: &Options{
|
||||||
ConfigFile: duplicateFieldConfig,
|
ConfigFile: duplicateFieldConfig,
|
||||||
Logs: logs.NewOptions(),
|
Logs: logs.NewOptions(),
|
||||||
ComponentGlobalsRegistry: featuregate.DefaultComponentGlobalsRegistry,
|
ComponentGlobalsRegistry: componentGlobalsRegistry,
|
||||||
},
|
},
|
||||||
expectedError: `key "leaderElect" already set`,
|
expectedError: `key "leaderElect" already set`,
|
||||||
checkErrFn: runtime.IsStrictDecodingError,
|
checkErrFn: runtime.IsStrictDecodingError,
|
||||||
@@ -813,7 +815,7 @@ profiles:
|
|||||||
options: &Options{
|
options: &Options{
|
||||||
ConfigFile: highThroughputProfileConfig,
|
ConfigFile: highThroughputProfileConfig,
|
||||||
Logs: logs.NewOptions(),
|
Logs: logs.NewOptions(),
|
||||||
ComponentGlobalsRegistry: featuregate.DefaultComponentGlobalsRegistry,
|
ComponentGlobalsRegistry: componentGlobalsRegistry,
|
||||||
},
|
},
|
||||||
expectedUsername: "config",
|
expectedUsername: "config",
|
||||||
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
|
expectedConfig: kubeschedulerconfig.KubeSchedulerConfiguration{
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import (
|
|||||||
"k8s.io/client-go/tools/leaderelection"
|
"k8s.io/client-go/tools/leaderelection"
|
||||||
cliflag "k8s.io/component-base/cli/flag"
|
cliflag "k8s.io/component-base/cli/flag"
|
||||||
"k8s.io/component-base/cli/globalflag"
|
"k8s.io/component-base/cli/globalflag"
|
||||||
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
"k8s.io/component-base/configz"
|
"k8s.io/component-base/configz"
|
||||||
"k8s.io/component-base/featuregate"
|
"k8s.io/component-base/featuregate"
|
||||||
"k8s.io/component-base/logs"
|
"k8s.io/component-base/logs"
|
||||||
@@ -84,10 +85,6 @@ type Option func(runtime.Registry) error
|
|||||||
|
|
||||||
// NewSchedulerCommand creates a *cobra.Command object with default parameters and registryOptions
|
// NewSchedulerCommand creates a *cobra.Command object with default parameters and registryOptions
|
||||||
func NewSchedulerCommand(registryOptions ...Option) *cobra.Command {
|
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.
|
|
||||||
_, _ = featuregate.DefaultComponentGlobalsRegistry.ComponentGlobalsOrRegister(
|
|
||||||
featuregate.DefaultKubeComponent, utilversion.DefaultBuildEffectiveVersion(), utilfeature.DefaultMutableFeatureGate)
|
|
||||||
opts := options.NewOptions()
|
opts := options.NewOptions()
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
@@ -138,7 +135,7 @@ for more information about scheduling and the kube-scheduler component.`,
|
|||||||
// runCommand runs the scheduler.
|
// runCommand runs the scheduler.
|
||||||
func runCommand(cmd *cobra.Command, opts *options.Options, registryOptions ...Option) error {
|
func runCommand(cmd *cobra.Command, opts *options.Options, registryOptions ...Option) error {
|
||||||
verflag.PrintAndExitIfRequested()
|
verflag.PrintAndExitIfRequested()
|
||||||
fg := opts.ComponentGlobalsRegistry.FeatureGateFor(featuregate.DefaultKubeComponent)
|
fg := opts.ComponentGlobalsRegistry.FeatureGateFor(basecompatibility.DefaultKubeComponent)
|
||||||
// Activate logging as soon as possible, after that
|
// Activate logging as soon as possible, after that
|
||||||
// show flags with the final logging configuration.
|
// show flags with the final logging configuration.
|
||||||
if err := logsapi.ValidateAndApply(opts.Logs, fg); err != nil {
|
if err := logsapi.ValidateAndApply(opts.Logs, fg); err != nil {
|
||||||
@@ -216,11 +213,11 @@ func Run(ctx context.Context, cc *schedulerserverconfig.CompletedConfig, sched *
|
|||||||
readyzChecks = append(readyzChecks, handlerSyncCheck)
|
readyzChecks = append(readyzChecks, handlerSyncCheck)
|
||||||
|
|
||||||
if cc.LeaderElection != nil && utilfeature.DefaultFeatureGate.Enabled(kubefeatures.CoordinatedLeaderElection) {
|
if cc.LeaderElection != nil && utilfeature.DefaultFeatureGate.Enabled(kubefeatures.CoordinatedLeaderElection) {
|
||||||
binaryVersion, err := semver.ParseTolerant(featuregate.DefaultComponentGlobalsRegistry.EffectiveVersionFor(featuregate.DefaultKubeComponent).BinaryVersion().String())
|
binaryVersion, err := semver.ParseTolerant(cc.ComponentGlobalsRegistry.EffectiveVersionFor(basecompatibility.DefaultKubeComponent).BinaryVersion().String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
emulationVersion, err := semver.ParseTolerant(featuregate.DefaultComponentGlobalsRegistry.EffectiveVersionFor(featuregate.DefaultKubeComponent).EmulationVersion().String())
|
emulationVersion, err := semver.ParseTolerant(cc.ComponentGlobalsRegistry.EffectiveVersionFor(basecompatibility.DefaultKubeComponent).EmulationVersion().String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,10 +36,10 @@ 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"
|
||||||
"k8s.io/apiserver/pkg/util/feature"
|
"k8s.io/apiserver/pkg/util/feature"
|
||||||
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
componentbaseconfig "k8s.io/component-base/config"
|
componentbaseconfig "k8s.io/component-base/config"
|
||||||
"k8s.io/component-base/featuregate"
|
"k8s.io/component-base/featuregate"
|
||||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||||
utilversion "k8s.io/component-base/version"
|
|
||||||
configv1 "k8s.io/kube-scheduler/config/v1"
|
configv1 "k8s.io/kube-scheduler/config/v1"
|
||||||
"k8s.io/kubernetes/cmd/kube-scheduler/app/options"
|
"k8s.io/kubernetes/cmd/kube-scheduler/app/options"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
"k8s.io/kubernetes/pkg/features"
|
||||||
@@ -438,12 +438,8 @@ leaderElection:
|
|||||||
for k, v := range tc.restoreFeatures {
|
for k, v := range tc.restoreFeatures {
|
||||||
featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, k, v)
|
featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, k, v)
|
||||||
}
|
}
|
||||||
componentGlobalsRegistry := featuregate.DefaultComponentGlobalsRegistry
|
componentGlobalsRegistry := basecompatibility.NewComponentGlobalsRegistry()
|
||||||
t.Cleanup(func() {
|
verKube := basecompatibility.NewEffectiveVersionFromString("1.32", "1.31", "1.31")
|
||||||
componentGlobalsRegistry.Reset()
|
|
||||||
})
|
|
||||||
componentGlobalsRegistry.Reset()
|
|
||||||
verKube := utilversion.NewEffectiveVersion("1.32")
|
|
||||||
fg := feature.DefaultFeatureGate.DeepCopy()
|
fg := feature.DefaultFeatureGate.DeepCopy()
|
||||||
utilruntime.Must(fg.AddVersioned(map[featuregate.Feature]featuregate.VersionedSpecs{
|
utilruntime.Must(fg.AddVersioned(map[featuregate.Feature]featuregate.VersionedSpecs{
|
||||||
"kubeA": {
|
"kubeA": {
|
||||||
@@ -454,10 +450,10 @@ leaderElection:
|
|||||||
{Version: version.MustParse("1.31"), Default: false, PreRelease: featuregate.Alpha},
|
{Version: version.MustParse("1.31"), Default: false, PreRelease: featuregate.Alpha},
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
utilruntime.Must(componentGlobalsRegistry.Register(featuregate.DefaultKubeComponent, verKube, fg))
|
utilruntime.Must(componentGlobalsRegistry.Register(basecompatibility.DefaultKubeComponent, verKube, fg))
|
||||||
|
|
||||||
fs := pflag.NewFlagSet("test", pflag.PanicOnError)
|
fs := pflag.NewFlagSet("test", pflag.PanicOnError)
|
||||||
opts := options.NewOptions()
|
opts := options.NewOptionsWithComponentGlobalsRegistry(componentGlobalsRegistry)
|
||||||
|
|
||||||
// use listeners instead of static ports so parallel test runs don't conflict
|
// use listeners instead of static ports so parallel test runs don't conflict
|
||||||
opts.SecureServing.Listener = makeListener(t)
|
opts.SecureServing.Listener = makeListener(t)
|
||||||
|
|||||||
@@ -189,8 +189,7 @@ func BuildGenericConfig(
|
|||||||
s.Etcd.StorageConfig.Transport.TracerProvider = noopoteltrace.NewTracerProvider()
|
s.Etcd.StorageConfig.Transport.TracerProvider = noopoteltrace.NewTracerProvider()
|
||||||
}
|
}
|
||||||
|
|
||||||
storageFactoryConfig := kubeapiserver.NewStorageFactoryConfig()
|
storageFactoryConfig := kubeapiserver.NewStorageFactoryConfigEffectiveVersion(genericConfig.EffectiveVersion)
|
||||||
storageFactoryConfig.CurrentVersion = genericConfig.EffectiveVersion
|
|
||||||
storageFactoryConfig.APIResourceConfig = genericConfig.MergedResourceConfig
|
storageFactoryConfig.APIResourceConfig = genericConfig.MergedResourceConfig
|
||||||
storageFactoryConfig.DefaultResourceEncoding.SetEffectiveVersion(genericConfig.EffectiveVersion)
|
storageFactoryConfig.DefaultResourceEncoding.SetEffectiveVersion(genericConfig.EffectiveVersion)
|
||||||
storageFactory, lastErr = storageFactoryConfig.Complete(s.Etcd).New()
|
storageFactory, lastErr = storageFactoryConfig.Complete(s.Etcd).New()
|
||||||
|
|||||||
@@ -40,10 +40,10 @@ import (
|
|||||||
auditbuffered "k8s.io/apiserver/plugin/pkg/audit/buffered"
|
auditbuffered "k8s.io/apiserver/plugin/pkg/audit/buffered"
|
||||||
audittruncate "k8s.io/apiserver/plugin/pkg/audit/truncate"
|
audittruncate "k8s.io/apiserver/plugin/pkg/audit/truncate"
|
||||||
cliflag "k8s.io/component-base/cli/flag"
|
cliflag "k8s.io/component-base/cli/flag"
|
||||||
|
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"
|
"k8s.io/component-base/metrics"
|
||||||
utilversion "k8s.io/component-base/version"
|
|
||||||
kubeoptions "k8s.io/kubernetes/pkg/kubeapiserver/options"
|
kubeoptions "k8s.io/kubernetes/pkg/kubeapiserver/options"
|
||||||
"k8s.io/kubernetes/pkg/serviceaccount"
|
"k8s.io/kubernetes/pkg/serviceaccount"
|
||||||
v1alpha1testing "k8s.io/kubernetes/pkg/serviceaccount/externaljwt/plugin/testing/v1alpha1"
|
v1alpha1testing "k8s.io/kubernetes/pkg/serviceaccount/externaljwt/plugin/testing/v1alpha1"
|
||||||
@@ -51,13 +51,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestAddFlags(t *testing.T) {
|
func TestAddFlags(t *testing.T) {
|
||||||
componentGlobalsRegistry := featuregate.DefaultComponentGlobalsRegistry
|
componentGlobalsRegistry := basecompatibility.NewComponentGlobalsRegistry()
|
||||||
t.Cleanup(func() {
|
|
||||||
componentGlobalsRegistry.Reset()
|
|
||||||
})
|
|
||||||
fs := pflag.NewFlagSet("addflagstest", pflag.PanicOnError)
|
fs := pflag.NewFlagSet("addflagstest", pflag.PanicOnError)
|
||||||
utilruntime.Must(componentGlobalsRegistry.Register("test", utilversion.NewEffectiveVersion("1.32"), featuregate.NewFeatureGate()))
|
utilruntime.Must(componentGlobalsRegistry.Register("test", basecompatibility.NewEffectiveVersionFromString("1.32", "1.31", "1.31"), featuregate.NewFeatureGate()))
|
||||||
s := NewOptions()
|
s := NewOptions()
|
||||||
|
s.GenericServerRunOptions.ComponentGlobalsRegistry = componentGlobalsRegistry
|
||||||
var fss cliflag.NamedFlagSets
|
var fss cliflag.NamedFlagSets
|
||||||
s.AddFlags(&fss)
|
s.AddFlags(&fss)
|
||||||
for _, f := range fss.FlagSets {
|
for _, f := range fss.FlagSets {
|
||||||
@@ -141,7 +139,7 @@ func TestAddFlags(t *testing.T) {
|
|||||||
JSONPatchMaxCopyBytes: int64(3 * 1024 * 1024),
|
JSONPatchMaxCopyBytes: int64(3 * 1024 * 1024),
|
||||||
MaxRequestBodyBytes: int64(3 * 1024 * 1024),
|
MaxRequestBodyBytes: int64(3 * 1024 * 1024),
|
||||||
ComponentGlobalsRegistry: componentGlobalsRegistry,
|
ComponentGlobalsRegistry: componentGlobalsRegistry,
|
||||||
ComponentName: featuregate.DefaultKubeComponent,
|
ComponentName: basecompatibility.DefaultKubeComponent,
|
||||||
},
|
},
|
||||||
Admission: &kubeoptions.AdmissionOptions{
|
Admission: &kubeoptions.AdmissionOptions{
|
||||||
GenericAdmission: &apiserveroptions.AdmissionOptions{
|
GenericAdmission: &apiserveroptions.AdmissionOptions{
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import (
|
|||||||
kubeapiserveradmission "k8s.io/apiserver/pkg/admission"
|
kubeapiserveradmission "k8s.io/apiserver/pkg/admission"
|
||||||
genericoptions "k8s.io/apiserver/pkg/server/options"
|
genericoptions "k8s.io/apiserver/pkg/server/options"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
"k8s.io/component-base/featuregate"
|
"k8s.io/component-base/featuregate"
|
||||||
basemetrics "k8s.io/component-base/metrics"
|
basemetrics "k8s.io/component-base/metrics"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
"k8s.io/kubernetes/pkg/features"
|
||||||
@@ -202,7 +203,7 @@ func TestValidateOptions(t *testing.T) {
|
|||||||
name: "validate master count equal 0",
|
name: "validate master count equal 0",
|
||||||
expectErrors: true,
|
expectErrors: true,
|
||||||
options: &Options{
|
options: &Options{
|
||||||
GenericServerRunOptions: &genericoptions.ServerRunOptions{ComponentGlobalsRegistry: featuregate.DefaultComponentGlobalsRegistry},
|
GenericServerRunOptions: &genericoptions.ServerRunOptions{ComponentGlobalsRegistry: basecompatibility.NewComponentGlobalsRegistry()},
|
||||||
Etcd: &genericoptions.EtcdOptions{},
|
Etcd: &genericoptions.EtcdOptions{},
|
||||||
SecureServing: &genericoptions.SecureServingOptionsWithLoopback{},
|
SecureServing: &genericoptions.SecureServingOptionsWithLoopback{},
|
||||||
Audit: &genericoptions.AuditOptions{},
|
Audit: &genericoptions.AuditOptions{},
|
||||||
@@ -229,7 +230,7 @@ func TestValidateOptions(t *testing.T) {
|
|||||||
name: "validate token request enable not attempted",
|
name: "validate token request enable not attempted",
|
||||||
expectErrors: true,
|
expectErrors: true,
|
||||||
options: &Options{
|
options: &Options{
|
||||||
GenericServerRunOptions: &genericoptions.ServerRunOptions{ComponentGlobalsRegistry: featuregate.DefaultComponentGlobalsRegistry},
|
GenericServerRunOptions: &genericoptions.ServerRunOptions{ComponentGlobalsRegistry: basecompatibility.NewComponentGlobalsRegistry()},
|
||||||
Etcd: &genericoptions.EtcdOptions{},
|
Etcd: &genericoptions.EtcdOptions{},
|
||||||
SecureServing: &genericoptions.SecureServingOptionsWithLoopback{},
|
SecureServing: &genericoptions.SecureServingOptionsWithLoopback{},
|
||||||
Audit: &genericoptions.AuditOptions{},
|
Audit: &genericoptions.AuditOptions{},
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ func (c completedConfig) New(name string, delegationTarget genericapiserver.Dele
|
|||||||
}
|
}
|
||||||
|
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(zpagesfeatures.ComponentStatusz) {
|
if utilfeature.DefaultFeatureGate.Enabled(zpagesfeatures.ComponentStatusz) {
|
||||||
statusz.Install(s.GenericAPIServer.Handler.NonGoRestfulMux, name, statusz.NewRegistry())
|
statusz.Install(s.GenericAPIServer.Handler.NonGoRestfulMux, name, statusz.NewRegistry(c.Generic.EffectiveVersion))
|
||||||
}
|
}
|
||||||
|
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(apiserverfeatures.CoordinatedLeaderElection) {
|
if utilfeature.DefaultFeatureGate.Enabled(apiserverfeatures.CoordinatedLeaderElection) {
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ import (
|
|||||||
"k8s.io/apiserver/pkg/server/resourceconfig"
|
"k8s.io/apiserver/pkg/server/resourceconfig"
|
||||||
serverstorage "k8s.io/apiserver/pkg/server/storage"
|
serverstorage "k8s.io/apiserver/pkg/server/storage"
|
||||||
etcd3testing "k8s.io/apiserver/pkg/storage/etcd3/testing"
|
etcd3testing "k8s.io/apiserver/pkg/storage/etcd3/testing"
|
||||||
|
"k8s.io/apiserver/pkg/util/compatibility"
|
||||||
"k8s.io/apiserver/pkg/util/openapi"
|
"k8s.io/apiserver/pkg/util/openapi"
|
||||||
"k8s.io/client-go/discovery"
|
"k8s.io/client-go/discovery"
|
||||||
"k8s.io/client-go/informers"
|
"k8s.io/client-go/informers"
|
||||||
@@ -103,7 +104,7 @@ func setUp(t *testing.T) (*etcd3testing.EtcdTestServer, Config, *assert.Assertio
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
config.ControlPlane.Generic.EffectiveVersion = utilversion.DefaultKubeEffectiveVersion()
|
config.ControlPlane.Generic.EffectiveVersion = compatibility.DefaultKubeEffectiveVersionForTest()
|
||||||
storageFactoryConfig := kubeapiserver.NewStorageFactoryConfig()
|
storageFactoryConfig := kubeapiserver.NewStorageFactoryConfig()
|
||||||
storageFactoryConfig.DefaultResourceEncoding.SetEffectiveVersion(config.ControlPlane.Generic.EffectiveVersion)
|
storageFactoryConfig.DefaultResourceEncoding.SetEffectiveVersion(config.ControlPlane.Generic.EffectiveVersion)
|
||||||
storageConfig.StorageObjectCountTracker = config.ControlPlane.Generic.StorageObjectCountTracker
|
storageConfig.StorageObjectCountTracker = config.ControlPlane.Generic.StorageObjectCountTracker
|
||||||
@@ -241,7 +242,7 @@ func TestVersion(t *testing.T) {
|
|||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
expectedInfo := utilversion.Get()
|
expectedInfo := utilversion.Get()
|
||||||
kubeVersion := utilversion.DefaultKubeEffectiveVersion().BinaryVersion()
|
kubeVersion := compatibility.DefaultKubeEffectiveVersionForTest().BinaryVersion()
|
||||||
expectedInfo.Major = fmt.Sprintf("%d", kubeVersion.Major())
|
expectedInfo.Major = fmt.Sprintf("%d", kubeVersion.Major())
|
||||||
expectedInfo.Minor = fmt.Sprintf("%d", kubeVersion.Minor())
|
expectedInfo.Minor = fmt.Sprintf("%d", kubeVersion.Minor())
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ import (
|
|||||||
"k8s.io/apiserver/pkg/server/resourceconfig"
|
"k8s.io/apiserver/pkg/server/resourceconfig"
|
||||||
serverstorage "k8s.io/apiserver/pkg/server/storage"
|
serverstorage "k8s.io/apiserver/pkg/server/storage"
|
||||||
"k8s.io/apiserver/pkg/storage/storagebackend"
|
"k8s.io/apiserver/pkg/storage/storagebackend"
|
||||||
version "k8s.io/component-base/version"
|
"k8s.io/apiserver/pkg/util/compatibility"
|
||||||
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||||
"k8s.io/kubernetes/pkg/apis/admissionregistration"
|
"k8s.io/kubernetes/pkg/apis/admissionregistration"
|
||||||
"k8s.io/kubernetes/pkg/apis/apps"
|
"k8s.io/kubernetes/pkg/apis/apps"
|
||||||
@@ -61,6 +62,11 @@ func DefaultWatchCacheSizes() map[schema.GroupResource]int {
|
|||||||
|
|
||||||
// NewStorageFactoryConfig returns a new StorageFactoryConfig set up with necessary resource overrides.
|
// NewStorageFactoryConfig returns a new StorageFactoryConfig set up with necessary resource overrides.
|
||||||
func NewStorageFactoryConfig() *StorageFactoryConfig {
|
func NewStorageFactoryConfig() *StorageFactoryConfig {
|
||||||
|
return NewStorageFactoryConfigEffectiveVersion(compatibility.DefaultComponentGlobalsRegistry.EffectiveVersionFor(basecompatibility.DefaultKubeComponent))
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewStorageFactoryConfigEffectiveVersion returns a new StorageFactoryConfig set up with necessary resource overrides for a given EffectiveVersion.
|
||||||
|
func NewStorageFactoryConfigEffectiveVersion(effectiveVersion basecompatibility.EffectiveVersion) *StorageFactoryConfig {
|
||||||
resources := []schema.GroupVersionResource{
|
resources := []schema.GroupVersionResource{
|
||||||
// If a resource has to be stored in a version that is not the
|
// If a resource has to be stored in a version that is not the
|
||||||
// latest, then it can be listed here. Usually this is the case
|
// latest, then it can be listed here. Usually this is the case
|
||||||
@@ -87,7 +93,7 @@ func NewStorageFactoryConfig() *StorageFactoryConfig {
|
|||||||
|
|
||||||
return &StorageFactoryConfig{
|
return &StorageFactoryConfig{
|
||||||
Serializer: legacyscheme.Codecs,
|
Serializer: legacyscheme.Codecs,
|
||||||
DefaultResourceEncoding: serverstorage.NewDefaultResourceEncodingConfig(legacyscheme.Scheme),
|
DefaultResourceEncoding: serverstorage.NewDefaultResourceEncodingConfigForEffectiveVersion(legacyscheme.Scheme, effectiveVersion),
|
||||||
ResourceEncodingOverrides: resources,
|
ResourceEncodingOverrides: resources,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,7 +107,6 @@ type StorageFactoryConfig struct {
|
|||||||
Serializer runtime.StorageSerializer
|
Serializer runtime.StorageSerializer
|
||||||
ResourceEncodingOverrides []schema.GroupVersionResource
|
ResourceEncodingOverrides []schema.GroupVersionResource
|
||||||
EtcdServersOverrides []string
|
EtcdServersOverrides []string
|
||||||
CurrentVersion version.EffectiveVersion
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Complete completes the StorageFactoryConfig with provided etcdOptions returning completedStorageFactoryConfig.
|
// Complete completes the StorageFactoryConfig with provided etcdOptions returning completedStorageFactoryConfig.
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ import (
|
|||||||
"k8s.io/apiserver/pkg/server/healthz"
|
"k8s.io/apiserver/pkg/server/healthz"
|
||||||
"k8s.io/apiserver/pkg/server/httplog"
|
"k8s.io/apiserver/pkg/server/httplog"
|
||||||
"k8s.io/apiserver/pkg/server/routes"
|
"k8s.io/apiserver/pkg/server/routes"
|
||||||
|
"k8s.io/apiserver/pkg/util/compatibility"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/apiserver/pkg/util/flushwriter"
|
"k8s.io/apiserver/pkg/util/flushwriter"
|
||||||
"k8s.io/component-base/configz"
|
"k8s.io/component-base/configz"
|
||||||
@@ -565,7 +566,7 @@ func (s *Server) InstallDebuggingHandlers() {
|
|||||||
|
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(zpagesfeatures.ComponentStatusz) {
|
if utilfeature.DefaultFeatureGate.Enabled(zpagesfeatures.ComponentStatusz) {
|
||||||
s.addMetricsBucketMatcher("statusz")
|
s.addMetricsBucketMatcher("statusz")
|
||||||
statusz.Install(s.restfulCont, ComponentKubelet, statusz.NewRegistry())
|
statusz.Install(s.restfulCont, ComponentKubelet, statusz.NewRegistry(compatibility.DefaultBuildEffectiveVersion()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// The /runningpods endpoint is used for testing only.
|
// The /runningpods endpoint is used for testing only.
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import (
|
|||||||
|
|
||||||
"k8s.io/apiextensions-apiserver/pkg/cmd/server/options"
|
"k8s.io/apiextensions-apiserver/pkg/cmd/server/options"
|
||||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||||
"k8s.io/component-base/featuregate"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewServerCommand(ctx context.Context, out, errOut io.Writer) *cobra.Command {
|
func NewServerCommand(ctx context.Context, out, errOut io.Writer) *cobra.Command {
|
||||||
@@ -34,7 +33,7 @@ func NewServerCommand(ctx context.Context, out, errOut io.Writer) *cobra.Command
|
|||||||
Short: "Launch an API extensions API server",
|
Short: "Launch an API extensions API server",
|
||||||
Long: "Launch an API extensions API server",
|
Long: "Launch an API extensions API server",
|
||||||
PersistentPreRunE: func(*cobra.Command, []string) error {
|
PersistentPreRunE: func(*cobra.Command, []string) error {
|
||||||
return featuregate.DefaultComponentGlobalsRegistry.Set()
|
return o.ServerRunOptions.ComponentGlobalsRegistry.Set()
|
||||||
},
|
},
|
||||||
RunE: func(c *cobra.Command, args []string) error {
|
RunE: func(c *cobra.Command, args []string) error {
|
||||||
if err := o.Complete(); err != nil {
|
if err := o.Complete(); err != nil {
|
||||||
|
|||||||
@@ -31,18 +31,18 @@ import (
|
|||||||
extensionsapiserver "k8s.io/apiextensions-apiserver/pkg/apiserver"
|
extensionsapiserver "k8s.io/apiextensions-apiserver/pkg/apiserver"
|
||||||
"k8s.io/apiextensions-apiserver/pkg/cmd/server/options"
|
"k8s.io/apiextensions-apiserver/pkg/cmd/server/options"
|
||||||
generatedopenapi "k8s.io/apiextensions-apiserver/pkg/generated/openapi"
|
generatedopenapi "k8s.io/apiextensions-apiserver/pkg/generated/openapi"
|
||||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
openapinamer "k8s.io/apiserver/pkg/endpoints/openapi"
|
openapinamer "k8s.io/apiserver/pkg/endpoints/openapi"
|
||||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||||
"k8s.io/apiserver/pkg/storage/storagebackend"
|
"k8s.io/apiserver/pkg/storage/storagebackend"
|
||||||
|
"k8s.io/apiserver/pkg/util/compatibility"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/apiserver/pkg/util/openapi"
|
"k8s.io/apiserver/pkg/util/openapi"
|
||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
"k8s.io/component-base/featuregate"
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||||
logsapi "k8s.io/component-base/logs/api/v1"
|
logsapi "k8s.io/component-base/logs/api/v1"
|
||||||
utilversion "k8s.io/component-base/version"
|
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -124,15 +124,17 @@ func StartTestServer(t Logger, _ *TestServerInstanceOptions, customFlags []strin
|
|||||||
|
|
||||||
fs := pflag.NewFlagSet("test", pflag.PanicOnError)
|
fs := pflag.NewFlagSet("test", pflag.PanicOnError)
|
||||||
|
|
||||||
featureGate := utilfeature.DefaultMutableFeatureGate
|
|
||||||
|
|
||||||
// Configure the effective version.
|
|
||||||
effectiveVersion := utilversion.DefaultKubeEffectiveVersion()
|
|
||||||
effectiveVersion.SetEmulationVersion(featureGate.EmulationVersion())
|
|
||||||
|
|
||||||
featuregate.DefaultComponentGlobalsRegistry.Reset()
|
|
||||||
utilruntime.Must(featuregate.DefaultComponentGlobalsRegistry.Register(featuregate.DefaultKubeComponent, effectiveVersion, featureGate))
|
|
||||||
s := options.NewCustomResourceDefinitionsServerOptions(os.Stdout, os.Stderr)
|
s := options.NewCustomResourceDefinitionsServerOptions(os.Stdout, os.Stderr)
|
||||||
|
|
||||||
|
// set up new instance of ComponentGlobalsRegistry instead of using the DefaultComponentGlobalsRegistry to avoid contention in parallel tests.
|
||||||
|
featureGate := utilfeature.DefaultMutableFeatureGate.DeepCopy()
|
||||||
|
effectiveVersion := compatibility.DefaultKubeEffectiveVersionForTest()
|
||||||
|
effectiveVersion.SetEmulationVersion(featureGate.EmulationVersion())
|
||||||
|
componentGlobalsRegistry := basecompatibility.NewComponentGlobalsRegistry()
|
||||||
|
if err := componentGlobalsRegistry.Register(basecompatibility.DefaultKubeComponent, effectiveVersion, featureGate); err != nil {
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
s.ServerRunOptions.ComponentGlobalsRegistry = componentGlobalsRegistry
|
||||||
s.AddFlags(fs)
|
s.AddFlags(fs)
|
||||||
|
|
||||||
s.RecommendedOptions.SecureServing.Listener, s.RecommendedOptions.SecureServing.BindPort, err = createLocalhostListenerOnFreePort()
|
s.RecommendedOptions.SecureServing.Listener, s.RecommendedOptions.SecureServing.BindPort, err = createLocalhostListenerOnFreePort()
|
||||||
@@ -155,8 +157,18 @@ func StartTestServer(t Logger, _ *TestServerInstanceOptions, customFlags []strin
|
|||||||
|
|
||||||
fs.Parse(customFlags)
|
fs.Parse(customFlags)
|
||||||
|
|
||||||
if err := featuregate.DefaultComponentGlobalsRegistry.Set(); err != nil {
|
if err := componentGlobalsRegistry.Set(); err != nil {
|
||||||
return result, err
|
return result, fmt.Errorf("%w\nIf you are using SetFeatureGate*DuringTest, try using --emulated-version and --feature-gates flags instead", err)
|
||||||
|
}
|
||||||
|
// If the local ComponentGlobalsRegistry is changed by the flags,
|
||||||
|
// we need to copy the new feature values back to the DefaultFeatureGate because most feature checks still use the DefaultFeatureGate.
|
||||||
|
if !featureGate.EmulationVersion().EqualTo(utilfeature.DefaultMutableFeatureGate.EmulationVersion()) {
|
||||||
|
featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t.(featuregatetesting.TB), utilfeature.DefaultMutableFeatureGate, effectiveVersion.EmulationVersion())
|
||||||
|
}
|
||||||
|
for f := range utilfeature.DefaultMutableFeatureGate.GetAll() {
|
||||||
|
if featureGate.Enabled(f) != utilfeature.DefaultFeatureGate.Enabled(f) {
|
||||||
|
featuregatetesting.SetFeatureGateDuringTest(t.(featuregatetesting.TB), utilfeature.DefaultFeatureGate, f, featureGate.Enabled(f))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.Complete(); err != nil {
|
if err := s.Complete(); err != nil {
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/apimachinery/pkg/util/version"
|
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
@@ -593,9 +592,7 @@ func TestFieldSelectorOpenAPI(t *testing.T) {
|
|||||||
|
|
||||||
func TestFieldSelectorDropFields(t *testing.T) {
|
func TestFieldSelectorDropFields(t *testing.T) {
|
||||||
_, ctx := ktesting.NewTestContext(t)
|
_, ctx := ktesting.NewTestContext(t)
|
||||||
featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultFeatureGate, version.MustParse("1.31"))
|
tearDown, apiExtensionClient, _, err := fixtures.StartDefaultServerWithClients(t, "--emulated-version=1.31", "--feature-gates=CustomResourceFieldSelectors=false")
|
||||||
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, apiextensionsfeatures.CustomResourceFieldSelectors, false)
|
|
||||||
tearDown, apiExtensionClient, _, err := fixtures.StartDefaultServerWithClients(t)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@@ -675,9 +672,8 @@ func TestFieldSelectorDropFields(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFieldSelectorDisablement(t *testing.T) {
|
func TestFieldSelectorDisablement(t *testing.T) {
|
||||||
featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultFeatureGate, version.MustParse("1.31"))
|
|
||||||
_, ctx := ktesting.NewTestContext(t)
|
_, ctx := ktesting.NewTestContext(t)
|
||||||
tearDown, config, _, err := fixtures.StartDefaultServer(t)
|
tearDown, config, _, err := fixtures.StartDefaultServer(t, "--emulated-version=1.31")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
12
staging/src/k8s.io/component-base/compatibility/OWNERS
Normal file
12
staging/src/k8s.io/component-base/compatibility/OWNERS
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
# See the OWNERS docs at https://go.k8s.io/owners
|
||||||
|
|
||||||
|
# Currently assigned this directory to sig-api-machinery since this is
|
||||||
|
# an interface to the version definition in "k8s.io/apiserver/pkg/util/compatibility".
|
||||||
|
|
||||||
|
approvers:
|
||||||
|
- sig-api-machinery-api-approvers
|
||||||
|
reviewers:
|
||||||
|
- sig-api-machinery-api-reviewers
|
||||||
|
- siyuanfoundation
|
||||||
|
labels:
|
||||||
|
- sig/api-machinery
|
||||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package featuregate
|
package compatibility
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -26,38 +26,12 @@ 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"
|
||||||
cliflag "k8s.io/component-base/cli/flag"
|
cliflag "k8s.io/component-base/cli/flag"
|
||||||
baseversion "k8s.io/component-base/version"
|
"k8s.io/component-base/featuregate"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 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
|
|
||||||
// _, _ = utilversion.DefaultComponentGlobalsRegistry.ComponentGlobalsOrRegister(utilversion.DefaultKubeComponent, utilversion.DefaultKubeEffectiveVersion(), utilfeature.DefaultMutableFeatureGate)
|
|
||||||
// wardleEffectiveVersion := utilversion.NewEffectiveVersion("1.2")
|
|
||||||
// wardleFeatureGate := featuregate.NewFeatureGate()
|
|
||||||
// utilruntime.Must(utilversion.DefaultComponentGlobalsRegistry.Register(apiserver.WardleComponentName, wardleEffectiveVersion, wardleFeatureGate, false))
|
|
||||||
//
|
|
||||||
// cmd := &cobra.Command{
|
|
||||||
// ...
|
|
||||||
// // call DefaultComponentGlobalsRegistry.Set() in PersistentPreRunE
|
|
||||||
// PersistentPreRunE: func(*cobra.Command, []string) error {
|
|
||||||
// if err := utilversion.DefaultComponentGlobalsRegistry.Set(); err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
// ...
|
|
||||||
// },
|
|
||||||
// RunE: func(c *cobra.Command, args []string) error {
|
|
||||||
// // call utilversion.DefaultComponentGlobalsRegistry.Validate() somewhere
|
|
||||||
// },
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// flags := cmd.Flags()
|
|
||||||
// // add flags
|
|
||||||
// utilversion.DefaultComponentGlobalsRegistry.AddFlags(flags)
|
|
||||||
var DefaultComponentGlobalsRegistry ComponentGlobalsRegistry = NewComponentGlobalsRegistry()
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// DefaultKubeComponent is the component name for k8s control plane components.
|
||||||
DefaultKubeComponent = "kube"
|
DefaultKubeComponent = "kube"
|
||||||
|
|
||||||
klogLevel = 2
|
klogLevel = 2
|
||||||
@@ -65,10 +39,10 @@ const (
|
|||||||
|
|
||||||
type VersionMapping func(from *version.Version) *version.Version
|
type VersionMapping func(from *version.Version) *version.Version
|
||||||
|
|
||||||
// ComponentGlobals stores the global variables for a component for easy access.
|
// ComponentGlobals stores the global variables for a component for easy access, including feature gate and effective version.
|
||||||
type ComponentGlobals struct {
|
type ComponentGlobals struct {
|
||||||
effectiveVersion baseversion.MutableEffectiveVersion
|
effectiveVersion MutableEffectiveVersion
|
||||||
featureGate MutableVersionedFeatureGate
|
featureGate featuregate.MutableVersionedFeatureGate
|
||||||
|
|
||||||
// emulationVersionMapping contains the mapping from the emulation version of this component
|
// emulationVersionMapping contains the mapping from the emulation version of this component
|
||||||
// to the emulation version of another component.
|
// to the emulation version of another component.
|
||||||
@@ -84,22 +58,24 @@ type ComponentGlobals struct {
|
|||||||
dependentMinCompatibilityVersion bool
|
dependentMinCompatibilityVersion bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ComponentGlobalsRegistry stores the global variables for different components for easy access, including feature gate and effective version of each component.
|
||||||
type ComponentGlobalsRegistry interface {
|
type ComponentGlobalsRegistry interface {
|
||||||
// EffectiveVersionFor returns the EffectiveVersion registered under the component.
|
// EffectiveVersionFor returns the EffectiveVersion registered under the component.
|
||||||
// Returns nil if the component is not registered.
|
// Returns nil if the component is not registered.
|
||||||
EffectiveVersionFor(component string) baseversion.EffectiveVersion
|
EffectiveVersionFor(component string) EffectiveVersion
|
||||||
// FeatureGateFor returns the FeatureGate registered under the component.
|
// FeatureGateFor returns the FeatureGate registered under the component.
|
||||||
// Returns nil if the component is not registered.
|
// Returns nil if the component is not registered.
|
||||||
FeatureGateFor(component string) FeatureGate
|
FeatureGateFor(component string) featuregate.FeatureGate
|
||||||
// Register registers the EffectiveVersion and FeatureGate for a component.
|
// Register registers the EffectiveVersion and FeatureGate for a component.
|
||||||
// returns error if the component is already registered.
|
// returns error if the component is already registered.
|
||||||
Register(component string, effectiveVersion baseversion.MutableEffectiveVersion, featureGate MutableVersionedFeatureGate) error
|
Register(component string, effectiveVersion MutableEffectiveVersion, featureGate featuregate.MutableVersionedFeatureGate) error
|
||||||
// ComponentGlobalsOrRegister would return the registered global variables for the component if it already exists in the registry.
|
// ComponentGlobalsOrRegister would return the registered global variables for the component if it already exists in the registry.
|
||||||
// Otherwise, the provided variables would be registered under the component, and the same variables would be returned.
|
// Otherwise, the provided variables would be registered under the component, and the same variables would be returned.
|
||||||
ComponentGlobalsOrRegister(component string, effectiveVersion baseversion.MutableEffectiveVersion, featureGate MutableVersionedFeatureGate) (baseversion.MutableEffectiveVersion, MutableVersionedFeatureGate)
|
ComponentGlobalsOrRegister(component string, effectiveVersion MutableEffectiveVersion, featureGate featuregate.MutableVersionedFeatureGate) (MutableEffectiveVersion, featuregate.MutableVersionedFeatureGate)
|
||||||
// AddFlags adds flags of "--emulated-version" and "--feature-gates"
|
// AddFlags adds flags of "--emulated-version" and "--feature-gates"
|
||||||
AddFlags(fs *pflag.FlagSet)
|
AddFlags(fs *pflag.FlagSet)
|
||||||
// Set sets the flags for all global variables for all components registered.
|
// Set sets the flags for all global variables for all components registered.
|
||||||
|
// A component's feature gate and effective version would not be updated until Set() is called.
|
||||||
Set() error
|
Set() error
|
||||||
// SetFallback calls Set() if it has never been called.
|
// SetFallback calls Set() if it has never been called.
|
||||||
SetFallback() error
|
SetFallback() error
|
||||||
@@ -118,9 +94,13 @@ type ComponentGlobalsRegistry interface {
|
|||||||
type componentGlobalsRegistry struct {
|
type componentGlobalsRegistry struct {
|
||||||
componentGlobals map[string]*ComponentGlobals
|
componentGlobals map[string]*ComponentGlobals
|
||||||
mutex sync.RWMutex
|
mutex sync.RWMutex
|
||||||
// list of component name to emulation version set from the flag.
|
// emulationVersionConfig stores the list of component name to emulation version set from the flag.
|
||||||
|
// When the `--emulated-version` flag is parsed, it would not take effect until Set() is called,
|
||||||
|
// because the emulation version needs to be set before the feature gate is set.
|
||||||
emulationVersionConfig []string
|
emulationVersionConfig []string
|
||||||
// map of component name to the list of feature gates set from the flag.
|
// featureGatesConfig stores the map of component name to the list of feature gates set from the flag.
|
||||||
|
// When the `--feature-gates` flag is parsed, it would not take effect until Set() is called,
|
||||||
|
// because the emulation version needs to be set before the feature gate is set.
|
||||||
featureGatesConfig map[string][]string
|
featureGatesConfig map[string][]string
|
||||||
// set stores if the Set() function for the registry is already called.
|
// set stores if the Set() function for the registry is already called.
|
||||||
set bool
|
set bool
|
||||||
@@ -143,7 +123,7 @@ func (r *componentGlobalsRegistry) Reset() {
|
|||||||
r.set = false
|
r.set = false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *componentGlobalsRegistry) EffectiveVersionFor(component string) baseversion.EffectiveVersion {
|
func (r *componentGlobalsRegistry) EffectiveVersionFor(component string) EffectiveVersion {
|
||||||
r.mutex.RLock()
|
r.mutex.RLock()
|
||||||
defer r.mutex.RUnlock()
|
defer r.mutex.RUnlock()
|
||||||
globals, ok := r.componentGlobals[component]
|
globals, ok := r.componentGlobals[component]
|
||||||
@@ -153,7 +133,7 @@ func (r *componentGlobalsRegistry) EffectiveVersionFor(component string) basever
|
|||||||
return globals.effectiveVersion
|
return globals.effectiveVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *componentGlobalsRegistry) FeatureGateFor(component string) FeatureGate {
|
func (r *componentGlobalsRegistry) FeatureGateFor(component string) featuregate.FeatureGate {
|
||||||
r.mutex.RLock()
|
r.mutex.RLock()
|
||||||
defer r.mutex.RUnlock()
|
defer r.mutex.RUnlock()
|
||||||
globals, ok := r.componentGlobals[component]
|
globals, ok := r.componentGlobals[component]
|
||||||
@@ -163,7 +143,7 @@ func (r *componentGlobalsRegistry) FeatureGateFor(component string) FeatureGate
|
|||||||
return globals.featureGate
|
return globals.featureGate
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *componentGlobalsRegistry) unsafeRegister(component string, effectiveVersion baseversion.MutableEffectiveVersion, featureGate MutableVersionedFeatureGate) error {
|
func (r *componentGlobalsRegistry) unsafeRegister(component string, effectiveVersion MutableEffectiveVersion, featureGate featuregate.MutableVersionedFeatureGate) error {
|
||||||
if _, ok := r.componentGlobals[component]; ok {
|
if _, ok := r.componentGlobals[component]; ok {
|
||||||
return fmt.Errorf("component globals of %s already registered", component)
|
return fmt.Errorf("component globals of %s already registered", component)
|
||||||
}
|
}
|
||||||
@@ -182,7 +162,7 @@ func (r *componentGlobalsRegistry) unsafeRegister(component string, effectiveVer
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *componentGlobalsRegistry) Register(component string, effectiveVersion baseversion.MutableEffectiveVersion, featureGate MutableVersionedFeatureGate) error {
|
func (r *componentGlobalsRegistry) Register(component string, effectiveVersion MutableEffectiveVersion, featureGate featuregate.MutableVersionedFeatureGate) error {
|
||||||
if effectiveVersion == nil {
|
if effectiveVersion == nil {
|
||||||
return fmt.Errorf("cannot register nil effectiveVersion")
|
return fmt.Errorf("cannot register nil effectiveVersion")
|
||||||
}
|
}
|
||||||
@@ -191,7 +171,7 @@ func (r *componentGlobalsRegistry) Register(component string, effectiveVersion b
|
|||||||
return r.unsafeRegister(component, effectiveVersion, featureGate)
|
return r.unsafeRegister(component, effectiveVersion, featureGate)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *componentGlobalsRegistry) ComponentGlobalsOrRegister(component string, effectiveVersion baseversion.MutableEffectiveVersion, featureGate MutableVersionedFeatureGate) (baseversion.MutableEffectiveVersion, MutableVersionedFeatureGate) {
|
func (r *componentGlobalsRegistry) ComponentGlobalsOrRegister(component string, effectiveVersion MutableEffectiveVersion, featureGate featuregate.MutableVersionedFeatureGate) (MutableEffectiveVersion, featuregate.MutableVersionedFeatureGate) {
|
||||||
r.mutex.Lock()
|
r.mutex.Lock()
|
||||||
defer r.mutex.Unlock()
|
defer r.mutex.Unlock()
|
||||||
globals, ok := r.componentGlobals[component]
|
globals, ok := r.componentGlobals[component]
|
||||||
@@ -219,22 +199,16 @@ func (r *componentGlobalsRegistry) unsafeKnownFeatures() []string {
|
|||||||
func (r *componentGlobalsRegistry) unsafeVersionFlagOptions(isEmulation bool) []string {
|
func (r *componentGlobalsRegistry) unsafeVersionFlagOptions(isEmulation bool) []string {
|
||||||
var vs []string
|
var vs []string
|
||||||
for component, globals := range r.componentGlobals {
|
for component, globals := range r.componentGlobals {
|
||||||
binaryVer := globals.effectiveVersion.BinaryVersion()
|
|
||||||
if isEmulation {
|
if isEmulation {
|
||||||
if globals.dependentEmulationVersion {
|
if globals.dependentEmulationVersion {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// emulated version could be between binaryMajor.{binaryMinor} and binaryMajor.{binaryMinor}
|
vs = append(vs, fmt.Sprintf("%s=%s", component, globals.effectiveVersion.AllowedEmulationVersionRange()))
|
||||||
// TODO: change to binaryMajor.{binaryMinor-1} and binaryMajor.{binaryMinor} in 1.32
|
|
||||||
vs = append(vs, fmt.Sprintf("%s=%s..%s (default=%s)", component,
|
|
||||||
binaryVer.SubtractMinor(0).String(), binaryVer.String(), globals.effectiveVersion.EmulationVersion().String()))
|
|
||||||
} else {
|
} else {
|
||||||
if globals.dependentMinCompatibilityVersion {
|
if globals.dependentMinCompatibilityVersion {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// min compatibility version could be between binaryMajor.{binaryMinor-1} and binaryMajor.{binaryMinor}
|
vs = append(vs, fmt.Sprintf("%s=%s", component, globals.effectiveVersion.AllowedMinCompatibilityVersionRange()))
|
||||||
vs = append(vs, fmt.Sprintf("%s=%s..%s (default=%s)", component,
|
|
||||||
binaryVer.SubtractMinor(1).String(), binaryVer.String(), globals.effectiveVersion.MinCompatibilityVersion().String()))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sort.Strings(vs)
|
sort.Strings(vs)
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright 2024 The Kubernetes Authors.
|
Copyright 2025 The Kubernetes Authors.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package featuregate
|
package compatibility
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -25,7 +25,7 @@ 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"
|
||||||
baseversion "k8s.io/component-base/version"
|
"k8s.io/component-base/featuregate"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -34,8 +34,8 @@ const (
|
|||||||
|
|
||||||
func TestEffectiveVersionRegistry(t *testing.T) {
|
func TestEffectiveVersionRegistry(t *testing.T) {
|
||||||
r := NewComponentGlobalsRegistry()
|
r := NewComponentGlobalsRegistry()
|
||||||
ver1 := baseversion.NewEffectiveVersion("1.31")
|
ver1 := NewEffectiveVersionFromString("1.31", "", "")
|
||||||
ver2 := baseversion.NewEffectiveVersion("1.28")
|
ver2 := NewEffectiveVersionFromString("1.28", "", "")
|
||||||
|
|
||||||
if r.EffectiveVersionFor(testComponent) != nil {
|
if r.EffectiveVersionFor(testComponent) != nil {
|
||||||
t.Fatalf("expected nil EffectiveVersion initially")
|
t.Fatalf("expected nil EffectiveVersion initially")
|
||||||
@@ -57,40 +57,40 @@ func TestEffectiveVersionRegistry(t *testing.T) {
|
|||||||
|
|
||||||
func testRegistry(t *testing.T) *componentGlobalsRegistry {
|
func testRegistry(t *testing.T) *componentGlobalsRegistry {
|
||||||
r := NewComponentGlobalsRegistry()
|
r := NewComponentGlobalsRegistry()
|
||||||
verKube := baseversion.NewEffectiveVersion("1.31")
|
verKube := NewEffectiveVersionFromString("1.31", "1.31", "1.30")
|
||||||
fgKube := NewVersionedFeatureGate(version.MustParse("0.0"))
|
fgKube := featuregate.NewVersionedFeatureGate(version.MustParse("0.0"))
|
||||||
err := fgKube.AddVersioned(map[Feature]VersionedSpecs{
|
err := fgKube.AddVersioned(map[featuregate.Feature]featuregate.VersionedSpecs{
|
||||||
"kubeA": {
|
"kubeA": {
|
||||||
{Version: version.MustParse("1.27"), Default: false, PreRelease: Alpha},
|
{Version: version.MustParse("1.27"), Default: false, PreRelease: featuregate.Alpha},
|
||||||
{Version: version.MustParse("1.28"), Default: false, PreRelease: Beta},
|
{Version: version.MustParse("1.28"), Default: false, PreRelease: featuregate.Beta},
|
||||||
{Version: version.MustParse("1.31"), Default: true, LockToDefault: true, PreRelease: GA},
|
{Version: version.MustParse("1.31"), Default: true, LockToDefault: true, PreRelease: featuregate.GA},
|
||||||
},
|
},
|
||||||
"kubeB": {
|
"kubeB": {
|
||||||
{Version: version.MustParse("1.30"), Default: false, PreRelease: Alpha},
|
{Version: version.MustParse("1.30"), Default: false, PreRelease: featuregate.Alpha},
|
||||||
},
|
},
|
||||||
"commonC": {
|
"commonC": {
|
||||||
{Version: version.MustParse("1.27"), Default: false, PreRelease: Alpha},
|
{Version: version.MustParse("1.27"), Default: false, PreRelease: featuregate.Alpha},
|
||||||
{Version: version.MustParse("1.29"), Default: true, PreRelease: Beta},
|
{Version: version.MustParse("1.29"), Default: true, PreRelease: featuregate.Beta},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
verTest := baseversion.NewEffectiveVersion("2.8")
|
verTest := NewEffectiveVersionFromString("2.8", "2.8", "2.7")
|
||||||
fgTest := NewVersionedFeatureGate(version.MustParse("0.0"))
|
fgTest := featuregate.NewVersionedFeatureGate(version.MustParse("0.0"))
|
||||||
err = fgTest.AddVersioned(map[Feature]VersionedSpecs{
|
err = fgTest.AddVersioned(map[featuregate.Feature]featuregate.VersionedSpecs{
|
||||||
"testA": {
|
"testA": {
|
||||||
{Version: version.MustParse("2.7"), Default: false, PreRelease: Alpha},
|
{Version: version.MustParse("2.7"), Default: false, PreRelease: featuregate.Alpha},
|
||||||
{Version: version.MustParse("2.8"), Default: false, PreRelease: Beta},
|
{Version: version.MustParse("2.8"), Default: false, PreRelease: featuregate.Beta},
|
||||||
{Version: version.MustParse("2.10"), Default: true, PreRelease: GA},
|
{Version: version.MustParse("2.10"), Default: true, PreRelease: featuregate.GA},
|
||||||
},
|
},
|
||||||
"testB": {
|
"testB": {
|
||||||
{Version: version.MustParse("2.9"), Default: false, PreRelease: Alpha},
|
{Version: version.MustParse("2.9"), Default: false, PreRelease: featuregate.Alpha},
|
||||||
},
|
},
|
||||||
"commonC": {
|
"commonC": {
|
||||||
{Version: version.MustParse("2.7"), Default: false, PreRelease: Alpha},
|
{Version: version.MustParse("2.7"), Default: false, PreRelease: featuregate.Alpha},
|
||||||
{Version: version.MustParse("2.9"), Default: true, PreRelease: Beta},
|
{Version: version.MustParse("2.9"), Default: true, PreRelease: featuregate.Beta},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -154,8 +154,8 @@ func TestFlags(t *testing.T) {
|
|||||||
parseError string
|
parseError string
|
||||||
expectedKubeEmulationVersion string
|
expectedKubeEmulationVersion string
|
||||||
expectedTestEmulationVersion string
|
expectedTestEmulationVersion string
|
||||||
expectedKubeFeatureValues map[Feature]bool
|
expectedKubeFeatureValues map[featuregate.Feature]bool
|
||||||
expectedTestFeatureValues map[Feature]bool
|
expectedTestFeatureValues map[featuregate.Feature]bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "setting kube emulation version",
|
name: "setting kube emulation version",
|
||||||
@@ -214,8 +214,8 @@ func TestFlags(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expectedKubeEmulationVersion: "1.31",
|
expectedKubeEmulationVersion: "1.31",
|
||||||
expectedTestEmulationVersion: "2.7",
|
expectedTestEmulationVersion: "2.7",
|
||||||
expectedKubeFeatureValues: map[Feature]bool{"kubeA": true, "kubeB": false, "commonC": true},
|
expectedKubeFeatureValues: map[featuregate.Feature]bool{"kubeA": true, "kubeB": false, "commonC": true},
|
||||||
expectedTestFeatureValues: map[Feature]bool{"testA": true, "testB": false, "commonC": false},
|
expectedTestFeatureValues: map[featuregate.Feature]bool{"testA": true, "testB": false, "commonC": false},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "setting future test feature flag",
|
name: "setting future test feature flag",
|
||||||
@@ -235,8 +235,8 @@ func TestFlags(t *testing.T) {
|
|||||||
},
|
},
|
||||||
expectedKubeEmulationVersion: "1.30",
|
expectedKubeEmulationVersion: "1.30",
|
||||||
expectedTestEmulationVersion: "2.7",
|
expectedTestEmulationVersion: "2.7",
|
||||||
expectedKubeFeatureValues: map[Feature]bool{"kubeA": false, "kubeB": true, "commonC": false},
|
expectedKubeFeatureValues: map[featuregate.Feature]bool{"kubeA": false, "kubeB": true, "commonC": false},
|
||||||
expectedTestFeatureValues: map[Feature]bool{"testA": false, "testB": false, "commonC": true},
|
expectedTestFeatureValues: map[featuregate.Feature]bool{"testA": false, "testB": false, "commonC": true},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "setting kube feature flag with different prefix",
|
name: "setting kube feature flag with different prefix",
|
||||||
@@ -313,9 +313,9 @@ func TestFlags(t *testing.T) {
|
|||||||
|
|
||||||
func TestVersionMapping(t *testing.T) {
|
func TestVersionMapping(t *testing.T) {
|
||||||
r := NewComponentGlobalsRegistry()
|
r := NewComponentGlobalsRegistry()
|
||||||
ver1 := baseversion.NewEffectiveVersion("0.58")
|
ver1 := NewEffectiveVersionFromString("0.58", "", "")
|
||||||
ver2 := baseversion.NewEffectiveVersion("1.28")
|
ver2 := NewEffectiveVersionFromString("1.28", "", "")
|
||||||
ver3 := baseversion.NewEffectiveVersion("2.10")
|
ver3 := NewEffectiveVersionFromString("2.10", "", "")
|
||||||
|
|
||||||
utilruntime.Must(r.Register("test1", ver1, nil))
|
utilruntime.Must(r.Register("test1", ver1, nil))
|
||||||
utilruntime.Must(r.Register("test2", ver2, nil))
|
utilruntime.Must(r.Register("test2", ver2, nil))
|
||||||
@@ -355,9 +355,9 @@ func TestVersionMapping(t *testing.T) {
|
|||||||
|
|
||||||
func TestVersionMappingWithMultipleDependency(t *testing.T) {
|
func TestVersionMappingWithMultipleDependency(t *testing.T) {
|
||||||
r := NewComponentGlobalsRegistry()
|
r := NewComponentGlobalsRegistry()
|
||||||
ver1 := baseversion.NewEffectiveVersion("0.58")
|
ver1 := NewEffectiveVersionFromString("0.58", "", "")
|
||||||
ver2 := baseversion.NewEffectiveVersion("1.28")
|
ver2 := NewEffectiveVersionFromString("1.28", "", "")
|
||||||
ver3 := baseversion.NewEffectiveVersion("2.10")
|
ver3 := NewEffectiveVersionFromString("2.10", "", "")
|
||||||
|
|
||||||
utilruntime.Must(r.Register("test1", ver1, nil))
|
utilruntime.Must(r.Register("test1", ver1, nil))
|
||||||
utilruntime.Must(r.Register("test2", ver2, nil))
|
utilruntime.Must(r.Register("test2", ver2, nil))
|
||||||
@@ -382,9 +382,9 @@ func TestVersionMappingWithMultipleDependency(t *testing.T) {
|
|||||||
|
|
||||||
func TestVersionMappingWithCyclicDependency(t *testing.T) {
|
func TestVersionMappingWithCyclicDependency(t *testing.T) {
|
||||||
r := NewComponentGlobalsRegistry()
|
r := NewComponentGlobalsRegistry()
|
||||||
ver1 := baseversion.NewEffectiveVersion("0.58")
|
ver1 := NewEffectiveVersionFromString("0.58", "", "")
|
||||||
ver2 := baseversion.NewEffectiveVersion("1.28")
|
ver2 := NewEffectiveVersionFromString("1.28", "", "")
|
||||||
ver3 := baseversion.NewEffectiveVersion("2.10")
|
ver3 := NewEffectiveVersionFromString("2.10", "", "")
|
||||||
|
|
||||||
utilruntime.Must(r.Register("test1", ver1, nil))
|
utilruntime.Must(r.Register("test1", ver1, nil))
|
||||||
utilruntime.Must(r.Register("test2", ver2, nil))
|
utilruntime.Must(r.Register("test2", ver2, nil))
|
||||||
213
staging/src/k8s.io/component-base/compatibility/version.go
Normal file
213
staging/src/k8s.io/component-base/compatibility/version.go
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
/*
|
||||||
|
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 (
|
||||||
|
"fmt"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/util/version"
|
||||||
|
baseversion "k8s.io/component-base/version"
|
||||||
|
)
|
||||||
|
|
||||||
|
// EffectiveVersion stores all the version information of a component.
|
||||||
|
type EffectiveVersion interface {
|
||||||
|
// BinaryVersion is the binary version of a component. Tied to a particular binary release.
|
||||||
|
BinaryVersion() *version.Version
|
||||||
|
// EmulationVersion is the version a component emulate its capabilities (APIs, features, ...) of.
|
||||||
|
// If EmulationVersion is set to be different from BinaryVersion, the component will emulate the behavior of this version instead of the underlying binary version.
|
||||||
|
EmulationVersion() *version.Version
|
||||||
|
// MinCompatibilityVersion is the minimum version a component is compatible with (in terms of storage versions, validation rules, ...).
|
||||||
|
MinCompatibilityVersion() *version.Version
|
||||||
|
EqualTo(other EffectiveVersion) bool
|
||||||
|
String() string
|
||||||
|
Validate() []error
|
||||||
|
// AllowedEmulationVersionRange returns the string of the allowed range of emulation version.
|
||||||
|
// Used only for docs/help.
|
||||||
|
AllowedEmulationVersionRange() string
|
||||||
|
// AllowedMinCompatibilityVersionRange returns the string of the allowed range of min compatibility version.
|
||||||
|
// Used only for docs/help.
|
||||||
|
AllowedMinCompatibilityVersionRange() string
|
||||||
|
}
|
||||||
|
|
||||||
|
type MutableEffectiveVersion interface {
|
||||||
|
EffectiveVersion
|
||||||
|
SetEmulationVersion(emulationVersion *version.Version)
|
||||||
|
SetMinCompatibilityVersion(minCompatibilityVersion *version.Version)
|
||||||
|
}
|
||||||
|
|
||||||
|
type effectiveVersion struct {
|
||||||
|
// When true, BinaryVersion() returns the current binary version
|
||||||
|
useDefaultBuildBinaryVersion atomic.Bool
|
||||||
|
// Holds the last binary version stored in Set()
|
||||||
|
binaryVersion atomic.Pointer[version.Version]
|
||||||
|
// If the emulationVersion is set by the users, it could only contain major and minor versions.
|
||||||
|
// In tests, emulationVersion could be the same as the binary version, or set directly,
|
||||||
|
// which can have "alpha" as pre-release to continue serving expired apis while we clean up the test.
|
||||||
|
emulationVersion atomic.Pointer[version.Version]
|
||||||
|
// minCompatibilityVersion could only contain major and minor versions.
|
||||||
|
minCompatibilityVersion atomic.Pointer[version.Version]
|
||||||
|
// emulationVersionFloor is the minimum emulationVersion allowed. No limit if nil.
|
||||||
|
emulationVersionFloor *version.Version
|
||||||
|
// minCompatibilityVersionFloor is the minimum minCompatibilityVersionFloor allowed. No limit if nil.
|
||||||
|
minCompatibilityVersionFloor *version.Version
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *effectiveVersion) BinaryVersion() *version.Version {
|
||||||
|
if m.useDefaultBuildBinaryVersion.Load() {
|
||||||
|
return defaultBuildBinaryVersion()
|
||||||
|
}
|
||||||
|
return m.binaryVersion.Load()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *effectiveVersion) EmulationVersion() *version.Version {
|
||||||
|
ver := m.emulationVersion.Load()
|
||||||
|
if ver != nil {
|
||||||
|
// Emulation version can have "alpha" as pre-release to continue serving expired apis while we clean up the test.
|
||||||
|
// The pre-release should not be accessible to the users.
|
||||||
|
return ver.WithPreRelease(m.BinaryVersion().PreRelease())
|
||||||
|
}
|
||||||
|
return ver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *effectiveVersion) MinCompatibilityVersion() *version.Version {
|
||||||
|
return m.minCompatibilityVersion.Load()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *effectiveVersion) EqualTo(other EffectiveVersion) bool {
|
||||||
|
return m.BinaryVersion().EqualTo(other.BinaryVersion()) && m.EmulationVersion().EqualTo(other.EmulationVersion()) && m.MinCompatibilityVersion().EqualTo(other.MinCompatibilityVersion())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *effectiveVersion) String() string {
|
||||||
|
if m == nil {
|
||||||
|
return "<nil>"
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("{BinaryVersion: %s, EmulationVersion: %s, MinCompatibilityVersion: %s}",
|
||||||
|
m.BinaryVersion().String(), m.EmulationVersion().String(), m.MinCompatibilityVersion().String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func majorMinor(ver *version.Version) *version.Version {
|
||||||
|
if ver == nil {
|
||||||
|
return ver
|
||||||
|
}
|
||||||
|
return version.MajorMinor(ver.Major(), ver.Minor())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *effectiveVersion) SetEmulationVersion(emulationVersion *version.Version) {
|
||||||
|
m.emulationVersion.Store(majorMinor(emulationVersion))
|
||||||
|
// set the default minCompatibilityVersion to be emulationVersion - 1 if possible
|
||||||
|
minCompatibilityVersion := majorMinor(emulationVersion.SubtractMinor(1))
|
||||||
|
if minCompatibilityVersion.LessThan(m.minCompatibilityVersionFloor) {
|
||||||
|
minCompatibilityVersion = m.minCompatibilityVersionFloor
|
||||||
|
}
|
||||||
|
m.minCompatibilityVersion.Store(minCompatibilityVersion)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetMinCompatibilityVersion should be called after SetEmulationVersion
|
||||||
|
func (m *effectiveVersion) SetMinCompatibilityVersion(minCompatibilityVersion *version.Version) {
|
||||||
|
m.minCompatibilityVersion.Store(majorMinor(minCompatibilityVersion))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *effectiveVersion) AllowedEmulationVersionRange() string {
|
||||||
|
binaryVersion := m.BinaryVersion()
|
||||||
|
if binaryVersion == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Consider patch version to be 0.
|
||||||
|
binaryVersion = version.MajorMinor(binaryVersion.Major(), binaryVersion.Minor())
|
||||||
|
|
||||||
|
floor := m.emulationVersionFloor
|
||||||
|
if floor == nil {
|
||||||
|
floor = version.MajorMinor(0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%s..%s (default=%s)", floor.String(), binaryVersion.String(), m.EmulationVersion().String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *effectiveVersion) AllowedMinCompatibilityVersionRange() string {
|
||||||
|
binaryVersion := m.BinaryVersion()
|
||||||
|
if binaryVersion == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Consider patch version to be 0.
|
||||||
|
binaryVersion = version.MajorMinor(binaryVersion.Major(), binaryVersion.Minor())
|
||||||
|
|
||||||
|
floor := m.minCompatibilityVersionFloor
|
||||||
|
if floor == nil {
|
||||||
|
floor = version.MajorMinor(0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf("%s..%s (default=%s)", floor.String(), binaryVersion.String(), m.MinCompatibilityVersion().String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *effectiveVersion) Validate() []error {
|
||||||
|
var errs []error
|
||||||
|
// Validate only checks the major and minor versions.
|
||||||
|
binaryVersion := m.BinaryVersion().WithPatch(0)
|
||||||
|
emulationVersion := m.emulationVersion.Load()
|
||||||
|
minCompatibilityVersion := m.minCompatibilityVersion.Load()
|
||||||
|
// emulationVersion can only be between emulationVersionFloor and binaryVersion
|
||||||
|
if emulationVersion.GreaterThan(binaryVersion) || emulationVersion.LessThan(m.emulationVersionFloor) {
|
||||||
|
errs = append(errs, fmt.Errorf("emulation version %s is not between [%s, %s]", emulationVersion.String(), m.emulationVersionFloor.String(), binaryVersion.String()))
|
||||||
|
}
|
||||||
|
// minCompatibilityVersion can only be between minCompatibilityVersionFloor and emulationVersion
|
||||||
|
if minCompatibilityVersion.GreaterThan(emulationVersion) || minCompatibilityVersion.LessThan(m.minCompatibilityVersionFloor) {
|
||||||
|
errs = append(errs, fmt.Errorf("minCompatibilityVersion version %s is not between [%s, %s]", minCompatibilityVersion.String(), m.minCompatibilityVersionFloor.String(), emulationVersion.String()))
|
||||||
|
}
|
||||||
|
return errs
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewEffectiveVersion creates a MutableEffectiveVersion from the binaryVersion.
|
||||||
|
// If useDefaultBuildBinaryVersion is true, the call of BinaryVersion() will always return the current binary version.
|
||||||
|
// NewEffectiveVersion(binaryVersion, true) should only be used if the binary version is dynamic.
|
||||||
|
// Otherwise, use NewEffectiveVersion(binaryVersion, false) or NewEffectiveVersionFromString.
|
||||||
|
func NewEffectiveVersion(binaryVersion *version.Version, useDefaultBuildBinaryVersion bool, emulationVersionFloor, minCompatibilityVersionFloor *version.Version) MutableEffectiveVersion {
|
||||||
|
effective := &effectiveVersion{
|
||||||
|
emulationVersionFloor: emulationVersionFloor,
|
||||||
|
minCompatibilityVersionFloor: minCompatibilityVersionFloor,
|
||||||
|
}
|
||||||
|
compatVersion := binaryVersion.SubtractMinor(1)
|
||||||
|
effective.binaryVersion.Store(binaryVersion)
|
||||||
|
effective.useDefaultBuildBinaryVersion.Store(useDefaultBuildBinaryVersion)
|
||||||
|
effective.SetEmulationVersion(binaryVersion)
|
||||||
|
effective.SetMinCompatibilityVersion(compatVersion)
|
||||||
|
return effective
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewEffectiveVersionFromString creates a MutableEffectiveVersion from the binaryVersion string.
|
||||||
|
func NewEffectiveVersionFromString(binaryVer, emulationVerFloor, minCompatibilityVerFloor string) MutableEffectiveVersion {
|
||||||
|
if binaryVer == "" {
|
||||||
|
return &effectiveVersion{}
|
||||||
|
}
|
||||||
|
binaryVersion := version.MustParse(binaryVer)
|
||||||
|
emulationVersionFloor := version.MajorMinor(0, 0)
|
||||||
|
if emulationVerFloor != "" {
|
||||||
|
emulationVersionFloor = version.MustParse(emulationVerFloor)
|
||||||
|
}
|
||||||
|
minCompatibilityVersionFloor := version.MajorMinor(0, 0)
|
||||||
|
if minCompatibilityVerFloor != "" {
|
||||||
|
minCompatibilityVersionFloor = version.MustParse(minCompatibilityVerFloor)
|
||||||
|
}
|
||||||
|
return NewEffectiveVersion(binaryVersion, false, emulationVersionFloor, minCompatibilityVersionFloor)
|
||||||
|
}
|
||||||
|
|
||||||
|
func defaultBuildBinaryVersion() *version.Version {
|
||||||
|
verInfo := baseversion.Get()
|
||||||
|
return version.MustParse(verInfo.String()).WithInfo(verInfo)
|
||||||
|
}
|
||||||
148
staging/src/k8s.io/component-base/compatibility/version_test.go
Normal file
148
staging/src/k8s.io/component-base/compatibility/version_test.go
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2024 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"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestValidate(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
binaryVersion string
|
||||||
|
emulationVersion string
|
||||||
|
minCompatibilityVersion string
|
||||||
|
emulationVersionFloor string
|
||||||
|
minCompatibilityVersionFloor string
|
||||||
|
expectErrors bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "patch version diff ok",
|
||||||
|
binaryVersion: "v1.32.1",
|
||||||
|
emulationVersion: "v1.32.2",
|
||||||
|
minCompatibilityVersion: "v1.32.5",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "emulation version greater than binary not ok",
|
||||||
|
binaryVersion: "v1.32.2",
|
||||||
|
emulationVersion: "v1.33.0",
|
||||||
|
minCompatibilityVersion: "v1.31.0",
|
||||||
|
expectErrors: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "min compatibility version greater than emulation version not ok",
|
||||||
|
binaryVersion: "v1.32.2",
|
||||||
|
emulationVersion: "v1.31.0",
|
||||||
|
minCompatibilityVersion: "v1.32.0",
|
||||||
|
expectErrors: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "between floor and binary ok",
|
||||||
|
binaryVersion: "v1.32.1",
|
||||||
|
emulationVersion: "v1.31.0",
|
||||||
|
minCompatibilityVersion: "v1.30.0",
|
||||||
|
emulationVersionFloor: "v1.31.0",
|
||||||
|
minCompatibilityVersionFloor: "v1.30.0",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "emulation version less than floor not ok",
|
||||||
|
binaryVersion: "v1.32.1",
|
||||||
|
emulationVersion: "v1.30.0",
|
||||||
|
minCompatibilityVersion: "v1.30.0",
|
||||||
|
emulationVersionFloor: "v1.31.0",
|
||||||
|
minCompatibilityVersionFloor: "v1.30.0",
|
||||||
|
expectErrors: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "min compatibility version less than floor not ok",
|
||||||
|
binaryVersion: "v1.32.1",
|
||||||
|
emulationVersion: "v1.31.0",
|
||||||
|
minCompatibilityVersion: "v1.29.0",
|
||||||
|
emulationVersionFloor: "v1.31.0",
|
||||||
|
minCompatibilityVersionFloor: "v1.30.0",
|
||||||
|
expectErrors: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
effective := NewEffectiveVersionFromString(test.binaryVersion, test.emulationVersionFloor, test.minCompatibilityVersionFloor)
|
||||||
|
emulationVersion := version.MustParseGeneric(test.emulationVersion)
|
||||||
|
minCompatibilityVersion := version.MustParseGeneric(test.minCompatibilityVersion)
|
||||||
|
effective.SetEmulationVersion(emulationVersion)
|
||||||
|
effective.SetMinCompatibilityVersion(minCompatibilityVersion)
|
||||||
|
|
||||||
|
errs := effective.Validate()
|
||||||
|
if len(errs) > 0 && !test.expectErrors {
|
||||||
|
t.Errorf("expected no errors, errors found %+v", errs)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(errs) == 0 && test.expectErrors {
|
||||||
|
t.Errorf("expected errors, no errors found")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetEmulationVersion(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
binaryVersion string
|
||||||
|
emulationVersion string
|
||||||
|
expectMinCompatibilityVersion string
|
||||||
|
emulationVersionFloor string
|
||||||
|
minCompatibilityVersionFloor string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "minCompatibilityVersion default to 1 minor less than emulationVersion",
|
||||||
|
binaryVersion: "v1.34",
|
||||||
|
emulationVersion: "v1.32",
|
||||||
|
expectMinCompatibilityVersion: "v1.31",
|
||||||
|
emulationVersionFloor: "v1.31",
|
||||||
|
minCompatibilityVersionFloor: "v1.31",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "minCompatibilityVersion default to emulationVersion when hitting the floor",
|
||||||
|
binaryVersion: "v1.34",
|
||||||
|
emulationVersion: "v1.31",
|
||||||
|
expectMinCompatibilityVersion: "v1.31",
|
||||||
|
emulationVersionFloor: "v1.31",
|
||||||
|
minCompatibilityVersionFloor: "v1.31",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
t.Run(test.name, func(t *testing.T) {
|
||||||
|
effective := NewEffectiveVersionFromString(test.binaryVersion, test.emulationVersionFloor, test.minCompatibilityVersionFloor)
|
||||||
|
|
||||||
|
emulationVersion := version.MustParseGeneric(test.emulationVersion)
|
||||||
|
effective.SetEmulationVersion(emulationVersion)
|
||||||
|
errs := effective.Validate()
|
||||||
|
if len(errs) > 0 {
|
||||||
|
t.Fatalf("expected no Validate errors, errors found %+v", errs)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
expectMinCompatibilityVersion := version.MustParseGeneric(test.expectMinCompatibilityVersion)
|
||||||
|
if !effective.MinCompatibilityVersion().EqualTo(expectMinCompatibilityVersion) {
|
||||||
|
t.Errorf("expected minCompatibilityVersion %s, got %s", expectMinCompatibilityVersion.String(), effective.MinCompatibilityVersion().String())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,43 +19,10 @@ package version
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"runtime"
|
"runtime"
|
||||||
"sync/atomic"
|
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/util/version"
|
|
||||||
apimachineryversion "k8s.io/apimachinery/pkg/version"
|
apimachineryversion "k8s.io/apimachinery/pkg/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
var minimumKubeEmulationVersion *version.Version = version.MajorMinor(1, 31)
|
|
||||||
|
|
||||||
type EffectiveVersion interface {
|
|
||||||
BinaryVersion() *version.Version
|
|
||||||
EmulationVersion() *version.Version
|
|
||||||
MinCompatibilityVersion() *version.Version
|
|
||||||
EqualTo(other EffectiveVersion) bool
|
|
||||||
String() string
|
|
||||||
Validate() []error
|
|
||||||
}
|
|
||||||
|
|
||||||
type MutableEffectiveVersion interface {
|
|
||||||
EffectiveVersion
|
|
||||||
Set(binaryVersion, emulationVersion, minCompatibilityVersion *version.Version)
|
|
||||||
SetEmulationVersion(emulationVersion *version.Version)
|
|
||||||
SetMinCompatibilityVersion(minCompatibilityVersion *version.Version)
|
|
||||||
}
|
|
||||||
|
|
||||||
type effectiveVersion struct {
|
|
||||||
// When true, BinaryVersion() returns the current binary version
|
|
||||||
useDefaultBuildBinaryVersion atomic.Bool
|
|
||||||
// Holds the last binary version stored in Set()
|
|
||||||
binaryVersion atomic.Pointer[version.Version]
|
|
||||||
// If the emulationVersion is set by the users, it could only contain major and minor versions.
|
|
||||||
// In tests, emulationVersion could be the same as the binary version, or set directly,
|
|
||||||
// which can have "alpha" as pre-release to continue serving expired apis while we clean up the test.
|
|
||||||
emulationVersion atomic.Pointer[version.Version]
|
|
||||||
// minCompatibilityVersion could only contain major and minor versions.
|
|
||||||
minCompatibilityVersion atomic.Pointer[version.Version]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get returns the overall codebase version. It's for detecting
|
// Get returns the overall codebase version. It's for detecting
|
||||||
// what code a binary was built from.
|
// what code a binary was built from.
|
||||||
func Get() apimachineryversion.Info {
|
func Get() apimachineryversion.Info {
|
||||||
@@ -73,134 +40,3 @@ func Get() apimachineryversion.Info {
|
|||||||
Platform: fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH),
|
Platform: fmt.Sprintf("%s/%s", runtime.GOOS, runtime.GOARCH),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *effectiveVersion) BinaryVersion() *version.Version {
|
|
||||||
if m.useDefaultBuildBinaryVersion.Load() {
|
|
||||||
return defaultBuildBinaryVersion()
|
|
||||||
}
|
|
||||||
return m.binaryVersion.Load()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *effectiveVersion) EmulationVersion() *version.Version {
|
|
||||||
ver := m.emulationVersion.Load()
|
|
||||||
if ver != nil {
|
|
||||||
// Emulation version can have "alpha" as pre-release to continue serving expired apis while we clean up the test.
|
|
||||||
// The pre-release should not be accessible to the users.
|
|
||||||
return ver.WithPreRelease(m.BinaryVersion().PreRelease())
|
|
||||||
}
|
|
||||||
return ver
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *effectiveVersion) MinCompatibilityVersion() *version.Version {
|
|
||||||
return m.minCompatibilityVersion.Load()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *effectiveVersion) EqualTo(other EffectiveVersion) bool {
|
|
||||||
return m.BinaryVersion().EqualTo(other.BinaryVersion()) && m.EmulationVersion().EqualTo(other.EmulationVersion()) && m.MinCompatibilityVersion().EqualTo(other.MinCompatibilityVersion())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *effectiveVersion) String() string {
|
|
||||||
if m == nil {
|
|
||||||
return "<nil>"
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("{BinaryVersion: %s, EmulationVersion: %s, MinCompatibilityVersion: %s}",
|
|
||||||
m.BinaryVersion().String(), m.EmulationVersion().String(), m.MinCompatibilityVersion().String())
|
|
||||||
}
|
|
||||||
|
|
||||||
func majorMinor(ver *version.Version) *version.Version {
|
|
||||||
if ver == nil {
|
|
||||||
return ver
|
|
||||||
}
|
|
||||||
return version.MajorMinor(ver.Major(), ver.Minor())
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *effectiveVersion) Set(binaryVersion, emulationVersion, minCompatibilityVersion *version.Version) {
|
|
||||||
m.binaryVersion.Store(binaryVersion)
|
|
||||||
m.useDefaultBuildBinaryVersion.Store(false)
|
|
||||||
m.emulationVersion.Store(majorMinor(emulationVersion))
|
|
||||||
m.minCompatibilityVersion.Store(majorMinor(minCompatibilityVersion))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *effectiveVersion) SetEmulationVersion(emulationVersion *version.Version) {
|
|
||||||
m.emulationVersion.Store(majorMinor(emulationVersion))
|
|
||||||
// set the default minCompatibilityVersion to be emulationVersion - 1
|
|
||||||
m.minCompatibilityVersion.Store(majorMinor(emulationVersion.SubtractMinor(1)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// SetMinCompatibilityVersion should be called after SetEmulationVersion
|
|
||||||
func (m *effectiveVersion) SetMinCompatibilityVersion(minCompatibilityVersion *version.Version) {
|
|
||||||
m.minCompatibilityVersion.Store(majorMinor(minCompatibilityVersion))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *effectiveVersion) Validate() []error {
|
|
||||||
var errs []error
|
|
||||||
// Validate only checks the major and minor versions.
|
|
||||||
binaryVersion := m.BinaryVersion().WithPatch(0)
|
|
||||||
emulationVersion := m.emulationVersion.Load()
|
|
||||||
minCompatibilityVersion := m.minCompatibilityVersion.Load()
|
|
||||||
|
|
||||||
// emulationVersion can only be 1.{binaryMinor-3}...1.{binaryMinor}
|
|
||||||
maxEmuVer := binaryVersion
|
|
||||||
minEmuVer := binaryVersion.SubtractMinor(3)
|
|
||||||
if emulationVersion.GreaterThan(maxEmuVer) || emulationVersion.LessThan(minEmuVer) {
|
|
||||||
errs = append(errs, fmt.Errorf("emulation version %s is not between [%s, %s]", emulationVersion.String(), minEmuVer.String(), maxEmuVer.String()))
|
|
||||||
}
|
|
||||||
// minCompatibilityVersion can only be 1.{binaryMinor-3} to 1.{binaryMinor}
|
|
||||||
maxCompVer := emulationVersion
|
|
||||||
minCompVer := binaryVersion.SubtractMinor(4)
|
|
||||||
if minCompatibilityVersion.GreaterThan(maxCompVer) || minCompatibilityVersion.LessThan(minCompVer) {
|
|
||||||
errs = append(errs, fmt.Errorf("minCompatibilityVersion version %s is not between [%s, %s]", minCompatibilityVersion.String(), minCompVer.String(), maxCompVer.String()))
|
|
||||||
}
|
|
||||||
return errs
|
|
||||||
}
|
|
||||||
|
|
||||||
func newEffectiveVersion(binaryVersion *version.Version, useDefaultBuildBinaryVersion bool) MutableEffectiveVersion {
|
|
||||||
effective := &effectiveVersion{}
|
|
||||||
compatVersion := binaryVersion.SubtractMinor(1)
|
|
||||||
effective.Set(binaryVersion, binaryVersion, compatVersion)
|
|
||||||
effective.useDefaultBuildBinaryVersion.Store(useDefaultBuildBinaryVersion)
|
|
||||||
return effective
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewEffectiveVersion(binaryVer string) MutableEffectiveVersion {
|
|
||||||
if binaryVer == "" {
|
|
||||||
return &effectiveVersion{}
|
|
||||||
}
|
|
||||||
binaryVersion := version.MustParse(binaryVer)
|
|
||||||
return newEffectiveVersion(binaryVersion, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
func defaultBuildBinaryVersion() *version.Version {
|
|
||||||
verInfo := Get()
|
|
||||||
return version.MustParse(verInfo.String()).WithInfo(verInfo)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DefaultBuildEffectiveVersion returns the MutableEffectiveVersion based on the
|
|
||||||
// current build information.
|
|
||||||
func DefaultBuildEffectiveVersion() MutableEffectiveVersion {
|
|
||||||
binaryVersion := defaultBuildBinaryVersion()
|
|
||||||
if binaryVersion.Major() == 0 && binaryVersion.Minor() == 0 {
|
|
||||||
return DefaultKubeEffectiveVersion()
|
|
||||||
}
|
|
||||||
return newEffectiveVersion(binaryVersion, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DefaultKubeEffectiveVersion returns the MutableEffectiveVersion based on the
|
|
||||||
// latest K8s release.
|
|
||||||
func DefaultKubeEffectiveVersion() MutableEffectiveVersion {
|
|
||||||
binaryVersion := version.MustParse(DefaultKubeBinaryVersion).WithInfo(Get())
|
|
||||||
return newEffectiveVersion(binaryVersion, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateKubeEffectiveVersion validates the EmulationVersion is at least 1.31 and MinCompatibilityVersion
|
|
||||||
// is at least 1.30 for kube components.
|
|
||||||
func ValidateKubeEffectiveVersion(effectiveVersion EffectiveVersion) error {
|
|
||||||
if !effectiveVersion.EmulationVersion().AtLeast(minimumKubeEmulationVersion) {
|
|
||||||
return fmt.Errorf("emulation version needs to be greater or equal to 1.31, got %s", effectiveVersion.EmulationVersion().String())
|
|
||||||
}
|
|
||||||
if !effectiveVersion.MinCompatibilityVersion().AtLeast(minimumKubeEmulationVersion.SubtractMinor(1)) {
|
|
||||||
return fmt.Errorf("minCompatibilityVersion version needs to be greater or equal to 1.30, got %s", effectiveVersion.MinCompatibilityVersion().String())
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,185 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2024 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 version
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/util/version"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestValidate(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
binaryVersion string
|
|
||||||
emulationVersion string
|
|
||||||
minCompatibilityVersion string
|
|
||||||
expectErrors bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "patch version diff ok",
|
|
||||||
binaryVersion: "v1.32.2",
|
|
||||||
emulationVersion: "v1.32.1",
|
|
||||||
minCompatibilityVersion: "v1.31.5",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "emulation version one minor lower than binary ok",
|
|
||||||
binaryVersion: "v1.32.2",
|
|
||||||
emulationVersion: "v1.31.0",
|
|
||||||
minCompatibilityVersion: "v1.31.0",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "emulation version two minor lower than binary ok",
|
|
||||||
binaryVersion: "v1.33.2",
|
|
||||||
emulationVersion: "v1.31.0",
|
|
||||||
minCompatibilityVersion: "v1.31.0",
|
|
||||||
expectErrors: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "emulation version three minor lower than binary ok",
|
|
||||||
binaryVersion: "v1.35.0",
|
|
||||||
emulationVersion: "v1.32.0",
|
|
||||||
minCompatibilityVersion: "v1.32.0",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "emulation version four minor lower than binary not ok",
|
|
||||||
binaryVersion: "v1.36.0",
|
|
||||||
emulationVersion: "v1.32.0",
|
|
||||||
minCompatibilityVersion: "v1.32.0",
|
|
||||||
expectErrors: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "emulation version one minor higher than binary not ok",
|
|
||||||
binaryVersion: "v1.32.2",
|
|
||||||
emulationVersion: "v1.33.0",
|
|
||||||
minCompatibilityVersion: "v1.31.0",
|
|
||||||
expectErrors: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "emulation version two minor higher than binary not ok",
|
|
||||||
binaryVersion: "v1.32.2",
|
|
||||||
emulationVersion: "v1.34.0",
|
|
||||||
minCompatibilityVersion: "v1.31.0",
|
|
||||||
expectErrors: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "compatibility version same as binary ok",
|
|
||||||
binaryVersion: "v1.32.2",
|
|
||||||
emulationVersion: "v1.32.0",
|
|
||||||
minCompatibilityVersion: "v1.32.0",
|
|
||||||
expectErrors: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "compatibility version two minor lower than binary ok",
|
|
||||||
binaryVersion: "v1.32.2",
|
|
||||||
emulationVersion: "v1.32.0",
|
|
||||||
minCompatibilityVersion: "v1.30.0",
|
|
||||||
expectErrors: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "compatibility version three minor lower than binary ok",
|
|
||||||
binaryVersion: "v1.34.2",
|
|
||||||
emulationVersion: "v1.33.0",
|
|
||||||
minCompatibilityVersion: "v1.31.0",
|
|
||||||
expectErrors: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "compatibility version one minor higher than binary not ok",
|
|
||||||
binaryVersion: "v1.32.2",
|
|
||||||
emulationVersion: "v1.32.0",
|
|
||||||
minCompatibilityVersion: "v1.33.0",
|
|
||||||
expectErrors: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "emulation version lower than compatibility version not ok",
|
|
||||||
binaryVersion: "v1.34.2",
|
|
||||||
emulationVersion: "v1.32.0",
|
|
||||||
minCompatibilityVersion: "v1.33.0",
|
|
||||||
expectErrors: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
t.Run(test.name, func(t *testing.T) {
|
|
||||||
binaryVersion := version.MustParseGeneric(test.binaryVersion)
|
|
||||||
effective := &effectiveVersion{}
|
|
||||||
emulationVersion := version.MustParseGeneric(test.emulationVersion)
|
|
||||||
minCompatibilityVersion := version.MustParseGeneric(test.minCompatibilityVersion)
|
|
||||||
effective.Set(binaryVersion, emulationVersion, minCompatibilityVersion)
|
|
||||||
|
|
||||||
errs := effective.Validate()
|
|
||||||
if len(errs) > 0 && !test.expectErrors {
|
|
||||||
t.Errorf("expected no errors, errors found %+v", errs)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(errs) == 0 && test.expectErrors {
|
|
||||||
t.Errorf("expected errors, no errors found")
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestValidateKubeEffectiveVersion(t *testing.T) {
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
emulationVersion string
|
|
||||||
minCompatibilityVersion string
|
|
||||||
expectErr bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "valid versions",
|
|
||||||
emulationVersion: "v1.31.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.29.0",
|
|
||||||
expectErr: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "both versions too low",
|
|
||||||
emulationVersion: "v1.30.0",
|
|
||||||
minCompatibilityVersion: "v1.30.0",
|
|
||||||
expectErr: true,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, test := range tests {
|
|
||||||
t.Run(test.name, func(t *testing.T) {
|
|
||||||
|
|
||||||
effective := NewEffectiveVersion("1.32")
|
|
||||||
effective.SetEmulationVersion(version.MustParseGeneric(test.emulationVersion))
|
|
||||||
effective.SetMinCompatibilityVersion(version.MustParseGeneric(test.minCompatibilityVersion))
|
|
||||||
|
|
||||||
err := ValidateKubeEffectiveVersion(effective)
|
|
||||||
if test.expectErr && err == nil {
|
|
||||||
t.Error("expected error, but got nil")
|
|
||||||
}
|
|
||||||
if !test.expectErr && err != nil {
|
|
||||||
t.Errorf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -20,9 +20,9 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/util/version"
|
"k8s.io/apimachinery/pkg/util/version"
|
||||||
"k8s.io/component-base/featuregate"
|
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
|
||||||
|
"k8s.io/component-base/compatibility"
|
||||||
compbasemetrics "k8s.io/component-base/metrics"
|
compbasemetrics "k8s.io/component-base/metrics"
|
||||||
utilversion "k8s.io/component-base/version"
|
utilversion "k8s.io/component-base/version"
|
||||||
)
|
)
|
||||||
@@ -34,9 +34,12 @@ type statuszRegistry interface {
|
|||||||
emulationVersion() *version.Version
|
emulationVersion() *version.Version
|
||||||
}
|
}
|
||||||
|
|
||||||
type registry struct{}
|
type registry struct {
|
||||||
|
// componentGlobalsRegistry compatibility.ComponentGlobalsRegistry
|
||||||
|
effectiveVersion compatibility.EffectiveVersion
|
||||||
|
}
|
||||||
|
|
||||||
func (registry) processStartTime() time.Time {
|
func (*registry) processStartTime() time.Time {
|
||||||
start, err := compbasemetrics.GetProcessStart()
|
start, err := compbasemetrics.GetProcessStart()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("Could not get process start time, %v", err)
|
klog.Errorf("Could not get process start time, %v", err)
|
||||||
@@ -45,23 +48,20 @@ func (registry) processStartTime() time.Time {
|
|||||||
return time.Unix(int64(start), 0)
|
return time.Unix(int64(start), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (registry) goVersion() string {
|
func (*registry) goVersion() string {
|
||||||
return utilversion.Get().GoVersion
|
return utilversion.Get().GoVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
func (registry) binaryVersion() *version.Version {
|
func (r *registry) binaryVersion() *version.Version {
|
||||||
effectiveVer := featuregate.DefaultComponentGlobalsRegistry.EffectiveVersionFor(featuregate.DefaultKubeComponent)
|
if r.effectiveVersion != nil {
|
||||||
if effectiveVer != nil {
|
return r.effectiveVersion.BinaryVersion()
|
||||||
return effectiveVer.BinaryVersion()
|
}
|
||||||
|
return version.MustParse(utilversion.Get().String())
|
||||||
}
|
}
|
||||||
|
|
||||||
return utilversion.DefaultKubeEffectiveVersion().BinaryVersion()
|
func (r *registry) emulationVersion() *version.Version {
|
||||||
}
|
if r.effectiveVersion != nil {
|
||||||
|
return r.effectiveVersion.EmulationVersion()
|
||||||
func (registry) emulationVersion() *version.Version {
|
|
||||||
effectiveVer := featuregate.DefaultComponentGlobalsRegistry.EffectiveVersionFor(featuregate.DefaultKubeComponent)
|
|
||||||
if effectiveVer != nil {
|
|
||||||
return effectiveVer.EmulationVersion()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -20,14 +20,12 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
|
||||||
"k8s.io/apimachinery/pkg/util/version"
|
"k8s.io/apimachinery/pkg/util/version"
|
||||||
"k8s.io/component-base/featuregate"
|
"k8s.io/component-base/compatibility"
|
||||||
utilversion "k8s.io/component-base/version"
|
utilversion "k8s.io/component-base/version"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestBinaryVersion(t *testing.T) {
|
func TestBinaryVersion(t *testing.T) {
|
||||||
componentGlobalsRegistry := featuregate.DefaultComponentGlobalsRegistry
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
setFakeEffectiveVersion bool
|
setFakeEffectiveVersion bool
|
||||||
@@ -42,20 +40,18 @@ func TestBinaryVersion(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "binaryVersion without effective version",
|
name: "binaryVersion without effective version",
|
||||||
wantBinaryVersion: utilversion.DefaultKubeEffectiveVersion().BinaryVersion(),
|
wantBinaryVersion: version.MustParse(utilversion.Get().String()),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
componentGlobalsRegistry.Reset()
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
registry := ®istry{}
|
||||||
if tt.setFakeEffectiveVersion {
|
if tt.setFakeEffectiveVersion {
|
||||||
verKube := utilversion.NewEffectiveVersion(tt.fakeVersion)
|
verKube := compatibility.NewEffectiveVersionFromString(tt.fakeVersion, "", "")
|
||||||
fg := featuregate.NewVersionedFeatureGate(version.MustParse(tt.fakeVersion))
|
registry.effectiveVersion = verKube
|
||||||
utilruntime.Must(componentGlobalsRegistry.Register(featuregate.DefaultKubeComponent, verKube, fg))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
registry := ®istry{}
|
|
||||||
got := registry.binaryVersion()
|
got := registry.binaryVersion()
|
||||||
assert.Equal(t, tt.wantBinaryVersion, got)
|
assert.Equal(t, tt.wantBinaryVersion, got)
|
||||||
})
|
})
|
||||||
@@ -63,7 +59,6 @@ func TestBinaryVersion(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestEmulationVersion(t *testing.T) {
|
func TestEmulationVersion(t *testing.T) {
|
||||||
componentGlobalsRegistry := featuregate.DefaultComponentGlobalsRegistry
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
setFakeEffectiveVersion bool
|
setFakeEffectiveVersion bool
|
||||||
@@ -83,16 +78,14 @@ func TestEmulationVersion(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
componentGlobalsRegistry.Reset()
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
registry := ®istry{}
|
||||||
if tt.setFakeEffectiveVersion {
|
if tt.setFakeEffectiveVersion {
|
||||||
verKube := utilversion.NewEffectiveVersion("0.0.0")
|
verKube := compatibility.NewEffectiveVersionFromString("0.0.0", "", "")
|
||||||
verKube.SetEmulationVersion(version.MustParse(tt.fakeEmulVer))
|
verKube.SetEmulationVersion(version.MustParse(tt.fakeEmulVer))
|
||||||
fg := featuregate.NewVersionedFeatureGate(version.MustParse(tt.fakeEmulVer))
|
registry.effectiveVersion = verKube
|
||||||
utilruntime.Must(componentGlobalsRegistry.Register(featuregate.DefaultKubeComponent, verKube, fg))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
registry := ®istry{}
|
|
||||||
got := registry.emulationVersion()
|
got := registry.emulationVersion()
|
||||||
if tt.wantEmul != nil && got != nil {
|
if tt.wantEmul != nil && got != nil {
|
||||||
assert.Equal(t, tt.wantEmul.Major(), got.Major())
|
assert.Equal(t, tt.wantEmul.Major(), got.Major())
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"k8s.io/component-base/compatibility"
|
||||||
"k8s.io/component-base/zpages/httputil"
|
"k8s.io/component-base/zpages/httputil"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
)
|
)
|
||||||
@@ -62,8 +63,8 @@ type mux interface {
|
|||||||
Handle(path string, handler http.Handler)
|
Handle(path string, handler http.Handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRegistry() statuszRegistry {
|
func NewRegistry(effectiveVersion compatibility.EffectiveVersion) statuszRegistry {
|
||||||
return registry{}
|
return ®istry{effectiveVersion: effectiveVersion}
|
||||||
}
|
}
|
||||||
|
|
||||||
func Install(m mux, componentName string, reg statuszRegistry) {
|
func Install(m mux, componentName string, reg statuszRegistry) {
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ require (
|
|||||||
github.com/google/gofuzz v1.2.0 // indirect
|
github.com/google/gofuzz v1.2.0 // indirect
|
||||||
github.com/google/uuid v1.6.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
|
||||||
github.com/josharian/intern v1.0.0 // indirect
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/json-iterator/go v1.1.12 // indirect
|
github.com/json-iterator/go v1.1.12 // indirect
|
||||||
github.com/mailru/easyjson v0.7.7 // indirect
|
github.com/mailru/easyjson v0.7.7 // indirect
|
||||||
@@ -57,7 +56,6 @@ require (
|
|||||||
github.com/prometheus/client_model v0.6.1 // indirect
|
github.com/prometheus/client_model v0.6.1 // indirect
|
||||||
github.com/prometheus/common v0.55.0 // indirect
|
github.com/prometheus/common v0.55.0 // indirect
|
||||||
github.com/prometheus/procfs v0.15.1 // indirect
|
github.com/prometheus/procfs v0.15.1 // indirect
|
||||||
github.com/spf13/cobra v1.8.1 // indirect
|
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/x448/float16 v0.8.4 // indirect
|
github.com/x448/float16 v0.8.4 // indirect
|
||||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
|
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
|
||||||
|
|||||||
4
staging/src/k8s.io/cri-client/go.sum
generated
4
staging/src/k8s.io/cri-client/go.sum
generated
@@ -18,7 +18,6 @@ github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91
|
|||||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
|
github.com/cncf/xds/go v0.0.0-20240423153145-555b57ec207b/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
@@ -70,7 +69,6 @@ github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad
|
|||||||
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0=
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0=
|
||||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
|
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||||
@@ -117,9 +115,7 @@ github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoG
|
|||||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
|
||||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
|
||||||
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ import (
|
|||||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||||
"k8s.io/apiserver/pkg/server/filters"
|
"k8s.io/apiserver/pkg/server/filters"
|
||||||
genericoptions "k8s.io/apiserver/pkg/server/options"
|
genericoptions "k8s.io/apiserver/pkg/server/options"
|
||||||
"k8s.io/component-base/featuregate"
|
|
||||||
"k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1"
|
"k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1"
|
||||||
"k8s.io/kube-aggregator/pkg/apiserver"
|
"k8s.io/kube-aggregator/pkg/apiserver"
|
||||||
aggregatorscheme "k8s.io/kube-aggregator/pkg/apiserver/scheme"
|
aggregatorscheme "k8s.io/kube-aggregator/pkg/apiserver/scheme"
|
||||||
@@ -63,7 +62,7 @@ func NewCommandStartAggregator(ctx context.Context, defaults *AggregatorOptions)
|
|||||||
Short: "Launch a API aggregator and proxy server",
|
Short: "Launch a API aggregator and proxy server",
|
||||||
Long: "Launch a API aggregator and proxy server",
|
Long: "Launch a API aggregator and proxy server",
|
||||||
PersistentPreRunE: func(*cobra.Command, []string) error {
|
PersistentPreRunE: func(*cobra.Command, []string) error {
|
||||||
return featuregate.DefaultComponentGlobalsRegistry.Set()
|
return o.ServerRunOptions.ComponentGlobalsRegistry.Set()
|
||||||
},
|
},
|
||||||
RunE: func(c *cobra.Command, args []string) error {
|
RunE: func(c *cobra.Command, args []string) error {
|
||||||
if err := o.Complete(); err != nil {
|
if err := o.Complete(); err != nil {
|
||||||
|
|||||||
@@ -33,9 +33,11 @@ import (
|
|||||||
"k8s.io/apiserver/pkg/endpoints/openapi"
|
"k8s.io/apiserver/pkg/endpoints/openapi"
|
||||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||||
genericoptions "k8s.io/apiserver/pkg/server/options"
|
genericoptions "k8s.io/apiserver/pkg/server/options"
|
||||||
|
"k8s.io/apiserver/pkg/util/compatibility"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
"k8s.io/component-base/featuregate"
|
"k8s.io/component-base/featuregate"
|
||||||
utilversion "k8s.io/component-base/version"
|
baseversion "k8s.io/component-base/version"
|
||||||
"k8s.io/sample-apiserver/pkg/admission/plugin/banflunder"
|
"k8s.io/sample-apiserver/pkg/admission/plugin/banflunder"
|
||||||
"k8s.io/sample-apiserver/pkg/admission/wardleinitializer"
|
"k8s.io/sample-apiserver/pkg/admission/wardleinitializer"
|
||||||
"k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1"
|
"k8s.io/sample-apiserver/pkg/apis/wardle/v1alpha1"
|
||||||
@@ -51,6 +53,8 @@ const defaultEtcdPathPrefix = "/registry/wardle.example.com"
|
|||||||
// WardleServerOptions contains state for master/api server
|
// WardleServerOptions contains state for master/api server
|
||||||
type WardleServerOptions struct {
|
type WardleServerOptions struct {
|
||||||
RecommendedOptions *genericoptions.RecommendedOptions
|
RecommendedOptions *genericoptions.RecommendedOptions
|
||||||
|
// ComponentGlobalsRegistry is the registry where the effective versions and feature gates for all components are stored.
|
||||||
|
ComponentGlobalsRegistry basecompatibility.ComponentGlobalsRegistry
|
||||||
|
|
||||||
SharedInformerFactory informers.SharedInformerFactory
|
SharedInformerFactory informers.SharedInformerFactory
|
||||||
StdOut io.Writer
|
StdOut io.Writer
|
||||||
@@ -63,7 +67,7 @@ func WardleVersionToKubeVersion(ver *version.Version) *version.Version {
|
|||||||
if ver.Major() != 1 {
|
if ver.Major() != 1 {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
kubeVer := utilversion.DefaultKubeEffectiveVersion().BinaryVersion()
|
kubeVer := version.MustParse(baseversion.DefaultKubeBinaryVersion)
|
||||||
// "1.2" maps to kubeVer
|
// "1.2" maps to kubeVer
|
||||||
offset := int(ver.Minor()) - 2
|
offset := int(ver.Minor()) - 2
|
||||||
mappedVer := kubeVer.OffsetMinor(offset)
|
mappedVer := kubeVer.OffsetMinor(offset)
|
||||||
@@ -80,6 +84,7 @@ func NewWardleServerOptions(out, errOut io.Writer) *WardleServerOptions {
|
|||||||
defaultEtcdPathPrefix,
|
defaultEtcdPathPrefix,
|
||||||
apiserver.Codecs.LegacyCodec(v1alpha1.SchemeGroupVersion),
|
apiserver.Codecs.LegacyCodec(v1alpha1.SchemeGroupVersion),
|
||||||
),
|
),
|
||||||
|
ComponentGlobalsRegistry: compatibility.DefaultComponentGlobalsRegistry,
|
||||||
|
|
||||||
StdOut: out,
|
StdOut: out,
|
||||||
StdErr: errOut,
|
StdErr: errOut,
|
||||||
@@ -99,7 +104,7 @@ func NewCommandStartWardleServer(ctx context.Context, defaults *WardleServerOpti
|
|||||||
if skipDefaultComponentGlobalsRegistrySet {
|
if skipDefaultComponentGlobalsRegistrySet {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return featuregate.DefaultComponentGlobalsRegistry.Set()
|
return defaults.ComponentGlobalsRegistry.Set()
|
||||||
},
|
},
|
||||||
RunE: func(c *cobra.Command, args []string) error {
|
RunE: func(c *cobra.Command, args []string) error {
|
||||||
if err := o.Complete(); err != nil {
|
if err := o.Complete(); err != nil {
|
||||||
@@ -135,8 +140,8 @@ func NewCommandStartWardleServer(ctx context.Context, defaults *WardleServerOpti
|
|||||||
// Register the "Wardle" component with the global component registry,
|
// Register the "Wardle" component with the global component registry,
|
||||||
// associating it with its effective version and feature gate configuration.
|
// associating it with its effective version and feature gate configuration.
|
||||||
// Will skip if the component has been registered, like in the integration test.
|
// Will skip if the component has been registered, like in the integration test.
|
||||||
_, wardleFeatureGate := featuregate.DefaultComponentGlobalsRegistry.ComponentGlobalsOrRegister(
|
_, wardleFeatureGate := defaults.ComponentGlobalsRegistry.ComponentGlobalsOrRegister(
|
||||||
apiserver.WardleComponentName, utilversion.NewEffectiveVersion(defaultWardleVersion),
|
apiserver.WardleComponentName, basecompatibility.NewEffectiveVersionFromString(defaultWardleVersion, "", ""),
|
||||||
featuregate.NewVersionedFeatureGate(version.MustParse(defaultWardleVersion)))
|
featuregate.NewVersionedFeatureGate(version.MustParse(defaultWardleVersion)))
|
||||||
|
|
||||||
// Add versioned feature specifications for the "BanFlunder" feature.
|
// Add versioned feature specifications for the "BanFlunder" feature.
|
||||||
@@ -150,14 +155,14 @@ func NewCommandStartWardleServer(ctx context.Context, defaults *WardleServerOpti
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
// Register the default kube component if not already present in the global registry.
|
// Register the default kube component if not already present in the global registry.
|
||||||
_, _ = featuregate.DefaultComponentGlobalsRegistry.ComponentGlobalsOrRegister(featuregate.DefaultKubeComponent,
|
_, _ = defaults.ComponentGlobalsRegistry.ComponentGlobalsOrRegister(basecompatibility.DefaultKubeComponent,
|
||||||
utilversion.NewEffectiveVersion(utilversion.DefaultKubeBinaryVersion), utilfeature.DefaultMutableFeatureGate)
|
basecompatibility.NewEffectiveVersionFromString(baseversion.DefaultKubeBinaryVersion, "", ""), utilfeature.DefaultMutableFeatureGate)
|
||||||
|
|
||||||
// Set the emulation version mapping from the "Wardle" component to the kube component.
|
// Set the emulation version mapping from the "Wardle" component to the kube component.
|
||||||
// This ensures that the emulation version of the latter is determined by the emulation version of the former.
|
// This ensures that the emulation version of the latter is determined by the emulation version of the former.
|
||||||
utilruntime.Must(featuregate.DefaultComponentGlobalsRegistry.SetEmulationVersionMapping(apiserver.WardleComponentName, featuregate.DefaultKubeComponent, WardleVersionToKubeVersion))
|
utilruntime.Must(defaults.ComponentGlobalsRegistry.SetEmulationVersionMapping(apiserver.WardleComponentName, basecompatibility.DefaultKubeComponent, WardleVersionToKubeVersion))
|
||||||
|
|
||||||
featuregate.DefaultComponentGlobalsRegistry.AddFlags(flags)
|
defaults.ComponentGlobalsRegistry.AddFlags(flags)
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
@@ -166,13 +171,13 @@ func NewCommandStartWardleServer(ctx context.Context, defaults *WardleServerOpti
|
|||||||
func (o WardleServerOptions) Validate(args []string) error {
|
func (o WardleServerOptions) Validate(args []string) error {
|
||||||
errors := []error{}
|
errors := []error{}
|
||||||
errors = append(errors, o.RecommendedOptions.Validate()...)
|
errors = append(errors, o.RecommendedOptions.Validate()...)
|
||||||
errors = append(errors, featuregate.DefaultComponentGlobalsRegistry.Validate()...)
|
errors = append(errors, o.ComponentGlobalsRegistry.Validate()...)
|
||||||
return utilerrors.NewAggregate(errors)
|
return utilerrors.NewAggregate(errors)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Complete fills in fields required to have valid data
|
// Complete fills in fields required to have valid data
|
||||||
func (o *WardleServerOptions) Complete() error {
|
func (o *WardleServerOptions) Complete() error {
|
||||||
if featuregate.DefaultComponentGlobalsRegistry.FeatureGateFor(apiserver.WardleComponentName).Enabled("BanFlunder") {
|
if o.ComponentGlobalsRegistry.FeatureGateFor(apiserver.WardleComponentName).Enabled("BanFlunder") {
|
||||||
// register admission plugins
|
// register admission plugins
|
||||||
banflunder.Register(o.RecommendedOptions.Admission.Plugins)
|
banflunder.Register(o.RecommendedOptions.Admission.Plugins)
|
||||||
|
|
||||||
@@ -209,8 +214,8 @@ func (o *WardleServerOptions) Config() (*apiserver.Config, error) {
|
|||||||
serverConfig.OpenAPIV3Config.Info.Title = "Wardle"
|
serverConfig.OpenAPIV3Config.Info.Title = "Wardle"
|
||||||
serverConfig.OpenAPIV3Config.Info.Version = "0.1"
|
serverConfig.OpenAPIV3Config.Info.Version = "0.1"
|
||||||
|
|
||||||
serverConfig.FeatureGate = featuregate.DefaultComponentGlobalsRegistry.FeatureGateFor(featuregate.DefaultKubeComponent)
|
serverConfig.FeatureGate = o.ComponentGlobalsRegistry.FeatureGateFor(basecompatibility.DefaultKubeComponent)
|
||||||
serverConfig.EffectiveVersion = featuregate.DefaultComponentGlobalsRegistry.EffectiveVersionFor(apiserver.WardleComponentName)
|
serverConfig.EffectiveVersion = o.ComponentGlobalsRegistry.EffectiveVersionFor(apiserver.WardleComponentName)
|
||||||
|
|
||||||
if err := o.RecommendedOptions.ApplyTo(serverConfig); err != nil {
|
if err := o.RecommendedOptions.ApplyTo(serverConfig); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -20,13 +20,13 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/util/version"
|
"k8s.io/apimachinery/pkg/util/version"
|
||||||
utilversion "k8s.io/component-base/version"
|
"k8s.io/apiserver/pkg/util/compatibility"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestWardleEmulationVersionToKubeEmulationVersion(t *testing.T) {
|
func TestWardleEmulationVersionToKubeEmulationVersion(t *testing.T) {
|
||||||
defaultKubeEffectiveVersion := utilversion.DefaultKubeEffectiveVersion()
|
defaultKubeEffectiveVersion := compatibility.DefaultKubeEffectiveVersionForTest()
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
desc string
|
desc string
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ import (
|
|||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io"
|
"io"
|
||||||
"k8s.io/apimachinery/pkg/util/version"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -634,9 +633,9 @@ func TestMatchConditionsWithoutStrictCostEnforcement(t *testing.T) {
|
|||||||
for _, testcase := range testcases {
|
for _, testcase := range testcases {
|
||||||
t.Run(testcase.name, func(t *testing.T) {
|
t.Run(testcase.name, func(t *testing.T) {
|
||||||
upCh := recorder.Reset()
|
upCh := recorder.Reset()
|
||||||
featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultFeatureGate, version.MustParse("1.31"))
|
server, err := apiservertesting.StartTestServer(t, nil, []string{
|
||||||
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.StrictCostEnforcementForWebhooks, false)
|
"--emulated-version", "1.31",
|
||||||
server, err := apiservertesting.StartTestServer(t, &apiservertesting.TestServerInstanceOptions{EmulationVersion: "1.31"}, []string{
|
"--feature-gates", "StrictCostEnforcementForWebhooks=false",
|
||||||
"--disable-admission-plugins=ServiceAccount",
|
"--disable-admission-plugins=ServiceAccount",
|
||||||
}, framework.SharedEtcd())
|
}, framework.SharedEtcd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -56,10 +56,12 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
utiljson "k8s.io/apimachinery/pkg/util/json"
|
utiljson "k8s.io/apimachinery/pkg/util/json"
|
||||||
"k8s.io/apimachinery/pkg/util/uuid"
|
"k8s.io/apimachinery/pkg/util/uuid"
|
||||||
|
"k8s.io/apimachinery/pkg/util/version"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
"k8s.io/apiserver/pkg/endpoints/handlers"
|
"k8s.io/apiserver/pkg/endpoints/handlers"
|
||||||
"k8s.io/apiserver/pkg/storage/storagebackend"
|
"k8s.io/apiserver/pkg/storage/storagebackend"
|
||||||
|
"k8s.io/apiserver/pkg/util/compatibility"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
"k8s.io/client-go/discovery/cached/memory"
|
"k8s.io/client-go/discovery/cached/memory"
|
||||||
"k8s.io/client-go/dynamic"
|
"k8s.io/client-go/dynamic"
|
||||||
@@ -70,7 +72,6 @@ import (
|
|||||||
"k8s.io/client-go/restmapper"
|
"k8s.io/client-go/restmapper"
|
||||||
"k8s.io/client-go/tools/pager"
|
"k8s.io/client-go/tools/pager"
|
||||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||||
utilversion "k8s.io/component-base/version"
|
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
"k8s.io/kubernetes/cmd/kube-apiserver/app/options"
|
"k8s.io/kubernetes/cmd/kube-apiserver/app/options"
|
||||||
kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing"
|
kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing"
|
||||||
@@ -3198,8 +3199,7 @@ func TestEmulatedStorageVersion(t *testing.T) {
|
|||||||
for emulatedVersion, cases := range groupedCases {
|
for emulatedVersion, cases := range groupedCases {
|
||||||
t.Run(emulatedVersion, func(t *testing.T) {
|
t.Run(emulatedVersion, func(t *testing.T) {
|
||||||
server := kubeapiservertesting.StartTestServerOrDie(
|
server := kubeapiservertesting.StartTestServerOrDie(
|
||||||
t, &kubeapiservertesting.TestServerInstanceOptions{BinaryVersion: emulatedVersion},
|
t, nil, []string{"--emulated-version=kube=" + emulatedVersion, `--storage-media-type=application/json`}, framework.SharedEtcd())
|
||||||
[]string{"--emulated-version=kube=" + emulatedVersion, `--storage-media-type=application/json`}, framework.SharedEtcd())
|
|
||||||
defer server.TearDownFn()
|
defer server.TearDownFn()
|
||||||
|
|
||||||
client := clientset.NewForConfigOrDie(server.ClientConfig)
|
client := clientset.NewForConfigOrDie(server.ClientConfig)
|
||||||
@@ -3302,7 +3302,7 @@ func TestAllowedEmulationVersions(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "default",
|
name: "default",
|
||||||
emulationVersion: utilversion.DefaultKubeEffectiveVersion().EmulationVersion().String(),
|
emulationVersion: compatibility.DefaultKubeEffectiveVersionForTest().EmulationVersion().String(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3337,6 +3337,7 @@ func TestAllowedEmulationVersions(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestEnableEmulationVersion(t *testing.T) {
|
func TestEnableEmulationVersion(t *testing.T) {
|
||||||
|
featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultFeatureGate, version.MustParse("1.32"))
|
||||||
server := kubeapiservertesting.StartTestServerOrDie(t,
|
server := kubeapiservertesting.StartTestServerOrDie(t,
|
||||||
&kubeapiservertesting.TestServerInstanceOptions{BinaryVersion: "1.32"},
|
&kubeapiservertesting.TestServerInstanceOptions{BinaryVersion: "1.32"},
|
||||||
[]string{"--emulated-version=kube=1.31"}, framework.SharedEtcd())
|
[]string{"--emulated-version=kube=1.31"}, framework.SharedEtcd())
|
||||||
@@ -3398,6 +3399,7 @@ func TestEnableEmulationVersion(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDisableEmulationVersion(t *testing.T) {
|
func TestDisableEmulationVersion(t *testing.T) {
|
||||||
|
featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultFeatureGate, version.MustParse("1.32"))
|
||||||
server := kubeapiservertesting.StartTestServerOrDie(t,
|
server := kubeapiservertesting.StartTestServerOrDie(t,
|
||||||
&kubeapiservertesting.TestServerInstanceOptions{BinaryVersion: "1.32"},
|
&kubeapiservertesting.TestServerInstanceOptions{BinaryVersion: "1.32"},
|
||||||
[]string{}, framework.SharedEtcd())
|
[]string{}, framework.SharedEtcd())
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"k8s.io/apimachinery/pkg/util/version"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"os"
|
"os"
|
||||||
@@ -2235,9 +2234,9 @@ func Test_CostLimitForValidation(t *testing.T) {
|
|||||||
func Test_CostLimitForValidationWithFeatureDisabled(t *testing.T) {
|
func Test_CostLimitForValidationWithFeatureDisabled(t *testing.T) {
|
||||||
resetPolicyRefreshInterval := generic.SetPolicyRefreshIntervalForTests(policyRefreshInterval)
|
resetPolicyRefreshInterval := generic.SetPolicyRefreshIntervalForTests(policyRefreshInterval)
|
||||||
defer resetPolicyRefreshInterval()
|
defer resetPolicyRefreshInterval()
|
||||||
featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultFeatureGate, version.MustParse("1.31"))
|
server, err := apiservertesting.StartTestServer(t, nil, []string{
|
||||||
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.StrictCostEnforcementForVAP, false)
|
"--emulated-version", "1.31",
|
||||||
server, err := apiservertesting.StartTestServer(t, &apiservertesting.TestServerInstanceOptions{EmulationVersion: "1.31"}, []string{
|
"--feature-gates", "StrictCostEnforcementForVAP=false",
|
||||||
"--enable-admission-plugins", "ValidatingAdmissionPolicy",
|
"--enable-admission-plugins", "ValidatingAdmissionPolicy",
|
||||||
}, framework.SharedEtcd())
|
}, framework.SharedEtcd())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
"k8s.io/apiserver/pkg/features"
|
"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"
|
||||||
appsv1ac "k8s.io/client-go/applyconfigurations/apps/v1"
|
appsv1ac "k8s.io/client-go/applyconfigurations/apps/v1"
|
||||||
autoscalingv1ac "k8s.io/client-go/applyconfigurations/autoscaling/v1"
|
autoscalingv1ac "k8s.io/client-go/applyconfigurations/autoscaling/v1"
|
||||||
@@ -83,7 +84,7 @@ func TestClient(t *testing.T) {
|
|||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
expectedInfo := utilversion.Get()
|
expectedInfo := utilversion.Get()
|
||||||
kubeVersion := utilversion.DefaultKubeEffectiveVersion().BinaryVersion()
|
kubeVersion := compatibility.DefaultKubeEffectiveVersionForTest().BinaryVersion()
|
||||||
expectedInfo.Major = fmt.Sprintf("%d", kubeVersion.Major())
|
expectedInfo.Major = fmt.Sprintf("%d", kubeVersion.Major())
|
||||||
expectedInfo.Minor = fmt.Sprintf("%d", kubeVersion.Minor())
|
expectedInfo.Minor = fmt.Sprintf("%d", kubeVersion.Minor())
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -117,7 +116,7 @@ func newTransformTest(tb testing.TB, transformerConfigYAML string, reload bool,
|
|||||||
return nil, fmt.Errorf("failed to read config file: %w", err)
|
return nil, fmt.Errorf("failed to read config file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.kubeAPIServer, err = startTestServerLocked(
|
if e.kubeAPIServer, err = kubeapiservertesting.StartTestServer(
|
||||||
tb, nil,
|
tb, nil,
|
||||||
e.getEncryptionOptions(reload), e.storageConfig); err != nil {
|
e.getEncryptionOptions(reload), e.storageConfig); err != nil {
|
||||||
e.cleanUp()
|
e.cleanUp()
|
||||||
@@ -148,15 +147,6 @@ func newTransformTest(tb testing.TB, transformerConfigYAML string, reload bool,
|
|||||||
return &e, nil
|
return &e, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var startTestServerLock sync.Mutex
|
|
||||||
|
|
||||||
// startTestServerLocked prevents parallel calls to kubeapiservertesting.StartTestServer because it messes with global state.
|
|
||||||
func startTestServerLocked(t ktesting.TB, instanceOptions *kubeapiservertesting.TestServerInstanceOptions, customFlags []string, storageConfig *storagebackend.Config) (result kubeapiservertesting.TestServer, err error) {
|
|
||||||
startTestServerLock.Lock()
|
|
||||||
defer startTestServerLock.Unlock()
|
|
||||||
return kubeapiservertesting.StartTestServer(t, instanceOptions, customFlags, storageConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *transformTest) cleanUp() {
|
func (e *transformTest) cleanUp() {
|
||||||
if e.configDir != "" {
|
if e.configDir != "" {
|
||||||
os.RemoveAll(e.configDir)
|
os.RemoveAll(e.configDir)
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/util/version"
|
"k8s.io/apimachinery/pkg/util/version"
|
||||||
|
"k8s.io/apiserver/pkg/util/compatibility"
|
||||||
utilversion "k8s.io/component-base/version"
|
utilversion "k8s.io/component-base/version"
|
||||||
|
|
||||||
"k8s.io/kubernetes/test/utils/image"
|
"k8s.io/kubernetes/test/utils/image"
|
||||||
@@ -34,9 +35,9 @@ import (
|
|||||||
// Tests aiming for full coverage of versions should test fixtures of all supported versions.
|
// Tests aiming for full coverage of versions should test fixtures of all supported versions.
|
||||||
func GetSupportedEmulatedVersions() []string {
|
func GetSupportedEmulatedVersions() []string {
|
||||||
return []string{
|
return []string{
|
||||||
utilversion.DefaultKubeEffectiveVersion().BinaryVersion().SubtractMinor(2).String(),
|
compatibility.DefaultKubeEffectiveVersionForTest().BinaryVersion().SubtractMinor(2).String(),
|
||||||
utilversion.DefaultKubeEffectiveVersion().BinaryVersion().SubtractMinor(1).String(),
|
compatibility.DefaultKubeEffectiveVersionForTest().BinaryVersion().SubtractMinor(1).String(),
|
||||||
utilversion.DefaultKubeEffectiveVersion().BinaryVersion().String(),
|
compatibility.DefaultKubeEffectiveVersionForTest().BinaryVersion().String(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -104,7 +104,6 @@ func testEtcdStoragePathWithVersion(t *testing.T, v string) {
|
|||||||
// only understand v1beta1.
|
// only understand v1beta1.
|
||||||
featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.MultiCIDRServiceAllocator, false)
|
featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, features.MultiCIDRServiceAllocator, false)
|
||||||
}
|
}
|
||||||
registerEffectiveEmulationVersion(t)
|
|
||||||
|
|
||||||
apiServer := StartRealAPIServerOrDie(t, func(opts *options.ServerRunOptions) {
|
apiServer := StartRealAPIServerOrDie(t, func(opts *options.ServerRunOptions) {
|
||||||
// Disable alphas when emulating previous versions.
|
// Disable alphas when emulating previous versions.
|
||||||
|
|||||||
@@ -36,9 +36,9 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||||
"k8s.io/apimachinery/pkg/util/json"
|
"k8s.io/apimachinery/pkg/util/json"
|
||||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
genericapiserveroptions "k8s.io/apiserver/pkg/server/options"
|
genericapiserveroptions "k8s.io/apiserver/pkg/server/options"
|
||||||
|
"k8s.io/apiserver/pkg/util/compatibility"
|
||||||
"k8s.io/apiserver/pkg/util/feature"
|
"k8s.io/apiserver/pkg/util/feature"
|
||||||
cacheddiscovery "k8s.io/client-go/discovery/cached/memory"
|
cacheddiscovery "k8s.io/client-go/discovery/cached/memory"
|
||||||
"k8s.io/client-go/dynamic"
|
"k8s.io/client-go/dynamic"
|
||||||
@@ -46,9 +46,8 @@ import (
|
|||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/restmapper"
|
"k8s.io/client-go/restmapper"
|
||||||
utiltesting "k8s.io/client-go/util/testing"
|
utiltesting "k8s.io/client-go/util/testing"
|
||||||
"k8s.io/component-base/featuregate"
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||||
utilversion "k8s.io/component-base/version"
|
|
||||||
"k8s.io/kubernetes/cmd/kube-apiserver/app"
|
"k8s.io/kubernetes/cmd/kube-apiserver/app"
|
||||||
"k8s.io/kubernetes/cmd/kube-apiserver/app/options"
|
"k8s.io/kubernetes/cmd/kube-apiserver/app/options"
|
||||||
"k8s.io/kubernetes/test/integration"
|
"k8s.io/kubernetes/test/integration"
|
||||||
@@ -67,17 +66,6 @@ AwEHoUQDQgAEH6cuzP8XuD5wal6wf9M6xDljTOPLX2i8uIp/C/ASqiIGUeeKQtX0
|
|||||||
/IR3qCXyThP/dbCiHrF3v1cuhBOHY8CLVg==
|
/IR3qCXyThP/dbCiHrF3v1cuhBOHY8CLVg==
|
||||||
-----END EC PRIVATE KEY-----`
|
-----END EC PRIVATE KEY-----`
|
||||||
|
|
||||||
func registerEffectiveEmulationVersion(t *testing.T) {
|
|
||||||
featureGate := feature.DefaultMutableFeatureGate
|
|
||||||
featureGate.AddMetrics()
|
|
||||||
|
|
||||||
effectiveVersion := utilversion.DefaultKubeEffectiveVersion()
|
|
||||||
effectiveVersion.SetEmulationVersion(featureGate.EmulationVersion())
|
|
||||||
featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, featureGate, effectiveVersion.EmulationVersion())
|
|
||||||
featuregate.DefaultComponentGlobalsRegistry.Reset()
|
|
||||||
utilruntime.Must(featuregate.DefaultComponentGlobalsRegistry.Register(featuregate.DefaultKubeComponent, effectiveVersion, featureGate))
|
|
||||||
}
|
|
||||||
|
|
||||||
// StartRealAPIServerOrDie starts an API server that is appropriate for use in tests that require one of every resource
|
// StartRealAPIServerOrDie starts an API server that is appropriate for use in tests that require one of every resource
|
||||||
func StartRealAPIServerOrDie(t *testing.T, configFuncs ...func(*options.ServerRunOptions)) *APIServer {
|
func StartRealAPIServerOrDie(t *testing.T, configFuncs ...func(*options.ServerRunOptions)) *APIServer {
|
||||||
tCtx := ktesting.Init(t)
|
tCtx := ktesting.Init(t)
|
||||||
@@ -108,6 +96,17 @@ func StartRealAPIServerOrDie(t *testing.T, configFuncs ...func(*options.ServerRu
|
|||||||
}
|
}
|
||||||
|
|
||||||
opts := options.NewServerRunOptions()
|
opts := options.NewServerRunOptions()
|
||||||
|
// If EmulationVersion of DefaultFeatureGate is set during test, we need to propagate it to the apiserver ComponentGlobalsRegistry.
|
||||||
|
featureGate := feature.DefaultMutableFeatureGate.DeepCopy()
|
||||||
|
effectiveVersion := compatibility.DefaultKubeEffectiveVersionForTest()
|
||||||
|
effectiveVersion.SetEmulationVersion(featureGate.EmulationVersion())
|
||||||
|
// set up new instance of ComponentGlobalsRegistry instead of using the DefaultComponentGlobalsRegistry to avoid contention in parallel tests.
|
||||||
|
componentGlobalsRegistry := basecompatibility.NewComponentGlobalsRegistry()
|
||||||
|
if err := componentGlobalsRegistry.Register(basecompatibility.DefaultKubeComponent, effectiveVersion, featureGate); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
opts.GenericServerRunOptions.ComponentGlobalsRegistry = componentGlobalsRegistry
|
||||||
|
|
||||||
opts.Options.SecureServing.Listener = listener
|
opts.Options.SecureServing.Listener = listener
|
||||||
opts.Options.SecureServing.ServerCert.CertDirectory = certDir
|
opts.Options.SecureServing.ServerCert.CertDirectory = certDir
|
||||||
opts.Options.ServiceAccountSigningKeyFile = saSigningKeyFile.Name()
|
opts.Options.ServiceAccountSigningKeyFile = saSigningKeyFile.Name()
|
||||||
@@ -123,6 +122,19 @@ func StartRealAPIServerOrDie(t *testing.T, configFuncs ...func(*options.ServerRu
|
|||||||
for _, f := range configFuncs {
|
for _, f := range configFuncs {
|
||||||
f(opts)
|
f(opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the local ComponentGlobalsRegistry is changed by configFuncs,
|
||||||
|
// we need to copy the new feature values back to the DefaultFeatureGate because most feature checks still use the DefaultFeatureGate.
|
||||||
|
if !featureGate.EmulationVersion().EqualTo(feature.DefaultMutableFeatureGate.EmulationVersion()) {
|
||||||
|
featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, feature.DefaultMutableFeatureGate, effectiveVersion.EmulationVersion())
|
||||||
|
}
|
||||||
|
for f := range feature.DefaultMutableFeatureGate.GetAll() {
|
||||||
|
if featureGate.Enabled(f) != feature.DefaultFeatureGate.Enabled(f) {
|
||||||
|
featuregatetesting.SetFeatureGateDuringTest(t, feature.DefaultFeatureGate, f, featureGate.Enabled(f))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
feature.DefaultMutableFeatureGate.AddMetrics()
|
||||||
|
|
||||||
completedOptions, err := opts.Complete(tCtx)
|
completedOptions, err := opts.Complete(tCtx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|||||||
@@ -55,9 +55,9 @@ import (
|
|||||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||||
"k8s.io/client-go/transport"
|
"k8s.io/client-go/transport"
|
||||||
"k8s.io/client-go/util/cert"
|
"k8s.io/client-go/util/cert"
|
||||||
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
"k8s.io/component-base/featuregate"
|
"k8s.io/component-base/featuregate"
|
||||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||||
utilversion "k8s.io/component-base/version"
|
|
||||||
apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
|
apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"
|
||||||
aggregatorclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset"
|
aggregatorclient "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset"
|
||||||
"k8s.io/kubernetes/cmd/kube-apiserver/app"
|
"k8s.io/kubernetes/cmd/kube-apiserver/app"
|
||||||
@@ -282,11 +282,8 @@ func testFrontProxyConfig(t *testing.T, withUID bool) {
|
|||||||
extraKASFlags = []string{"--requestheader-uid-headers=x-remote-uid"}
|
extraKASFlags = []string{"--requestheader-uid-headers=x-remote-uid"}
|
||||||
}
|
}
|
||||||
|
|
||||||
// each wardle binary is bundled with a specific kube binary.
|
|
||||||
kubeBinaryVersion := sampleserver.WardleVersionToKubeVersion(version.MustParse(wardleBinaryVersion)).String()
|
|
||||||
|
|
||||||
// start up the KAS and prepare the options for the wardle API server
|
// start up the KAS and prepare the options for the wardle API server
|
||||||
testKAS, wardleOptions, wardlePort := prepareAggregatedWardleAPIServer(ctx, t, testNamespace, kubeBinaryVersion, wardleBinaryVersion, extraKASFlags, withUID)
|
testKAS, wardleOptions, wardlePort := prepareAggregatedWardleAPIServer(ctx, t, testNamespace, wardleBinaryVersion, extraKASFlags, withUID)
|
||||||
kubeConfig := getKubeConfig(testKAS)
|
kubeConfig := getKubeConfig(testKAS)
|
||||||
|
|
||||||
// create the SA that we will use to query the aggregated API
|
// create the SA that we will use to query the aggregated API
|
||||||
@@ -402,10 +399,7 @@ func testAggregatedAPIServer(t *testing.T, setWardleFeatureGate, banFlunder bool
|
|||||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
|
||||||
t.Cleanup(cancel)
|
t.Cleanup(cancel)
|
||||||
|
|
||||||
// each wardle binary is bundled with a specific kube binary.
|
testKAS, wardleOptions, wardlePort := prepareAggregatedWardleAPIServer(ctx, t, testNamespace, wardleBinaryVersion, nil, false)
|
||||||
kubeBinaryVersion := sampleserver.WardleVersionToKubeVersion(version.MustParse(wardleBinaryVersion)).String()
|
|
||||||
|
|
||||||
testKAS, wardleOptions, wardlePort := prepareAggregatedWardleAPIServer(ctx, t, testNamespace, kubeBinaryVersion, wardleBinaryVersion, nil, false)
|
|
||||||
kubeClientConfig := getKubeConfig(testKAS)
|
kubeClientConfig := getKubeConfig(testKAS)
|
||||||
|
|
||||||
wardleCertDir, _ := os.MkdirTemp("", "test-integration-wardle-server")
|
wardleCertDir, _ := os.MkdirTemp("", "test-integration-wardle-server")
|
||||||
@@ -685,7 +679,7 @@ func TestAggregatedAPIServerRejectRedirectResponse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareAggregatedWardleAPIServer(ctx context.Context, t *testing.T, namespace, kubebinaryVersion, wardleBinaryVersion string, kubeAPIServerFlags []string, withUID bool) (*kastesting.TestServer, *sampleserver.WardleServerOptions, int) {
|
func prepareAggregatedWardleAPIServer(ctx context.Context, t *testing.T, namespace, wardleBinaryVersion string, kubeAPIServerFlags []string, withUID bool) (*kastesting.TestServer, *sampleserver.WardleServerOptions, int) {
|
||||||
// makes the kube-apiserver very responsive. it's normally a minute
|
// makes the kube-apiserver very responsive. it's normally a minute
|
||||||
dynamiccertificates.FileRefreshDuration = 1 * time.Second
|
dynamiccertificates.FileRefreshDuration = 1 * time.Second
|
||||||
|
|
||||||
@@ -697,22 +691,17 @@ func prepareAggregatedWardleAPIServer(ctx context.Context, t *testing.T, namespa
|
|||||||
// endpoints cannot have loopback IPs so we need to override the resolver itself
|
// endpoints cannot have loopback IPs so we need to override the resolver itself
|
||||||
t.Cleanup(app.SetServiceResolverForTests(staticURLServiceResolver(fmt.Sprintf("https://127.0.0.1:%d", wardlePort))))
|
t.Cleanup(app.SetServiceResolverForTests(staticURLServiceResolver(fmt.Sprintf("https://127.0.0.1:%d", wardlePort))))
|
||||||
|
|
||||||
// TODO figure out how to actually make BinaryVersion/EmulationVersion work with Wardle and KAS at the same time when Alpha FG are being set
|
|
||||||
if withUID {
|
|
||||||
kubebinaryVersion = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
testServer := kastesting.StartTestServerOrDie(t,
|
testServer := kastesting.StartTestServerOrDie(t,
|
||||||
&kastesting.TestServerInstanceOptions{
|
&kastesting.TestServerInstanceOptions{
|
||||||
EnableCertAuth: true,
|
EnableCertAuth: true,
|
||||||
BinaryVersion: kubebinaryVersion,
|
|
||||||
},
|
},
|
||||||
kubeAPIServerFlags,
|
kubeAPIServerFlags,
|
||||||
framework.SharedEtcd())
|
framework.SharedEtcd())
|
||||||
t.Cleanup(func() { testServer.TearDownFn() })
|
t.Cleanup(func() { testServer.TearDownFn() })
|
||||||
|
|
||||||
_, _ = featuregate.DefaultComponentGlobalsRegistry.ComponentGlobalsOrRegister(
|
componentGlobalsRegistry := testServer.ServerOpts.Options.GenericServerRunOptions.ComponentGlobalsRegistry
|
||||||
apiserver.WardleComponentName, utilversion.NewEffectiveVersion(wardleBinaryVersion),
|
_, _ = componentGlobalsRegistry.ComponentGlobalsOrRegister(
|
||||||
|
apiserver.WardleComponentName, basecompatibility.NewEffectiveVersionFromString(wardleBinaryVersion, "", ""),
|
||||||
featuregate.NewVersionedFeatureGate(version.MustParse(wardleBinaryVersion)))
|
featuregate.NewVersionedFeatureGate(version.MustParse(wardleBinaryVersion)))
|
||||||
|
|
||||||
kubeClient := client.NewForConfigOrDie(getKubeConfig(testServer))
|
kubeClient := client.NewForConfigOrDie(getKubeConfig(testServer))
|
||||||
@@ -740,6 +729,7 @@ func prepareAggregatedWardleAPIServer(ctx context.Context, t *testing.T, namespa
|
|||||||
}
|
}
|
||||||
|
|
||||||
wardleOptions := sampleserver.NewWardleServerOptions(os.Stdout, os.Stderr)
|
wardleOptions := sampleserver.NewWardleServerOptions(os.Stdout, os.Stderr)
|
||||||
|
wardleOptions.ComponentGlobalsRegistry = componentGlobalsRegistry
|
||||||
// ensure this is a SAN on the generated cert for service FQDN
|
// ensure this is a SAN on the generated cert for service FQDN
|
||||||
wardleOptions.AlternateDNS = []string{
|
wardleOptions.AlternateDNS = []string{
|
||||||
fmt.Sprintf("api.%s.svc", namespace),
|
fmt.Sprintf("api.%s.svc", namespace),
|
||||||
|
|||||||
@@ -35,9 +35,13 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||||
genericapiserveroptions "k8s.io/apiserver/pkg/server/options"
|
genericapiserveroptions "k8s.io/apiserver/pkg/server/options"
|
||||||
|
"k8s.io/apiserver/pkg/util/compatibility"
|
||||||
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
client "k8s.io/client-go/kubernetes"
|
client "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/rest"
|
"k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/util/cert"
|
"k8s.io/client-go/util/cert"
|
||||||
|
basecompatibility "k8s.io/component-base/compatibility"
|
||||||
|
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||||
aggregatorscheme "k8s.io/kube-aggregator/pkg/apiserver/scheme"
|
aggregatorscheme "k8s.io/kube-aggregator/pkg/apiserver/scheme"
|
||||||
netutils "k8s.io/utils/net"
|
netutils "k8s.io/utils/net"
|
||||||
|
|
||||||
@@ -136,6 +140,17 @@ func StartTestServer(ctx context.Context, t testing.TB, setup TestServerSetup) (
|
|||||||
}
|
}
|
||||||
|
|
||||||
opts := options.NewServerRunOptions()
|
opts := options.NewServerRunOptions()
|
||||||
|
// If EmulationVersion of DefaultFeatureGate is set during test, we need to propagate it to the apiserver ComponentGlobalsRegistry.
|
||||||
|
featureGate := utilfeature.DefaultMutableFeatureGate.DeepCopy()
|
||||||
|
effectiveVersion := compatibility.DefaultKubeEffectiveVersionForTest()
|
||||||
|
effectiveVersion.SetEmulationVersion(featureGate.EmulationVersion())
|
||||||
|
// set up new instance of ComponentGlobalsRegistry instead of using the DefaultComponentGlobalsRegistry to avoid contention in parallel tests.
|
||||||
|
componentGlobalsRegistry := basecompatibility.NewComponentGlobalsRegistry()
|
||||||
|
if err := componentGlobalsRegistry.Register(basecompatibility.DefaultKubeComponent, effectiveVersion, featureGate); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
opts.GenericServerRunOptions.ComponentGlobalsRegistry = componentGlobalsRegistry
|
||||||
|
|
||||||
opts.SecureServing.Listener = listener
|
opts.SecureServing.Listener = listener
|
||||||
opts.SecureServing.BindAddress = netutils.ParseIPSloppy("127.0.0.1")
|
opts.SecureServing.BindAddress = netutils.ParseIPSloppy("127.0.0.1")
|
||||||
opts.SecureServing.ServerCert.CertDirectory = certDir
|
opts.SecureServing.ServerCert.CertDirectory = certDir
|
||||||
@@ -158,6 +173,18 @@ func StartTestServer(ctx context.Context, t testing.TB, setup TestServerSetup) (
|
|||||||
setup.ModifyServerRunOptions(opts)
|
setup.ModifyServerRunOptions(opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If the local ComponentGlobalsRegistry is changed by ModifyServerRunOptions,
|
||||||
|
// we need to copy the new feature values back to the DefaultFeatureGate because most feature checks still use the DefaultFeatureGate.
|
||||||
|
if !featureGate.EmulationVersion().EqualTo(utilfeature.DefaultMutableFeatureGate.EmulationVersion()) {
|
||||||
|
featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultMutableFeatureGate, effectiveVersion.EmulationVersion())
|
||||||
|
}
|
||||||
|
for f := range utilfeature.DefaultMutableFeatureGate.GetAll() {
|
||||||
|
if featureGate.Enabled(f) != utilfeature.DefaultFeatureGate.Enabled(f) {
|
||||||
|
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, f, featureGate.Enabled(f))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
utilfeature.DefaultMutableFeatureGate.AddMetrics()
|
||||||
|
|
||||||
completedOptions, err := opts.Complete(ctx)
|
completedOptions, err := opts.Complete(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
|||||||
@@ -1230,9 +1230,8 @@ func TestMutablePodSchedulingDirectives(t *testing.T) {
|
|||||||
// Test disabling of RelaxedDNSSearchValidation after a Pod has been created
|
// Test disabling of RelaxedDNSSearchValidation after a Pod has been created
|
||||||
func TestRelaxedDNSSearchValidation(t *testing.T) {
|
func TestRelaxedDNSSearchValidation(t *testing.T) {
|
||||||
// Disable ServiceAccount admission plugin as we don't have serviceaccount controller running.
|
// Disable ServiceAccount admission plugin as we don't have serviceaccount controller running.
|
||||||
server := kubeapiservertesting.StartTestServerOrDie(t,
|
server := kubeapiservertesting.StartTestServerOrDie(t, nil,
|
||||||
&kubeapiservertesting.TestServerInstanceOptions{BinaryVersion: "1.32"},
|
append(framework.DefaultTestServerFlags(), "--emulated-version=1.32"), framework.SharedEtcd())
|
||||||
framework.DefaultTestServerFlags(), framework.SharedEtcd())
|
|
||||||
defer server.TearDownFn()
|
defer server.TearDownFn()
|
||||||
|
|
||||||
client := clientset.NewForConfigOrDie(server.ClientConfig)
|
client := clientset.NewForConfigOrDie(server.ClientConfig)
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ package service
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"k8s.io/apimachinery/pkg/util/version"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -34,10 +34,8 @@ import (
|
|||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
servicecontroller "k8s.io/cloud-provider/controllers/service"
|
servicecontroller "k8s.io/cloud-provider/controllers/service"
|
||||||
fakecloud "k8s.io/cloud-provider/fake"
|
fakecloud "k8s.io/cloud-provider/fake"
|
||||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
|
||||||
controllersmetrics "k8s.io/component-base/metrics/prometheus/controllers"
|
controllersmetrics "k8s.io/component-base/metrics/prometheus/controllers"
|
||||||
kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing"
|
kubeapiservertesting "k8s.io/kubernetes/cmd/kube-apiserver/app/testing"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
|
||||||
"k8s.io/kubernetes/test/integration/framework"
|
"k8s.io/kubernetes/test/integration/framework"
|
||||||
"k8s.io/utils/net"
|
"k8s.io/utils/net"
|
||||||
utilpointer "k8s.io/utils/pointer"
|
utilpointer "k8s.io/utils/pointer"
|
||||||
@@ -708,13 +706,12 @@ func Test_ServiceLoadBalancerIPMode(t *testing.T) {
|
|||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run("", func(t *testing.T) {
|
t.Run("", func(t *testing.T) {
|
||||||
var testServerOptions *kubeapiservertesting.TestServerInstanceOptions
|
serverFlags := framework.DefaultTestServerFlags()
|
||||||
if !tc.ipModeEnabled {
|
if !tc.ipModeEnabled {
|
||||||
testServerOptions = &kubeapiservertesting.TestServerInstanceOptions{EmulationVersion: "1.31"}
|
serverFlags = append(serverFlags, "--emulated-version=1.31")
|
||||||
featuregatetesting.SetFeatureGateEmulationVersionDuringTest(t, utilfeature.DefaultFeatureGate, version.MustParse("1.31"))
|
|
||||||
}
|
}
|
||||||
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.LoadBalancerIPMode, tc.ipModeEnabled)
|
serverFlags = append(serverFlags, fmt.Sprintf("--feature-gates=LoadBalancerIPMode=%v", tc.ipModeEnabled))
|
||||||
server := kubeapiservertesting.StartTestServerOrDie(t, testServerOptions, framework.DefaultTestServerFlags(), framework.SharedEtcd())
|
server := kubeapiservertesting.StartTestServerOrDie(t, nil, serverFlags, framework.SharedEtcd())
|
||||||
defer server.TearDownFn()
|
defer server.TearDownFn()
|
||||||
|
|
||||||
client, err := clientset.NewForConfig(server.ClientConfig)
|
client, err := clientset.NewForConfig(server.ClientConfig)
|
||||||
|
|||||||
Reference in New Issue
Block a user