mirror of https://github.com/k3s-io/k3s
Merge pull request #72382 from liggitt/volumescheduling-ga
Stop checking VolumeScheduling feature gatepull/564/head
commit
66bf481114
|
@ -14,7 +14,6 @@ go_library(
|
|||
"//cmd/kube-scheduler/app/options:go_default_library",
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/controller:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/scheduler:go_default_library",
|
||||
"//pkg/scheduler/algorithmprovider:go_default_library",
|
||||
"//pkg/scheduler/api:go_default_library",
|
||||
|
@ -38,10 +37,8 @@ go_library(
|
|||
"//staging/src/k8s.io/apiserver/pkg/server/healthz:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/server/mux:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/server/routes:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/flag:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/globalflag:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers/storage/v1:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/tools/leaderelection:go_default_library",
|
||||
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
|
||||
|
|
|
@ -38,17 +38,14 @@ import (
|
|||
"k8s.io/apiserver/pkg/server/healthz"
|
||||
"k8s.io/apiserver/pkg/server/mux"
|
||||
"k8s.io/apiserver/pkg/server/routes"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
apiserverflag "k8s.io/apiserver/pkg/util/flag"
|
||||
"k8s.io/apiserver/pkg/util/globalflag"
|
||||
storageinformers "k8s.io/client-go/informers/storage/v1"
|
||||
v1core "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||
"k8s.io/client-go/tools/leaderelection"
|
||||
schedulerserverconfig "k8s.io/kubernetes/cmd/kube-scheduler/app/config"
|
||||
"k8s.io/kubernetes/cmd/kube-scheduler/app/options"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/controller"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/scheduler"
|
||||
"k8s.io/kubernetes/pkg/scheduler/algorithmprovider"
|
||||
schedulerapi "k8s.io/kubernetes/pkg/scheduler/api"
|
||||
|
@ -165,11 +162,6 @@ func runCommand(cmd *cobra.Command, args []string, opts *options.Options) error
|
|||
|
||||
// Run executes the scheduler based on the given configuration. It only return on error or when stopCh is closed.
|
||||
func Run(cc schedulerserverconfig.CompletedConfig, stopCh <-chan struct{}) error {
|
||||
var storageClassInformer storageinformers.StorageClassInformer
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||
storageClassInformer = cc.InformerFactory.Storage().V1().StorageClasses()
|
||||
}
|
||||
|
||||
// Create the scheduler.
|
||||
sched, err := scheduler.New(cc.Client,
|
||||
cc.InformerFactory.Core().V1().Nodes(),
|
||||
|
@ -181,7 +173,7 @@ func Run(cc schedulerserverconfig.CompletedConfig, stopCh <-chan struct{}) error
|
|||
cc.InformerFactory.Apps().V1().StatefulSets(),
|
||||
cc.InformerFactory.Core().V1().Services(),
|
||||
cc.InformerFactory.Policy().V1beta1().PodDisruptionBudgets(),
|
||||
storageClassInformer,
|
||||
cc.InformerFactory.Storage().V1().StorageClasses(),
|
||||
cc.Recorder,
|
||||
cc.ComponentConfig.AlgorithmSource,
|
||||
stopCh,
|
||||
|
@ -335,11 +327,6 @@ func newHealthzHandler(config *kubeschedulerconfig.KubeSchedulerConfiguration, s
|
|||
|
||||
// NewSchedulerConfig creates the scheduler configuration. This is exposed for use by tests.
|
||||
func NewSchedulerConfig(s schedulerserverconfig.CompletedConfig) (*factory.Config, error) {
|
||||
var storageClassInformer storageinformers.StorageClassInformer
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||
storageClassInformer = s.InformerFactory.Storage().V1().StorageClasses()
|
||||
}
|
||||
|
||||
// Set up the configurator which can create schedulers from configs.
|
||||
configurator := factory.NewConfigFactory(&factory.ConfigFactoryArgs{
|
||||
SchedulerName: s.ComponentConfig.SchedulerName,
|
||||
|
@ -353,7 +340,7 @@ func NewSchedulerConfig(s schedulerserverconfig.CompletedConfig) (*factory.Confi
|
|||
StatefulSetInformer: s.InformerFactory.Apps().V1().StatefulSets(),
|
||||
ServiceInformer: s.InformerFactory.Core().V1().Services(),
|
||||
PdbInformer: s.InformerFactory.Policy().V1beta1().PodDisruptionBudgets(),
|
||||
StorageClassInformer: storageClassInformer,
|
||||
StorageClassInformer: s.InformerFactory.Storage().V1().StorageClasses(),
|
||||
HardPodAffinitySymmetricWeight: s.ComponentConfig.HardPodAffinitySymmetricWeight,
|
||||
DisablePreemption: s.ComponentConfig.DisablePreemption,
|
||||
PercentageOfNodesToScore: s.ComponentConfig.PercentageOfNodesToScore,
|
||||
|
|
|
@ -1777,11 +1777,9 @@ func ValidatePersistentVolumeUpdate(newPv, oldPv *core.PersistentVolume) field.E
|
|||
|
||||
allErrs = append(allErrs, ValidateImmutableField(newPv.Spec.VolumeMode, oldPv.Spec.VolumeMode, field.NewPath("volumeMode"))...)
|
||||
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||
// Allow setting NodeAffinity if oldPv NodeAffinity was not set
|
||||
if oldPv.Spec.NodeAffinity != nil {
|
||||
allErrs = append(allErrs, ValidateImmutableField(newPv.Spec.NodeAffinity, oldPv.Spec.NodeAffinity, field.NewPath("nodeAffinity"))...)
|
||||
}
|
||||
// Allow setting NodeAffinity if oldPv NodeAffinity was not set
|
||||
if oldPv.Spec.NodeAffinity != nil {
|
||||
allErrs = append(allErrs, ValidateImmutableField(newPv.Spec.NodeAffinity, oldPv.Spec.NodeAffinity, field.NewPath("nodeAffinity"))...)
|
||||
}
|
||||
|
||||
return allErrs
|
||||
|
@ -3160,22 +3158,17 @@ func ValidateTopologySelectorTerm(term core.TopologySelectorTerm, fldPath *field
|
|||
exprMap := make(map[string]sets.String)
|
||||
exprPath := fldPath.Child("matchLabelExpressions")
|
||||
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||
// Allow empty MatchLabelExpressions, in case this field becomes optional in the future.
|
||||
// Allow empty MatchLabelExpressions, in case this field becomes optional in the future.
|
||||
for i, req := range term.MatchLabelExpressions {
|
||||
idxPath := exprPath.Index(i)
|
||||
valueSet, exprErrs := validateTopologySelectorLabelRequirement(req, idxPath)
|
||||
allErrs = append(allErrs, exprErrs...)
|
||||
|
||||
for i, req := range term.MatchLabelExpressions {
|
||||
idxPath := exprPath.Index(i)
|
||||
valueSet, exprErrs := validateTopologySelectorLabelRequirement(req, idxPath)
|
||||
allErrs = append(allErrs, exprErrs...)
|
||||
|
||||
// Validate no duplicate keys exist.
|
||||
if _, exists := exprMap[req.Key]; exists {
|
||||
allErrs = append(allErrs, field.Duplicate(idxPath.Child("key"), req.Key))
|
||||
}
|
||||
exprMap[req.Key] = valueSet
|
||||
// Validate no duplicate keys exist.
|
||||
if _, exists := exprMap[req.Key]; exists {
|
||||
allErrs = append(allErrs, field.Duplicate(idxPath.Child("key"), req.Key))
|
||||
}
|
||||
} else if len(term.MatchLabelExpressions) != 0 {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath, "field is disabled by feature-gate VolumeScheduling"))
|
||||
exprMap[req.Key] = valueSet
|
||||
}
|
||||
|
||||
return exprMap, allErrs
|
||||
|
@ -5319,10 +5312,6 @@ func validateVolumeNodeAffinity(nodeAffinity *core.VolumeNodeAffinity, fldPath *
|
|||
return false, allErrs
|
||||
}
|
||||
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath, "Volume node affinity is disabled by feature-gate"))
|
||||
}
|
||||
|
||||
if nodeAffinity.Required != nil {
|
||||
allErrs = append(allErrs, ValidateNodeSelector(nodeAffinity.Required, fldPath.Child("required"))...)
|
||||
} else {
|
||||
|
|
|
@ -577,19 +577,6 @@ func TestValidateLocalVolumesDisabled(t *testing.T) {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
for name, scenario := range scenarios {
|
||||
t.Run(name+" VolumeScheduling disabled", func(t *testing.T) {
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, false)()
|
||||
errs := ValidatePersistentVolume(scenario.volume)
|
||||
if len(errs) == 0 && scenario.isExpectedFailure {
|
||||
t.Errorf("Unexpected success for scenario: %s", name)
|
||||
}
|
||||
if len(errs) > 0 && !scenario.isExpectedFailure {
|
||||
t.Errorf("Unexpected failure for scenario: %s - %+v", name, errs)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testVolumeWithNodeAffinity(affinity *core.VolumeNodeAffinity) *core.PersistentVolume {
|
||||
|
|
|
@ -39,7 +39,6 @@ go_test(
|
|||
srcs = ["util_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/storage:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
|
||||
|
|
|
@ -24,14 +24,6 @@ import (
|
|||
|
||||
// DropDisabledFields removes disabled fields from the StorageClass object.
|
||||
func DropDisabledFields(class, oldClass *storage.StorageClass) {
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||
class.VolumeBindingMode = nil
|
||||
class.AllowedTopologies = nil
|
||||
if oldClass != nil {
|
||||
oldClass.VolumeBindingMode = nil
|
||||
oldClass.AllowedTopologies = nil
|
||||
}
|
||||
}
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.ExpandPersistentVolumes) && !allowVolumeExpansionInUse(oldClass) {
|
||||
class.AllowVolumeExpansion = nil
|
||||
}
|
||||
|
|
|
@ -24,53 +24,10 @@ import (
|
|||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
func TestDropAlphaFields(t *testing.T) {
|
||||
bindingMode := storage.VolumeBindingWaitForFirstConsumer
|
||||
allowedTopologies := []api.TopologySelectorTerm{
|
||||
{
|
||||
MatchLabelExpressions: []api.TopologySelectorLabelRequirement{
|
||||
{
|
||||
Key: "kubernetes.io/hostname",
|
||||
Values: []string{"node1"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Test that field gets dropped when feature gate is not set
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, false)()
|
||||
class := &storage.StorageClass{
|
||||
VolumeBindingMode: &bindingMode,
|
||||
AllowedTopologies: allowedTopologies,
|
||||
}
|
||||
DropDisabledFields(class, nil)
|
||||
if class.VolumeBindingMode != nil {
|
||||
t.Errorf("VolumeBindingMode field didn't get dropped: %+v", class.VolumeBindingMode)
|
||||
}
|
||||
if class.AllowedTopologies != nil {
|
||||
t.Errorf("AllowedTopologies field didn't get dropped: %+v", class.AllowedTopologies)
|
||||
}
|
||||
|
||||
// Test that field does not get dropped when feature gate is set
|
||||
class = &storage.StorageClass{
|
||||
VolumeBindingMode: &bindingMode,
|
||||
AllowedTopologies: allowedTopologies,
|
||||
}
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)()
|
||||
DropDisabledFields(class, nil)
|
||||
if class.VolumeBindingMode != &bindingMode {
|
||||
t.Errorf("VolumeBindingMode field got unexpectantly modified: %+v", class.VolumeBindingMode)
|
||||
}
|
||||
if !reflect.DeepEqual(class.AllowedTopologies, allowedTopologies) {
|
||||
t.Errorf("AllowedTopologies field got unexpectantly modified: %+v", class.AllowedTopologies)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDropAllowVolumeExpansion(t *testing.T) {
|
||||
allowVolumeExpansion := false
|
||||
scWithoutAllowVolumeExpansion := func() *storage.StorageClass {
|
||||
|
|
|
@ -19,13 +19,11 @@ go_library(
|
|||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/storage:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/api/storage/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/conversion:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -52,10 +50,7 @@ go_test(
|
|||
deps = [
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/apis/storage/install:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//staging/src/k8s.io/api/storage/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library",
|
||||
],
|
||||
)
|
||||
|
|
|
@ -20,8 +20,6 @@ import (
|
|||
"k8s.io/api/core/v1"
|
||||
storagev1 "k8s.io/api/storage/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
func addDefaultingFuncs(scheme *runtime.Scheme) error {
|
||||
|
@ -34,7 +32,7 @@ func SetDefaults_StorageClass(obj *storagev1.StorageClass) {
|
|||
*obj.ReclaimPolicy = v1.PersistentVolumeReclaimDelete
|
||||
}
|
||||
|
||||
if obj.VolumeBindingMode == nil && utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||
if obj.VolumeBindingMode == nil {
|
||||
obj.VolumeBindingMode = new(storagev1.VolumeBindingMode)
|
||||
*obj.VolumeBindingMode = storagev1.VolumeBindingImmediate
|
||||
}
|
||||
|
|
|
@ -22,11 +22,8 @@ import (
|
|||
|
||||
storagev1 "k8s.io/api/storage/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
_ "k8s.io/kubernetes/pkg/apis/storage/install"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
func roundTrip(t *testing.T, obj runtime.Object) runtime.Object {
|
||||
|
@ -53,7 +50,7 @@ func roundTrip(t *testing.T, obj runtime.Object) runtime.Object {
|
|||
func TestSetDefaultVolumeBindingMode(t *testing.T) {
|
||||
class := &storagev1.StorageClass{}
|
||||
|
||||
// When feature gate is enabled, field should be defaulted
|
||||
// field should be defaulted
|
||||
defaultMode := storagev1.VolumeBindingImmediate
|
||||
output := roundTrip(t, runtime.Object(class)).(*storagev1.StorageClass)
|
||||
outMode := output.VolumeBindingMode
|
||||
|
@ -62,13 +59,4 @@ func TestSetDefaultVolumeBindingMode(t *testing.T) {
|
|||
} else if *outMode != defaultMode {
|
||||
t.Errorf("Expected VolumeBindingMode to be defaulted to: %+v, got: %+v", defaultMode, outMode)
|
||||
}
|
||||
|
||||
class = &storagev1.StorageClass{}
|
||||
|
||||
// When feature gate is disabled, field should not be defaulted
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, false)()
|
||||
output = roundTrip(t, runtime.Object(class)).(*storagev1.StorageClass)
|
||||
if output.VolumeBindingMode != nil {
|
||||
t.Errorf("Expected VolumeBindingMode to not be defaulted, got: %+v", output.VolumeBindingMode)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,13 +19,11 @@ go_library(
|
|||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/storage:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/api/storage/v1beta1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/conversion:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -52,10 +50,7 @@ go_test(
|
|||
deps = [
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/apis/storage/install:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//staging/src/k8s.io/api/storage/v1beta1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library",
|
||||
],
|
||||
)
|
||||
|
|
|
@ -20,8 +20,6 @@ import (
|
|||
"k8s.io/api/core/v1"
|
||||
storagev1beta1 "k8s.io/api/storage/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
func addDefaultingFuncs(scheme *runtime.Scheme) error {
|
||||
|
@ -34,7 +32,7 @@ func SetDefaults_StorageClass(obj *storagev1beta1.StorageClass) {
|
|||
*obj.ReclaimPolicy = v1.PersistentVolumeReclaimDelete
|
||||
}
|
||||
|
||||
if obj.VolumeBindingMode == nil && utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||
if obj.VolumeBindingMode == nil {
|
||||
obj.VolumeBindingMode = new(storagev1beta1.VolumeBindingMode)
|
||||
*obj.VolumeBindingMode = storagev1beta1.VolumeBindingImmediate
|
||||
}
|
||||
|
|
|
@ -22,11 +22,8 @@ import (
|
|||
|
||||
storagev1beta1 "k8s.io/api/storage/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
_ "k8s.io/kubernetes/pkg/apis/storage/install"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
func roundTrip(t *testing.T, obj runtime.Object) runtime.Object {
|
||||
|
@ -53,7 +50,7 @@ func roundTrip(t *testing.T, obj runtime.Object) runtime.Object {
|
|||
func TestSetDefaultVolumeBindingMode(t *testing.T) {
|
||||
class := &storagev1beta1.StorageClass{}
|
||||
|
||||
// When feature gate is enabled, field should be defaulted
|
||||
// field should be defaulted
|
||||
defaultMode := storagev1beta1.VolumeBindingImmediate
|
||||
output := roundTrip(t, runtime.Object(class)).(*storagev1beta1.StorageClass)
|
||||
outMode := output.VolumeBindingMode
|
||||
|
@ -62,14 +59,4 @@ func TestSetDefaultVolumeBindingMode(t *testing.T) {
|
|||
} else if *outMode != defaultMode {
|
||||
t.Errorf("Expected VolumeBindingMode to be defaulted to: %+v, got: %+v", defaultMode, outMode)
|
||||
}
|
||||
|
||||
class = &storagev1beta1.StorageClass{}
|
||||
|
||||
// When feature gate is disabled, field should not be defaulted
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, false)()
|
||||
output = roundTrip(t, runtime.Object(class)).(*storagev1beta1.StorageClass)
|
||||
if output.VolumeBindingMode != nil {
|
||||
t.Errorf("Expected VolumeBindingMode to not be defaulted, got: %+v", output.VolumeBindingMode)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -15,12 +15,10 @@ go_library(
|
|||
"//pkg/apis/core/helper:go_default_library",
|
||||
"//pkg/apis/core/validation:go_default_library",
|
||||
"//pkg/apis/storage:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/validation:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -31,10 +29,7 @@ go_test(
|
|||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/apis/storage:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
@ -24,12 +24,10 @@ import (
|
|||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/validation"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/apis/core/helper"
|
||||
apivalidation "k8s.io/kubernetes/pkg/apis/core/validation"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -233,14 +231,10 @@ var supportedVolumeBindingModes = sets.NewString(string(storage.VolumeBindingImm
|
|||
// validateVolumeBindingMode tests that VolumeBindingMode specifies valid values.
|
||||
func validateVolumeBindingMode(mode *storage.VolumeBindingMode, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||
if mode == nil {
|
||||
allErrs = append(allErrs, field.Required(fldPath, ""))
|
||||
} else if !supportedVolumeBindingModes.Has(string(*mode)) {
|
||||
allErrs = append(allErrs, field.NotSupported(fldPath, mode, supportedVolumeBindingModes.List()))
|
||||
}
|
||||
} else if mode != nil {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath, "field is disabled by feature-gate VolumeScheduling"))
|
||||
if mode == nil {
|
||||
allErrs = append(allErrs, field.Required(fldPath, ""))
|
||||
} else if !supportedVolumeBindingModes.Has(string(*mode)) {
|
||||
allErrs = append(allErrs, field.NotSupported(fldPath, mode, supportedVolumeBindingModes.List()))
|
||||
}
|
||||
|
||||
return allErrs
|
||||
|
@ -254,10 +248,6 @@ func validateAllowedTopologies(topologies []api.TopologySelectorTerm, fldPath *f
|
|||
return allErrs
|
||||
}
|
||||
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath, "field is disabled by feature-gate VolumeScheduling"))
|
||||
}
|
||||
|
||||
rawTopologies := make([]map[string]sets.String, len(topologies))
|
||||
for i, term := range topologies {
|
||||
idxPath := fldPath.Index(i)
|
||||
|
|
|
@ -22,11 +22,8 @@ import (
|
|||
"testing"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -480,22 +477,6 @@ func makeClass(mode *storage.VolumeBindingMode, topologies []api.TopologySelecto
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Remove these tests once feature gate is not required
|
||||
func TestValidateVolumeBindingModeAlphaDisabled(t *testing.T) {
|
||||
errorCases := map[string]*storage.StorageClass{
|
||||
"immediate mode": makeClass(&immediateMode1, nil),
|
||||
"waiting mode": makeClass(&waitingMode, nil),
|
||||
"invalid mode": makeClass(&invalidMode, nil),
|
||||
}
|
||||
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, false)()
|
||||
for testName, storageClass := range errorCases {
|
||||
if errs := ValidateStorageClass(storageClass); len(errs) == 0 {
|
||||
t.Errorf("Expected failure for test: %v", testName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type bindingTest struct {
|
||||
class *storage.StorageClass
|
||||
shouldSucceed bool
|
||||
|
@ -521,8 +502,6 @@ func TestValidateVolumeBindingMode(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
// TODO: remove when feature gate not required
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)()
|
||||
for testName, testCase := range cases {
|
||||
errs := ValidateStorageClass(testCase.class)
|
||||
if testCase.shouldSucceed && len(errs) != 0 {
|
||||
|
@ -579,8 +558,6 @@ func TestValidateUpdateVolumeBindingMode(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
// TODO: remove when feature gate not required
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)()
|
||||
for testName, testCase := range cases {
|
||||
errs := ValidateStorageClassUpdate(testCase.newClass, testCase.oldClass)
|
||||
if testCase.shouldSucceed && len(errs) != 0 {
|
||||
|
@ -883,7 +860,6 @@ func TestValidateAllowedTopologies(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)()
|
||||
for testName, testCase := range cases {
|
||||
errs := ValidateStorageClass(testCase.class)
|
||||
if testCase.shouldSucceed && len(errs) != 0 {
|
||||
|
@ -893,12 +869,4 @@ func TestValidateAllowedTopologies(t *testing.T) {
|
|||
t.Errorf("Expected failure for test %q, got success", testName)
|
||||
}
|
||||
}
|
||||
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, false)()
|
||||
for testName, testCase := range cases {
|
||||
errs := ValidateStorageClass(testCase.class)
|
||||
if len(errs) == 0 && testCase.class.AllowedTopologies != nil {
|
||||
t.Errorf("Expected failure for test %q, got success", testName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ go_library(
|
|||
"//pkg/api/v1/node:go_default_library",
|
||||
"//pkg/apis/core/v1/helper:go_default_library",
|
||||
"//pkg/controller:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/kubelet/apis:go_default_library",
|
||||
"//pkg/scheduler/api:go_default_library",
|
||||
"//pkg/util/node:go_default_library",
|
||||
|
@ -33,7 +32,6 @@ go_library(
|
|||
"//staging/src/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes/scheme:go_default_library",
|
||||
|
@ -60,7 +58,6 @@ go_test(
|
|||
"//pkg/cloudprovider/providers/fake:go_default_library",
|
||||
"//pkg/controller:go_default_library",
|
||||
"//pkg/controller/testutil:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/kubelet/apis:go_default_library",
|
||||
"//pkg/scheduler/api:go_default_library",
|
||||
"//pkg/volume/util:go_default_library",
|
||||
|
@ -69,8 +66,6 @@ go_test(
|
|||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
||||
|
|
|
@ -33,7 +33,6 @@ import (
|
|||
"k8s.io/apimachinery/pkg/util/strategicpatch"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
corelisters "k8s.io/client-go/listers/core/v1"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
|
@ -41,7 +40,6 @@ import (
|
|||
cloudprovider "k8s.io/cloud-provider"
|
||||
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
||||
"k8s.io/kubernetes/pkg/controller"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
|
||||
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
||||
)
|
||||
|
@ -204,7 +202,7 @@ func (pvlc *PersistentVolumeLabelController) addLabelsAndAffinityToVolume(vol *v
|
|||
func (pvlc *PersistentVolumeLabelController) createPatch(vol *v1.PersistentVolume, volLabels map[string]string) ([]byte, error) {
|
||||
volName := vol.Name
|
||||
newVolume := vol.DeepCopyObject().(*v1.PersistentVolume)
|
||||
populateAffinity := utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) && len(volLabels) != 0
|
||||
populateAffinity := len(volLabels) != 0
|
||||
|
||||
if newVolume.Labels == nil {
|
||||
newVolume.Labels = make(map[string]string)
|
||||
|
|
|
@ -27,11 +27,8 @@ import (
|
|||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
sets "k8s.io/apimachinery/pkg/util/sets"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
core "k8s.io/client-go/testing"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
|
||||
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
||||
|
||||
|
@ -451,7 +448,6 @@ func TestCreatePatch(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)()
|
||||
for d, tc := range testCases {
|
||||
cloud := &fakecloud.FakeCloud{}
|
||||
client := fake.NewSimpleClientset()
|
||||
|
@ -520,8 +516,6 @@ func TestAddLabelsToVolume(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)()
|
||||
|
||||
for d, tc := range testCases {
|
||||
labeledCh := make(chan bool, 1)
|
||||
client := fake.NewSimpleClientset()
|
||||
|
|
|
@ -286,10 +286,6 @@ func checkVolumeSatisfyClaim(volume *v1.PersistentVolume, claim *v1.PersistentVo
|
|||
}
|
||||
|
||||
func (ctrl *PersistentVolumeController) shouldDelayBinding(claim *v1.PersistentVolumeClaim) (bool, error) {
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// When feature VolumeScheduling enabled,
|
||||
// Scheduler signal to the PV controller to start dynamic
|
||||
// provisioning by setting the "annSelectedNode" annotation
|
||||
|
|
|
@ -24,15 +24,12 @@ import (
|
|||
storagev1 "k8s.io/api/storage/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
|
||||
"k8s.io/client-go/informers"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
core "k8s.io/client-go/testing"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/klog"
|
||||
"k8s.io/kubernetes/pkg/controller"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -336,24 +333,3 @@ func TestDelayBinding(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDelayBindingDisabled(t *testing.T) {
|
||||
// When volumeScheduling feature gate is disabled, should always be immediate
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, false)()
|
||||
|
||||
client := &fake.Clientset{}
|
||||
informerFactory := informers.NewSharedInformerFactory(client, controller.NoResyncPeriodFunc())
|
||||
classInformer := informerFactory.Storage().V1().StorageClasses()
|
||||
ctrl := &PersistentVolumeController{
|
||||
classLister: classInformer.Lister(),
|
||||
}
|
||||
|
||||
name := "volumeScheduling-feature-disabled"
|
||||
shouldDelay, err := ctrl.shouldDelayBinding(makePVCClass(&classWaitMode, false))
|
||||
if err != nil {
|
||||
t.Errorf("Test %q returned error: %v", name, err)
|
||||
}
|
||||
if shouldDelay {
|
||||
t.Errorf("Test %q returned true, expected false", name)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -413,7 +413,7 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS
|
|||
PodShareProcessNamespace: {Default: true, PreRelease: utilfeature.Beta},
|
||||
PodPriority: {Default: true, PreRelease: utilfeature.Beta},
|
||||
TaintNodesByCondition: {Default: true, PreRelease: utilfeature.Beta},
|
||||
MountPropagation: {Default: true, PreRelease: utilfeature.GA},
|
||||
MountPropagation: {Default: true, PreRelease: utilfeature.GA, LockToDefault: true}, // remove in 1.14
|
||||
QOSReserved: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
ExpandPersistentVolumes: {Default: true, PreRelease: utilfeature.Beta},
|
||||
ExpandInUsePersistentVolumes: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
|
@ -422,7 +422,7 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS
|
|||
CPUCFSQuotaPeriod: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
ServiceNodeExclusion: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
MountContainers: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
VolumeScheduling: {Default: true, PreRelease: utilfeature.GA},
|
||||
VolumeScheduling: {Default: true, PreRelease: utilfeature.GA, LockToDefault: true}, // remove in 1.16
|
||||
CSIPersistentVolume: {Default: true, PreRelease: utilfeature.GA},
|
||||
CSIDriverRegistry: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
CSINodeInfo: {Default: false, PreRelease: utilfeature.Alpha},
|
||||
|
|
|
@ -9,7 +9,6 @@ go_library(
|
|||
importpath = "k8s.io/kubernetes/pkg/scheduler",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/scheduler/algorithm:go_default_library",
|
||||
"//pkg/scheduler/algorithm/predicates:go_default_library",
|
||||
"//pkg/scheduler/api:go_default_library",
|
||||
|
@ -27,7 +26,6 @@ go_library(
|
|||
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers/apps/v1:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers/policy/v1beta1:go_default_library",
|
||||
|
@ -46,7 +44,6 @@ go_test(
|
|||
deps = [
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/controller/volume/persistentvolume:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/scheduler/algorithm:go_default_library",
|
||||
"//pkg/scheduler/algorithm/predicates:go_default_library",
|
||||
"//pkg/scheduler/api:go_default_library",
|
||||
|
@ -66,8 +63,6 @@ go_test(
|
|||
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/listers/core/v1:go_default_library",
|
||||
|
|
|
@ -635,18 +635,16 @@ func (c *VolumeZoneChecker) predicate(pod *v1.Pod, meta PredicateMetadata, nodeI
|
|||
|
||||
pvName := pvc.Spec.VolumeName
|
||||
if pvName == "" {
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||
scName := v1helper.GetPersistentVolumeClaimClass(pvc)
|
||||
if len(scName) > 0 {
|
||||
class, _ := c.classInfo.GetStorageClassInfo(scName)
|
||||
if class != nil {
|
||||
if class.VolumeBindingMode == nil {
|
||||
return false, nil, fmt.Errorf("VolumeBindingMode not set for StorageClass %q", scName)
|
||||
}
|
||||
if *class.VolumeBindingMode == storagev1.VolumeBindingWaitForFirstConsumer {
|
||||
// Skip unbound volumes
|
||||
continue
|
||||
}
|
||||
scName := v1helper.GetPersistentVolumeClaimClass(pvc)
|
||||
if len(scName) > 0 {
|
||||
class, _ := c.classInfo.GetStorageClassInfo(scName)
|
||||
if class != nil {
|
||||
if class.VolumeBindingMode == nil {
|
||||
return false, nil, fmt.Errorf("VolumeBindingMode not set for StorageClass %q", scName)
|
||||
}
|
||||
if *class.VolumeBindingMode == storagev1.VolumeBindingWaitForFirstConsumer {
|
||||
// Skip unbound volumes
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1618,10 +1616,6 @@ func NewVolumeBindingPredicate(binder *volumebinder.VolumeBinder) FitPredicate {
|
|||
}
|
||||
|
||||
func (c *VolumeBindingChecker) predicate(pod *v1.Pod, meta PredicateMetadata, nodeInfo *schedulernodeinfo.NodeInfo) (bool, []PredicateFailureReason, error) {
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||
return true, nil, nil
|
||||
}
|
||||
|
||||
node := nodeInfo.Node()
|
||||
if node == nil {
|
||||
return false, nil, fmt.Errorf("node not found")
|
||||
|
|
|
@ -29,10 +29,7 @@ import (
|
|||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
|
||||
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
|
||||
schedulerapi "k8s.io/kubernetes/pkg/scheduler/api"
|
||||
schedulernodeinfo "k8s.io/kubernetes/pkg/scheduler/nodeinfo"
|
||||
|
@ -4884,8 +4881,6 @@ func TestVolumeZonePredicateWithVolumeBinding(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)()
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
fit := NewVolumeZonePredicate(pvInfo, pvcInfo, classInfo)
|
||||
|
|
|
@ -12,7 +12,6 @@ go_library(
|
|||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//pkg/api/v1/pod:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/kubelet/apis:go_default_library",
|
||||
"//pkg/scheduler/algorithm:go_default_library",
|
||||
"//pkg/scheduler/algorithm/predicates:go_default_library",
|
||||
|
@ -38,7 +37,6 @@ go_library(
|
|||
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers/apps/v1:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/informers/policy/v1beta1:go_default_library",
|
||||
|
|
|
@ -38,7 +38,6 @@ import (
|
|||
"k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
appsinformers "k8s.io/client-go/informers/apps/v1"
|
||||
coreinformers "k8s.io/client-go/informers/core/v1"
|
||||
policyinformers "k8s.io/client-go/informers/policy/v1beta1"
|
||||
|
@ -51,7 +50,6 @@ import (
|
|||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/client-go/tools/record"
|
||||
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
|
||||
"k8s.io/kubernetes/pkg/scheduler/algorithm"
|
||||
"k8s.io/kubernetes/pkg/scheduler/algorithm/predicates"
|
||||
|
@ -378,16 +376,14 @@ func NewConfigFactory(args *ConfigFactoryArgs) Configurator {
|
|||
},
|
||||
)
|
||||
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||
// Setup volume binder
|
||||
c.volumeBinder = volumebinder.NewVolumeBinder(args.Client, args.PvcInformer, args.PvInformer, args.StorageClassInformer, time.Duration(args.BindTimeoutSeconds)*time.Second)
|
||||
// Setup volume binder
|
||||
c.volumeBinder = volumebinder.NewVolumeBinder(args.Client, args.PvcInformer, args.PvInformer, args.StorageClassInformer, time.Duration(args.BindTimeoutSeconds)*time.Second)
|
||||
|
||||
args.StorageClassInformer.Informer().AddEventHandler(
|
||||
cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: c.onStorageClassAdd,
|
||||
},
|
||||
)
|
||||
}
|
||||
args.StorageClassInformer.Informer().AddEventHandler(
|
||||
cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: c.onStorageClassAdd,
|
||||
},
|
||||
)
|
||||
|
||||
// Setup cache comparer
|
||||
debugger := cachedebugger.New(
|
||||
|
@ -491,9 +487,6 @@ func (c *configFactory) onPvcAdd(obj interface{}) {
|
|||
}
|
||||
|
||||
func (c *configFactory) onPvcUpdate(old, new interface{}) {
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||
return
|
||||
}
|
||||
c.podQueue.MoveAllToActiveQueue()
|
||||
}
|
||||
|
||||
|
|
|
@ -29,14 +29,12 @@ import (
|
|||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
appsinformers "k8s.io/client-go/informers/apps/v1"
|
||||
coreinformers "k8s.io/client-go/informers/core/v1"
|
||||
policyinformers "k8s.io/client-go/informers/policy/v1beta1"
|
||||
storageinformers "k8s.io/client-go/informers/storage/v1"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/tools/record"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
schedulerapi "k8s.io/kubernetes/pkg/scheduler/api"
|
||||
latestschedulerapi "k8s.io/kubernetes/pkg/scheduler/api/latest"
|
||||
kubeschedulerconfig "k8s.io/kubernetes/pkg/scheduler/apis/config"
|
||||
|
@ -352,12 +350,10 @@ func (sched *Scheduler) preempt(preemptor *v1.Pod, scheduleErr error) (string, e
|
|||
//
|
||||
// This function modifies assumed if volume binding is required.
|
||||
func (sched *Scheduler) assumeVolumes(assumed *v1.Pod, host string) (allBound bool, err error) {
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||
allBound, err = sched.config.VolumeBinder.Binder.AssumePodVolumes(assumed, host)
|
||||
if err != nil {
|
||||
sched.recordSchedulingFailure(assumed, err, SchedulerError,
|
||||
fmt.Sprintf("AssumePodVolumes failed: %v", err))
|
||||
}
|
||||
allBound, err = sched.config.VolumeBinder.Binder.AssumePodVolumes(assumed, host)
|
||||
if err != nil {
|
||||
sched.recordSchedulingFailure(assumed, err, SchedulerError,
|
||||
fmt.Sprintf("AssumePodVolumes failed: %v", err))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
@ -32,8 +32,6 @@ import (
|
|||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
|
||||
"k8s.io/client-go/informers"
|
||||
clientsetfake "k8s.io/client-go/kubernetes/fake"
|
||||
corelister "k8s.io/client-go/listers/core/v1"
|
||||
|
@ -41,7 +39,6 @@ import (
|
|||
"k8s.io/client-go/tools/record"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/controller/volume/persistentvolume"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/scheduler/algorithm"
|
||||
"k8s.io/kubernetes/pkg/scheduler/algorithm/predicates"
|
||||
"k8s.io/kubernetes/pkg/scheduler/api"
|
||||
|
@ -779,8 +776,6 @@ func TestSchedulerWithVolumeBinding(t *testing.T) {
|
|||
// This can be small because we wait for pod to finish scheduling first
|
||||
chanTimeout := 2 * time.Second
|
||||
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)()
|
||||
|
||||
table := []struct {
|
||||
name string
|
||||
expectError error
|
||||
|
|
|
@ -576,12 +576,10 @@ func (c *awsElasticBlockStoreProvisioner) Provision(selectedNode *v1.Node, allow
|
|||
}
|
||||
}
|
||||
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||
pv.Spec.NodeAffinity = new(v1.VolumeNodeAffinity)
|
||||
pv.Spec.NodeAffinity.Required = new(v1.NodeSelector)
|
||||
pv.Spec.NodeAffinity.Required.NodeSelectorTerms = make([]v1.NodeSelectorTerm, 1)
|
||||
pv.Spec.NodeAffinity.Required.NodeSelectorTerms[0].MatchExpressions = requirements
|
||||
}
|
||||
pv.Spec.NodeAffinity = new(v1.VolumeNodeAffinity)
|
||||
pv.Spec.NodeAffinity.Required = new(v1.NodeSelector)
|
||||
pv.Spec.NodeAffinity.Required.NodeSelectorTerms = make([]v1.NodeSelectorTerm, 1)
|
||||
pv.Spec.NodeAffinity.Required.NodeSelectorTerms[0].MatchExpressions = requirements
|
||||
|
||||
return pv, nil
|
||||
}
|
||||
|
|
|
@ -311,51 +311,49 @@ func (p *azureDiskProvisioner) Provision(selectedNode *v1.Node, allowedTopologie
|
|||
},
|
||||
}
|
||||
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||
nodeSelectorTerms := make([]v1.NodeSelectorTerm, 0)
|
||||
nodeSelectorTerms := make([]v1.NodeSelectorTerm, 0)
|
||||
|
||||
if zoned {
|
||||
// Set node affinity labels based on availability zone labels.
|
||||
if len(labels) > 0 {
|
||||
requirements := make([]v1.NodeSelectorRequirement, 0)
|
||||
for k, v := range labels {
|
||||
requirements = append(requirements, v1.NodeSelectorRequirement{Key: k, Operator: v1.NodeSelectorOpIn, Values: []string{v}})
|
||||
}
|
||||
if zoned {
|
||||
// Set node affinity labels based on availability zone labels.
|
||||
if len(labels) > 0 {
|
||||
requirements := make([]v1.NodeSelectorRequirement, 0)
|
||||
for k, v := range labels {
|
||||
requirements = append(requirements, v1.NodeSelectorRequirement{Key: k, Operator: v1.NodeSelectorOpIn, Values: []string{v}})
|
||||
}
|
||||
|
||||
nodeSelectorTerms = append(nodeSelectorTerms, v1.NodeSelectorTerm{
|
||||
MatchExpressions: requirements,
|
||||
})
|
||||
}
|
||||
} else {
|
||||
// Set node affinity labels based on fault domains.
|
||||
// This is required because unzoned AzureDisk can't be attached to zoned nodes.
|
||||
// There are at most 3 fault domains available in each region.
|
||||
// Refer https://docs.microsoft.com/en-us/azure/virtual-machines/windows/manage-availability.
|
||||
for i := 0; i < 3; i++ {
|
||||
requirements := []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: kubeletapis.LabelZoneRegion,
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{diskController.GetLocation()},
|
||||
},
|
||||
{
|
||||
Key: kubeletapis.LabelZoneFailureDomain,
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{strconv.Itoa(i)},
|
||||
},
|
||||
}
|
||||
nodeSelectorTerms = append(nodeSelectorTerms, v1.NodeSelectorTerm{
|
||||
MatchExpressions: requirements,
|
||||
})
|
||||
}
|
||||
nodeSelectorTerms = append(nodeSelectorTerms, v1.NodeSelectorTerm{
|
||||
MatchExpressions: requirements,
|
||||
})
|
||||
}
|
||||
|
||||
if len(nodeSelectorTerms) > 0 {
|
||||
pv.Spec.NodeAffinity = &v1.VolumeNodeAffinity{
|
||||
Required: &v1.NodeSelector{
|
||||
NodeSelectorTerms: nodeSelectorTerms,
|
||||
} else {
|
||||
// Set node affinity labels based on fault domains.
|
||||
// This is required because unzoned AzureDisk can't be attached to zoned nodes.
|
||||
// There are at most 3 fault domains available in each region.
|
||||
// Refer https://docs.microsoft.com/en-us/azure/virtual-machines/windows/manage-availability.
|
||||
for i := 0; i < 3; i++ {
|
||||
requirements := []v1.NodeSelectorRequirement{
|
||||
{
|
||||
Key: kubeletapis.LabelZoneRegion,
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{diskController.GetLocation()},
|
||||
},
|
||||
{
|
||||
Key: kubeletapis.LabelZoneFailureDomain,
|
||||
Operator: v1.NodeSelectorOpIn,
|
||||
Values: []string{strconv.Itoa(i)},
|
||||
},
|
||||
}
|
||||
nodeSelectorTerms = append(nodeSelectorTerms, v1.NodeSelectorTerm{
|
||||
MatchExpressions: requirements,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
if len(nodeSelectorTerms) > 0 {
|
||||
pv.Spec.NodeAffinity = &v1.VolumeNodeAffinity{
|
||||
Required: &v1.NodeSelector{
|
||||
NodeSelectorTerms: nodeSelectorTerms,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -561,20 +561,18 @@ func (c *cinderVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopolo
|
|||
pv.Spec.AccessModes = c.plugin.GetAccessModes()
|
||||
}
|
||||
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||
requirements := make([]v1.NodeSelectorRequirement, 0)
|
||||
for k, v := range labels {
|
||||
if v != "" {
|
||||
requirements = append(requirements, v1.NodeSelectorRequirement{Key: k, Operator: v1.NodeSelectorOpIn, Values: []string{v}})
|
||||
}
|
||||
}
|
||||
if len(requirements) > 0 {
|
||||
pv.Spec.NodeAffinity = new(v1.VolumeNodeAffinity)
|
||||
pv.Spec.NodeAffinity.Required = new(v1.NodeSelector)
|
||||
pv.Spec.NodeAffinity.Required.NodeSelectorTerms = make([]v1.NodeSelectorTerm, 1)
|
||||
pv.Spec.NodeAffinity.Required.NodeSelectorTerms[0].MatchExpressions = requirements
|
||||
requirements := make([]v1.NodeSelectorRequirement, 0)
|
||||
for k, v := range labels {
|
||||
if v != "" {
|
||||
requirements = append(requirements, v1.NodeSelectorRequirement{Key: k, Operator: v1.NodeSelectorOpIn, Values: []string{v}})
|
||||
}
|
||||
}
|
||||
if len(requirements) > 0 {
|
||||
pv.Spec.NodeAffinity = new(v1.VolumeNodeAffinity)
|
||||
pv.Spec.NodeAffinity.Required = new(v1.NodeSelector)
|
||||
pv.Spec.NodeAffinity.Required.NodeSelectorTerms = make([]v1.NodeSelectorTerm, 1)
|
||||
pv.Spec.NodeAffinity.Required.NodeSelectorTerms[0].MatchExpressions = requirements
|
||||
}
|
||||
|
||||
return pv, nil
|
||||
}
|
||||
|
|
|
@ -551,7 +551,7 @@ func (c *gcePersistentDiskProvisioner) Provision(selectedNode *v1.Node, allowedT
|
|||
}
|
||||
}
|
||||
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) && len(requirements) > 0 {
|
||||
if len(requirements) > 0 {
|
||||
pv.Spec.NodeAffinity = new(v1.VolumeNodeAffinity)
|
||||
pv.Spec.NodeAffinity.Required = new(v1.NodeSelector)
|
||||
pv.Spec.NodeAffinity.Required.NodeSelectorTerms = make([]v1.NodeSelectorTerm, 1)
|
||||
|
|
|
@ -60,7 +60,6 @@ go_test(
|
|||
deps = [
|
||||
"//pkg/apis/core/install:go_default_library",
|
||||
"//pkg/apis/core/v1/helper:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/kubelet/apis:go_default_library",
|
||||
"//pkg/util/mount:go_default_library",
|
||||
"//pkg/util/slice:go_default_library",
|
||||
|
@ -70,8 +69,6 @@ go_test(
|
|||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/util/testing:go_default_library",
|
||||
],
|
||||
)
|
||||
|
|
|
@ -24,7 +24,6 @@ import (
|
|||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
|
||||
utiltesting "k8s.io/client-go/util/testing"
|
||||
|
||||
// util.go uses api.Codecs.LegacyCodec so import this package to do some
|
||||
|
@ -32,7 +31,6 @@ import (
|
|||
"hash/fnv"
|
||||
|
||||
_ "k8s.io/kubernetes/pkg/apis/core/install"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
|
||||
"reflect"
|
||||
|
@ -40,7 +38,6 @@ import (
|
|||
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
|
||||
|
||||
"k8s.io/kubernetes/pkg/util/slice"
|
||||
|
@ -1065,7 +1062,6 @@ func TestSelectZoneForVolume(t *testing.T) {
|
|||
ZonesWithNodes string
|
||||
Node *v1.Node
|
||||
AllowedTopologies []v1.TopologySelectorTerm
|
||||
VolumeScheduling bool
|
||||
// Expectations around returned zone from SelectZoneForVolume
|
||||
Reject bool // expect error due to validation failing
|
||||
ExpectSpecificZone bool // expect returned zone to specifically match a single zone (rather than one from a set)
|
||||
|
@ -1078,7 +1074,6 @@ func TestSelectZoneForVolume(t *testing.T) {
|
|||
// [1] Node irrelevant
|
||||
// [2] Zone and Zones parameters presents
|
||||
// [3] AllowedTopologies irrelevant
|
||||
// [4] VolumeScheduling irrelevant
|
||||
{
|
||||
Name: "Nil_Node_with_Zone_Zones_parameters_present",
|
||||
ZonePresent: true,
|
||||
|
@ -1092,53 +1087,45 @@ func TestSelectZoneForVolume(t *testing.T) {
|
|||
// [1] Node with no zone labels
|
||||
// [2] Zone/Zones parameter irrelevant
|
||||
// [3] AllowedTopologies irrelevant
|
||||
// [4] VolumeScheduling enabled
|
||||
{
|
||||
Name: "Node_with_no_Zone_labels",
|
||||
Node: nodeWithNoLabels,
|
||||
VolumeScheduling: true,
|
||||
Reject: true,
|
||||
Name: "Node_with_no_Zone_labels",
|
||||
Node: nodeWithNoLabels,
|
||||
Reject: true,
|
||||
},
|
||||
|
||||
// Node with Zone labels as well as Zone parameter specified [Fail]
|
||||
// [1] Node with zone labels
|
||||
// [2] Zone parameter specified
|
||||
// [3] AllowedTopologies irrelevant
|
||||
// [4] VolumeScheduling enabled
|
||||
{
|
||||
Name: "Node_with_Zone_labels_and_Zone_parameter_present",
|
||||
Node: nodeWithZoneLabels,
|
||||
ZonePresent: true,
|
||||
Zone: "zoneX",
|
||||
VolumeScheduling: true,
|
||||
Reject: true,
|
||||
Name: "Node_with_Zone_labels_and_Zone_parameter_present",
|
||||
Node: nodeWithZoneLabels,
|
||||
ZonePresent: true,
|
||||
Zone: "zoneX",
|
||||
Reject: true,
|
||||
},
|
||||
|
||||
// Node with Zone labels as well as Zones parameter specified [Fail]
|
||||
// [1] Node with zone labels
|
||||
// [2] Zones parameter specified
|
||||
// [3] AllowedTopologies irrelevant
|
||||
// [4] VolumeScheduling enabled
|
||||
{
|
||||
Name: "Node_with_Zone_labels_and_Zones_parameter_present",
|
||||
Node: nodeWithZoneLabels,
|
||||
ZonesPresent: true,
|
||||
Zones: "zoneX,zoneY",
|
||||
VolumeScheduling: true,
|
||||
Reject: true,
|
||||
Name: "Node_with_Zone_labels_and_Zones_parameter_present",
|
||||
Node: nodeWithZoneLabels,
|
||||
ZonesPresent: true,
|
||||
Zones: "zoneX,zoneY",
|
||||
Reject: true,
|
||||
},
|
||||
|
||||
// Zone parameter as well as AllowedTopologies specified [Fail]
|
||||
// [1] nil Node
|
||||
// [2] Zone parameter specified
|
||||
// [3] AllowedTopologies specified
|
||||
// [4] VolumeScheduling enabled
|
||||
{
|
||||
Name: "Nil_Node_and_Zone_parameter_and_Allowed_Topology_term",
|
||||
Node: nil,
|
||||
ZonePresent: true,
|
||||
Zone: "zoneX",
|
||||
VolumeScheduling: true,
|
||||
Name: "Nil_Node_and_Zone_parameter_and_Allowed_Topology_term",
|
||||
Node: nil,
|
||||
ZonePresent: true,
|
||||
Zone: "zoneX",
|
||||
AllowedTopologies: []v1.TopologySelectorTerm{
|
||||
{
|
||||
MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{
|
||||
|
@ -1156,13 +1143,11 @@ func TestSelectZoneForVolume(t *testing.T) {
|
|||
// [1] nil Node
|
||||
// [2] Zones parameter specified
|
||||
// [3] AllowedTopologies specified
|
||||
// [4] VolumeScheduling enabled
|
||||
{
|
||||
Name: "Nil_Node_and_Zones_parameter_and_Allowed_Topology_term",
|
||||
Node: nil,
|
||||
ZonesPresent: true,
|
||||
Zones: "zoneX,zoneY",
|
||||
VolumeScheduling: true,
|
||||
Name: "Nil_Node_and_Zones_parameter_and_Allowed_Topology_term",
|
||||
Node: nil,
|
||||
ZonesPresent: true,
|
||||
Zones: "zoneX,zoneY",
|
||||
AllowedTopologies: []v1.TopologySelectorTerm{
|
||||
{
|
||||
MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{
|
||||
|
@ -1180,11 +1165,9 @@ func TestSelectZoneForVolume(t *testing.T) {
|
|||
// [1] nil Node
|
||||
// [2] no Zone/Zones parameter
|
||||
// [3] AllowedTopologies with invalid key specified
|
||||
// [4] VolumeScheduling enabled
|
||||
{
|
||||
Name: "Nil_Node_and_Invalid_Allowed_Topology_Key",
|
||||
Node: nil,
|
||||
VolumeScheduling: true,
|
||||
Name: "Nil_Node_and_Invalid_Allowed_Topology_Key",
|
||||
Node: nil,
|
||||
AllowedTopologies: []v1.TopologySelectorTerm{
|
||||
{
|
||||
MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{
|
||||
|
@ -1206,11 +1189,9 @@ func TestSelectZoneForVolume(t *testing.T) {
|
|||
// [1] nil Node
|
||||
// [2] no Zone/Zones parameter
|
||||
// [3] Invalid AllowedTopologies
|
||||
// [4] VolumeScheduling enabled
|
||||
{
|
||||
Name: "Nil_Node_and_Invalid_AllowedTopologies",
|
||||
Node: nil,
|
||||
VolumeScheduling: true,
|
||||
Name: "Nil_Node_and_Invalid_AllowedTopologies",
|
||||
Node: nil,
|
||||
AllowedTopologies: []v1.TopologySelectorTerm{
|
||||
{
|
||||
MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{},
|
||||
|
@ -1219,77 +1200,29 @@ func TestSelectZoneForVolume(t *testing.T) {
|
|||
Reject: true,
|
||||
},
|
||||
|
||||
// POSITIVE TESTS WITH VolumeScheduling DISABLED
|
||||
|
||||
// Select zone from active zones [Pass]
|
||||
// [1] nil Node (Node irrelevant)
|
||||
// [2] no Zone parameter
|
||||
// [3] no AllowedTopologies
|
||||
// [4] VolumeScheduling disabled
|
||||
{
|
||||
Name: "No_Zone_Zones_parameter_and_VolumeScheduling_disabled",
|
||||
ZonesWithNodes: "zoneX,zoneY",
|
||||
VolumeScheduling: false,
|
||||
Reject: false,
|
||||
ExpectedZones: "zoneX,zoneY",
|
||||
},
|
||||
|
||||
// Select zone from single zone parameter [Pass]
|
||||
// [1] nil Node (Node irrelevant)
|
||||
// [2] Zone parameter specified
|
||||
// [3] no AllowedTopologies
|
||||
// [4] VolumeScheduling disabled
|
||||
{
|
||||
Name: "Zone_parameter_present_and_VolumeScheduling_disabled",
|
||||
ZonePresent: true,
|
||||
Zone: "zoneX",
|
||||
VolumeScheduling: false,
|
||||
Reject: false,
|
||||
ExpectSpecificZone: true,
|
||||
ExpectedZone: "zoneX",
|
||||
},
|
||||
|
||||
// Select zone from zones parameter [Pass]
|
||||
// [1] nil Node (Node irrelevant)
|
||||
// [2] Zones parameter specified
|
||||
// [3] no AllowedTopologies
|
||||
// [4] VolumeScheduling disabled
|
||||
{
|
||||
Name: "Zones_parameter_present_and_VolumeScheduling_disabled",
|
||||
ZonesPresent: true,
|
||||
Zones: "zoneX,zoneY",
|
||||
VolumeScheduling: false,
|
||||
Reject: false,
|
||||
ExpectedZones: "zoneX,zoneY",
|
||||
},
|
||||
|
||||
// POSITIVE TESTS WITH VolumeScheduling ENABLED
|
||||
|
||||
// Select zone from active zones [Pass]
|
||||
// [1] nil Node
|
||||
// [2] no Zone parameter specified
|
||||
// [3] no AllowedTopologies
|
||||
// [4] VolumeScheduling enabled
|
||||
{
|
||||
Name: "Nil_Node_and_No_Zone_Zones_parameter_and_no_Allowed_topologies_and_VolumeScheduling_enabled",
|
||||
Node: nil,
|
||||
ZonesWithNodes: "zoneX,zoneY",
|
||||
VolumeScheduling: true,
|
||||
Reject: false,
|
||||
ExpectedZones: "zoneX,zoneY",
|
||||
Name: "Nil_Node_and_No_Zone_Zones_parameter_and_no_Allowed_topologies_and_VolumeScheduling_enabled",
|
||||
Node: nil,
|
||||
ZonesWithNodes: "zoneX,zoneY",
|
||||
Reject: false,
|
||||
ExpectedZones: "zoneX,zoneY",
|
||||
},
|
||||
|
||||
// Select zone from single zone parameter [Pass]
|
||||
// [1] nil Node
|
||||
// [2] Zone parameter specified
|
||||
// [3] no AllowedTopology specified
|
||||
// [4] VolumeScheduling enabled
|
||||
{
|
||||
Name: "Nil_Node_and_Zone_parameter_present_and_VolumeScheduling_enabled",
|
||||
ZonePresent: true,
|
||||
Zone: "zoneX",
|
||||
Node: nil,
|
||||
VolumeScheduling: true,
|
||||
Reject: false,
|
||||
ExpectSpecificZone: true,
|
||||
ExpectedZone: "zoneX",
|
||||
|
@ -1299,26 +1232,22 @@ func TestSelectZoneForVolume(t *testing.T) {
|
|||
// [1] nil Node
|
||||
// [2] Zones parameter specified
|
||||
// [3] no AllowedTopology
|
||||
// [4] VolumeScheduling enabled
|
||||
{
|
||||
Name: "Nil_Node_and_Zones_parameter_present_and_VolumeScheduling_enabled",
|
||||
ZonesPresent: true,
|
||||
Zones: "zoneX,zoneY",
|
||||
Node: nil,
|
||||
VolumeScheduling: true,
|
||||
Reject: false,
|
||||
ExpectedZones: "zoneX,zoneY",
|
||||
Name: "Nil_Node_and_Zones_parameter_present_and_VolumeScheduling_enabled",
|
||||
ZonesPresent: true,
|
||||
Zones: "zoneX,zoneY",
|
||||
Node: nil,
|
||||
Reject: false,
|
||||
ExpectedZones: "zoneX,zoneY",
|
||||
},
|
||||
|
||||
// Select zone from node label [Pass]
|
||||
// [1] Node with zone labels
|
||||
// [2] no zone/zones parameters
|
||||
// [3] no AllowedTopology
|
||||
// [4] VolumeScheduling enabled
|
||||
{
|
||||
Name: "Node_with_Zone_labels_and_VolumeScheduling_enabled",
|
||||
Node: nodeWithZoneLabels,
|
||||
VolumeScheduling: true,
|
||||
Reject: false,
|
||||
ExpectSpecificZone: true,
|
||||
ExpectedZone: "zoneX",
|
||||
|
@ -1328,11 +1257,9 @@ func TestSelectZoneForVolume(t *testing.T) {
|
|||
// [1] Node with zone labels
|
||||
// [2] no Zone/Zones parameters
|
||||
// [3] AllowedTopology with single term with multiple values specified (ignored)
|
||||
// [4] VolumeScheduling enabled
|
||||
{
|
||||
Name: "Node_with_Zone_labels_and_Multiple_Allowed_Topology_values_and_VolumeScheduling_enabled",
|
||||
Node: nodeWithZoneLabels,
|
||||
VolumeScheduling: true,
|
||||
Name: "Node_with_Zone_labels_and_Multiple_Allowed_Topology_values_and_VolumeScheduling_enabled",
|
||||
Node: nodeWithZoneLabels,
|
||||
AllowedTopologies: []v1.TopologySelectorTerm{
|
||||
{
|
||||
MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{
|
||||
|
@ -1352,11 +1279,9 @@ func TestSelectZoneForVolume(t *testing.T) {
|
|||
// [1] nil Node
|
||||
// [2] no Zone/Zones parametes specified
|
||||
// [3] AllowedTopologies with single term with multiple values specified
|
||||
// [4] VolumeScheduling enabled
|
||||
{
|
||||
Name: "Nil_Node_with_Multiple_Allowed_Topology_values_and_VolumeScheduling_enabled",
|
||||
Node: nil,
|
||||
VolumeScheduling: true,
|
||||
Name: "Nil_Node_with_Multiple_Allowed_Topology_values_and_VolumeScheduling_enabled",
|
||||
Node: nil,
|
||||
AllowedTopologies: []v1.TopologySelectorTerm{
|
||||
{
|
||||
MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{
|
||||
|
@ -1375,11 +1300,9 @@ func TestSelectZoneForVolume(t *testing.T) {
|
|||
// [1] nil Node
|
||||
// [2] no Zone/Zones parametes specified
|
||||
// [3] AllowedTopologies with multiple terms specified
|
||||
// [4] VolumeScheduling enabled
|
||||
{
|
||||
Name: "Nil_Node_and_Multiple_Allowed_Topology_terms_and_VolumeScheduling_enabled",
|
||||
Node: nil,
|
||||
VolumeScheduling: true,
|
||||
Name: "Nil_Node_and_Multiple_Allowed_Topology_terms_and_VolumeScheduling_enabled",
|
||||
Node: nil,
|
||||
AllowedTopologies: []v1.TopologySelectorTerm{
|
||||
{
|
||||
MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{
|
||||
|
@ -1407,11 +1330,9 @@ func TestSelectZoneForVolume(t *testing.T) {
|
|||
// [1] nil Node
|
||||
// [2] no Zone/Zones parametes specified
|
||||
// [3] AllowedTopologies with single term and value specified
|
||||
// [4] VolumeScheduling enabled
|
||||
{
|
||||
Name: "Nil_Node_and_Single_Allowed_Topology_term_value_and_VolumeScheduling_enabled",
|
||||
Node: nil,
|
||||
VolumeScheduling: true,
|
||||
Name: "Nil_Node_and_Single_Allowed_Topology_term_value_and_VolumeScheduling_enabled",
|
||||
Node: nil,
|
||||
AllowedTopologies: []v1.TopologySelectorTerm{
|
||||
{
|
||||
MatchLabelExpressions: []v1.TopologySelectorLabelRequirement{
|
||||
|
@ -1430,8 +1351,6 @@ func TestSelectZoneForVolume(t *testing.T) {
|
|||
|
||||
for _, test := range tests {
|
||||
t.Run(test.Name, func(t *testing.T) {
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, test.VolumeScheduling)()
|
||||
|
||||
var zonesParameter, zonesWithNodes sets.String
|
||||
var err error
|
||||
|
||||
|
|
|
@ -18,13 +18,11 @@ go_library(
|
|||
"//pkg/cloudprovider/providers/aws:go_default_library",
|
||||
"//pkg/cloudprovider/providers/azure:go_default_library",
|
||||
"//pkg/cloudprovider/providers/gce:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/kubeapiserver/admission:go_default_library",
|
||||
"//pkg/kubelet/apis:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//pkg/volume/util:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/cloud-provider:go_default_library",
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
],
|
||||
|
@ -37,15 +35,12 @@ go_test(
|
|||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/cloudprovider/providers/aws:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/kubelet/apis:go_default_library",
|
||||
"//pkg/volume/util:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/admission:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature/testing:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
|
|
@ -23,14 +23,12 @@ import (
|
|||
"sync"
|
||||
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
cloudprovider "k8s.io/cloud-provider"
|
||||
"k8s.io/klog"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/aws"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/azure"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
kubeapiserveradmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
|
||||
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
|
||||
vol "k8s.io/kubernetes/pkg/volume"
|
||||
|
@ -158,25 +156,23 @@ func (l *persistentVolumeLabel) Admit(a admission.Attributes) (err error) {
|
|||
requirements = append(requirements, api.NodeSelectorRequirement{Key: k, Operator: api.NodeSelectorOpIn, Values: values})
|
||||
}
|
||||
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||
if volume.Spec.NodeAffinity == nil {
|
||||
volume.Spec.NodeAffinity = new(api.VolumeNodeAffinity)
|
||||
}
|
||||
if volume.Spec.NodeAffinity.Required == nil {
|
||||
volume.Spec.NodeAffinity.Required = new(api.NodeSelector)
|
||||
}
|
||||
if len(volume.Spec.NodeAffinity.Required.NodeSelectorTerms) == 0 {
|
||||
// Need at least one term pre-allocated whose MatchExpressions can be appended to
|
||||
volume.Spec.NodeAffinity.Required.NodeSelectorTerms = make([]api.NodeSelectorTerm, 1)
|
||||
}
|
||||
if nodeSelectorRequirementKeysExistInNodeSelectorTerms(requirements, volume.Spec.NodeAffinity.Required.NodeSelectorTerms) {
|
||||
klog.V(4).Infof("NodeSelectorRequirements for cloud labels %v conflict with existing NodeAffinity %v. Skipping addition of NodeSelectorRequirements for cloud labels.",
|
||||
requirements, volume.Spec.NodeAffinity)
|
||||
} else {
|
||||
for _, req := range requirements {
|
||||
for i := range volume.Spec.NodeAffinity.Required.NodeSelectorTerms {
|
||||
volume.Spec.NodeAffinity.Required.NodeSelectorTerms[i].MatchExpressions = append(volume.Spec.NodeAffinity.Required.NodeSelectorTerms[i].MatchExpressions, req)
|
||||
}
|
||||
if volume.Spec.NodeAffinity == nil {
|
||||
volume.Spec.NodeAffinity = new(api.VolumeNodeAffinity)
|
||||
}
|
||||
if volume.Spec.NodeAffinity.Required == nil {
|
||||
volume.Spec.NodeAffinity.Required = new(api.NodeSelector)
|
||||
}
|
||||
if len(volume.Spec.NodeAffinity.Required.NodeSelectorTerms) == 0 {
|
||||
// Need at least one term pre-allocated whose MatchExpressions can be appended to
|
||||
volume.Spec.NodeAffinity.Required.NodeSelectorTerms = make([]api.NodeSelectorTerm, 1)
|
||||
}
|
||||
if nodeSelectorRequirementKeysExistInNodeSelectorTerms(requirements, volume.Spec.NodeAffinity.Required.NodeSelectorTerms) {
|
||||
klog.V(4).Infof("NodeSelectorRequirements for cloud labels %v conflict with existing NodeAffinity %v. Skipping addition of NodeSelectorRequirements for cloud labels.",
|
||||
requirements, volume.Spec.NodeAffinity)
|
||||
} else {
|
||||
for _, req := range requirements {
|
||||
for i := range volume.Spec.NodeAffinity.Required.NodeSelectorTerms {
|
||||
volume.Spec.NodeAffinity.Required.NodeSelectorTerms[i].MatchExpressions = append(volume.Spec.NodeAffinity.Required.NodeSelectorTerms[i].MatchExpressions, req)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,11 +27,8 @@ import (
|
|||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
utilfeaturetesting "k8s.io/apiserver/pkg/util/feature/testing"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/aws"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
|
||||
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
||||
)
|
||||
|
@ -125,8 +122,6 @@ func TestAdmission(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)()
|
||||
|
||||
// Non-cloud PVs are ignored
|
||||
err := handler.Admit(admission.NewAttributesRecord(&ignoredPV, nil, api.Kind("PersistentVolume").WithVersion("version"), ignoredPV.Namespace, ignoredPV.Name, api.Resource("persistentvolumes").WithVersion("version"), "", admission.Create, false, nil))
|
||||
if err != nil {
|
||||
|
|
|
@ -489,17 +489,14 @@ func ClusterRoles() []rbacv1.ClusterRole {
|
|||
rbacv1helpers.NewRule("create").Groups(certificatesGroup).Resources("certificatesigningrequests/selfnodeclient").RuleOrDie(),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||
roles = append(roles, rbacv1.ClusterRole{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "system:volume-scheduler"},
|
||||
Rules: []rbacv1.PolicyRule{
|
||||
rbacv1helpers.NewRule(ReadUpdate...).Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(),
|
||||
rbacv1helpers.NewRule(Read...).Groups(storageGroup).Resources("storageclasses").RuleOrDie(),
|
||||
rbacv1helpers.NewRule(ReadUpdate...).Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(),
|
||||
},
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
externalProvisionerRules := []rbacv1.PolicyRule{
|
||||
|
@ -535,6 +532,7 @@ func ClusterRoleBindings() []rbacv1.ClusterRoleBinding {
|
|||
rbacv1helpers.NewClusterBinding("system:kube-dns").SAs("kube-system", "kube-dns").BindingOrDie(),
|
||||
rbacv1helpers.NewClusterBinding("system:kube-scheduler").Users(user.KubeScheduler).BindingOrDie(),
|
||||
rbacv1helpers.NewClusterBinding("system:aws-cloud-provider").SAs("kube-system", "aws-cloud-provider").BindingOrDie(),
|
||||
rbacv1helpers.NewClusterBinding("system:volume-scheduler").Users(user.KubeScheduler).BindingOrDie(),
|
||||
|
||||
// This default binding of the system:node role to the system:nodes group is deprecated in 1.7 with the availability of the Node authorizer.
|
||||
// This leaves the binding, but with an empty set of subjects, so that tightening reconciliation can remove the subject.
|
||||
|
@ -544,10 +542,6 @@ func ClusterRoleBindings() []rbacv1.ClusterRoleBinding {
|
|||
},
|
||||
}
|
||||
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||
rolebindings = append(rolebindings, rbacv1helpers.NewClusterBinding("system:volume-scheduler").Users(user.KubeScheduler).BindingOrDie())
|
||||
}
|
||||
|
||||
addClusterRoleBindingLabel(rolebindings)
|
||||
|
||||
return rolebindings
|
||||
|
|
|
@ -63,7 +63,11 @@ var (
|
|||
)
|
||||
|
||||
type FeatureSpec struct {
|
||||
Default bool
|
||||
// Default is the default enablement state for the feature
|
||||
Default bool
|
||||
// LockToDefault indicates that the feature is locked to its default and cannot be changed
|
||||
LockToDefault bool
|
||||
// PreRelease indicates the maturity level of the feature
|
||||
PreRelease prerelease
|
||||
}
|
||||
|
||||
|
@ -199,6 +203,9 @@ func (f *featureGate) SetFromMap(m map[string]bool) error {
|
|||
if !ok {
|
||||
return fmt.Errorf("unrecognized feature gate: %s", k)
|
||||
}
|
||||
if featureSpec.LockToDefault && featureSpec.Default != v {
|
||||
return fmt.Errorf("cannot set feature gate %v to %v, feature is locked to %v", k, v, featureSpec.Default)
|
||||
}
|
||||
enabled[k] = v
|
||||
// Handle "special" features like "all alpha gates"
|
||||
if fn, found := f.special[k]; found {
|
||||
|
|
|
@ -221,6 +221,8 @@ func TestFeatureGateSetFromMap(t *testing.T) {
|
|||
// gates for testing
|
||||
const testAlphaGate Feature = "TestAlpha"
|
||||
const testBetaGate Feature = "TestBeta"
|
||||
const testLockedTrueGate Feature = "TestLockedTrue"
|
||||
const testLockedFalseGate Feature = "TestLockedFalse"
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
|
@ -270,17 +272,54 @@ func TestFeatureGateSetFromMap(t *testing.T) {
|
|||
},
|
||||
setmapError: "unrecognized feature gate:",
|
||||
},
|
||||
{
|
||||
name: "set locked gates",
|
||||
setmap: map[string]bool{
|
||||
"TestLockedTrue": true,
|
||||
"TestLockedFalse": false,
|
||||
},
|
||||
expect: map[Feature]bool{
|
||||
testAlphaGate: false,
|
||||
testBetaGate: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "set locked gates",
|
||||
setmap: map[string]bool{
|
||||
"TestLockedTrue": false,
|
||||
},
|
||||
expect: map[Feature]bool{
|
||||
testAlphaGate: false,
|
||||
testBetaGate: false,
|
||||
},
|
||||
setmapError: "cannot set feature gate TestLockedTrue to false, feature is locked to true",
|
||||
},
|
||||
{
|
||||
name: "set locked gates",
|
||||
setmap: map[string]bool{
|
||||
"TestLockedFalse": true,
|
||||
},
|
||||
expect: map[Feature]bool{
|
||||
testAlphaGate: false,
|
||||
testBetaGate: false,
|
||||
},
|
||||
setmapError: "cannot set feature gate TestLockedFalse to true, feature is locked to false",
|
||||
},
|
||||
}
|
||||
for i, test := range tests {
|
||||
t.Run(fmt.Sprintf("SetFromMap %s", test.name), func(t *testing.T) {
|
||||
f := NewFeatureGate()
|
||||
f.Add(map[Feature]FeatureSpec{
|
||||
testAlphaGate: {Default: false, PreRelease: Alpha},
|
||||
testBetaGate: {Default: false, PreRelease: Beta},
|
||||
testAlphaGate: {Default: false, PreRelease: Alpha},
|
||||
testBetaGate: {Default: false, PreRelease: Beta},
|
||||
testLockedTrueGate: {Default: true, PreRelease: GA, LockToDefault: true},
|
||||
testLockedFalseGate: {Default: false, PreRelease: GA, LockToDefault: true},
|
||||
})
|
||||
err := f.SetFromMap(test.setmap)
|
||||
if test.setmapError != "" {
|
||||
if !strings.Contains(err.Error(), test.setmapError) {
|
||||
if err == nil {
|
||||
t.Errorf("expected error, got none")
|
||||
} else if !strings.Contains(err.Error(), test.setmapError) {
|
||||
t.Errorf("%d: SetFromMap(%#v) Expected err:%v, Got err:%v", i, test.setmap, test.setmapError, err)
|
||||
}
|
||||
} else if err != nil {
|
||||
|
|
|
@ -97,7 +97,6 @@ type testPVC struct {
|
|||
}
|
||||
|
||||
func TestVolumeBinding(t *testing.T) {
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)()
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PersistentLocalVolumes, true)()
|
||||
config := setupCluster(t, "volume-scheduling-", 2, 0, 0)
|
||||
defer config.teardown()
|
||||
|
@ -268,7 +267,6 @@ func TestVolumeBinding(t *testing.T) {
|
|||
|
||||
// TestVolumeBindingRescheduling tests scheduler will retry scheduling when needed.
|
||||
func TestVolumeBindingRescheduling(t *testing.T) {
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)()
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PersistentLocalVolumes, true)()
|
||||
config := setupCluster(t, "volume-scheduling-", 2, 0, 0)
|
||||
defer config.teardown()
|
||||
|
@ -412,7 +410,6 @@ func TestVolumeBindingDynamicStressSlow(t *testing.T) {
|
|||
}
|
||||
|
||||
func testVolumeBindingStress(t *testing.T, schedulerResyncPeriod time.Duration, dynamic bool, provisionDelaySeconds int) {
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)()
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PersistentLocalVolumes, true)()
|
||||
config := setupCluster(t, "volume-binding-stress-", 1, schedulerResyncPeriod, provisionDelaySeconds)
|
||||
defer config.teardown()
|
||||
|
@ -502,7 +499,6 @@ func testVolumeBindingStress(t *testing.T, schedulerResyncPeriod time.Duration,
|
|||
}
|
||||
|
||||
func testVolumeBindingWithAffinity(t *testing.T, anti bool, numNodes, numPods, numPVsFirstNode int) {
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)()
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PersistentLocalVolumes, true)()
|
||||
config := setupCluster(t, "volume-pod-affinity-", numNodes, 0, 0)
|
||||
defer config.teardown()
|
||||
|
@ -629,7 +625,6 @@ func TestVolumeBindingWithAffinity(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestPVAffinityConflict(t *testing.T) {
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)()
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PersistentLocalVolumes, true)()
|
||||
config := setupCluster(t, "volume-scheduling-", 3, 0, 0)
|
||||
defer config.teardown()
|
||||
|
@ -690,7 +685,6 @@ func TestPVAffinityConflict(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestVolumeProvision(t *testing.T) {
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)()
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PersistentLocalVolumes, true)()
|
||||
config := setupCluster(t, "volume-scheduling", 1, 0, 0)
|
||||
defer config.teardown()
|
||||
|
@ -830,7 +824,6 @@ func TestVolumeProvision(t *testing.T) {
|
|||
// on provision failure.
|
||||
func TestRescheduleProvisioning(t *testing.T) {
|
||||
// Set feature gates
|
||||
defer utilfeaturetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeScheduling, true)()
|
||||
controllerCh := make(chan struct{})
|
||||
|
||||
context := initTestMaster(t, "reschedule-volume-provision", nil)
|
||||
|
|
Loading…
Reference in New Issue