mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-20 02:11:09 +00:00
storage capacity: GA, always enabled, remove feature check
The code and tests for scenarios where the feature is disabled are no longer needed because the feature is graduating to GA.
This commit is contained in:
parent
faa027ca2b
commit
3a7deaa141
@ -357,9 +357,6 @@ type CSIDriverSpec struct {
|
||||
//
|
||||
// This field was immutable in Kubernetes <= 1.22 and now is mutable.
|
||||
//
|
||||
// This is a beta field and only available when the CSIStorageCapacity
|
||||
// feature is enabled. The default is false.
|
||||
//
|
||||
// +optional
|
||||
StorageCapacity *bool
|
||||
|
||||
|
@ -49,7 +49,7 @@ func SetDefaults_CSIDriver(obj *storagev1.CSIDriver) {
|
||||
obj.Spec.PodInfoOnMount = new(bool)
|
||||
*(obj.Spec.PodInfoOnMount) = false
|
||||
}
|
||||
if obj.Spec.StorageCapacity == nil && utilfeature.DefaultFeatureGate.Enabled(features.CSIStorageCapacity) {
|
||||
if obj.Spec.StorageCapacity == nil {
|
||||
obj.Spec.StorageCapacity = new(bool)
|
||||
*(obj.Spec.StorageCapacity) = false
|
||||
}
|
||||
|
@ -52,7 +52,6 @@ func roundTrip(t *testing.T, obj runtime.Object) runtime.Object {
|
||||
}
|
||||
|
||||
func TestSetDefaultStorageCapacityEnabled(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIStorageCapacity, true)()
|
||||
driver := &storagev1.CSIDriver{}
|
||||
|
||||
// field should be defaulted
|
||||
@ -66,18 +65,6 @@ func TestSetDefaultStorageCapacityEnabled(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultStorageCapacityDisabled(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIStorageCapacity, false)()
|
||||
driver := &storagev1.CSIDriver{}
|
||||
|
||||
// field should not be defaulted
|
||||
output := roundTrip(t, runtime.Object(driver)).(*storagev1.CSIDriver)
|
||||
outStorageCapacity := output.Spec.StorageCapacity
|
||||
if outStorageCapacity != nil {
|
||||
t.Errorf("Expected StorageCapacity to remain nil, got: %+v", outStorageCapacity)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultVolumeBindingMode(t *testing.T) {
|
||||
class := &storagev1.StorageClass{}
|
||||
|
||||
|
@ -49,7 +49,7 @@ func SetDefaults_CSIDriver(obj *storagev1beta1.CSIDriver) {
|
||||
obj.Spec.PodInfoOnMount = new(bool)
|
||||
*(obj.Spec.PodInfoOnMount) = false
|
||||
}
|
||||
if obj.Spec.StorageCapacity == nil && utilfeature.DefaultFeatureGate.Enabled(features.CSIStorageCapacity) {
|
||||
if obj.Spec.StorageCapacity == nil {
|
||||
obj.Spec.StorageCapacity = new(bool)
|
||||
*(obj.Spec.StorageCapacity) = false
|
||||
}
|
||||
|
@ -87,7 +87,6 @@ func TestSetDefaultAttachRequired(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSetDefaultStorageCapacityEnabled(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIStorageCapacity, true)()
|
||||
driver := &storagev1beta1.CSIDriver{}
|
||||
|
||||
// field should be defaulted
|
||||
@ -101,18 +100,6 @@ func TestSetDefaultStorageCapacityEnabled(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultStorageCapacityDisabled(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIStorageCapacity, false)()
|
||||
driver := &storagev1beta1.CSIDriver{}
|
||||
|
||||
// field should not be defaulted
|
||||
output := roundTrip(t, runtime.Object(driver)).(*storagev1beta1.CSIDriver)
|
||||
outStorageCapacity := output.Spec.StorageCapacity
|
||||
if outStorageCapacity != nil {
|
||||
t.Errorf("Expected StorageCapacity to remain nil, got: %+v", outStorageCapacity)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultVolumeLifecycleModesEnabled(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
|
||||
driver := &storagev1beta1.CSIDriver{}
|
||||
|
@ -469,7 +469,7 @@ func validatePodInfoOnMount(podInfoOnMount *bool, fldPath *field.Path) field.Err
|
||||
// validateStorageCapacity tests if storageCapacity is set for CSIDriver.
|
||||
func validateStorageCapacity(storageCapacity *bool, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if storageCapacity == nil && utilfeature.DefaultFeatureGate.Enabled(features.CSIStorageCapacity) {
|
||||
if storageCapacity == nil {
|
||||
allErrs = append(allErrs, field.Required(fldPath, ""))
|
||||
}
|
||||
|
||||
|
@ -2093,9 +2093,7 @@ func TestCSIDriverValidationUpdate(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCSIDriverStorageCapacityEnablement(t *testing.T) {
|
||||
run := func(t *testing.T, enabled, withField bool) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIStorageCapacity, enabled)()
|
||||
|
||||
run := func(t *testing.T, withField bool) {
|
||||
driverName := "test-driver"
|
||||
attachRequired := true
|
||||
podInfoOnMount := true
|
||||
@ -2113,7 +2111,7 @@ func TestCSIDriverStorageCapacityEnablement(t *testing.T) {
|
||||
csiDriver.Spec.StorageCapacity = &storageCapacity
|
||||
}
|
||||
errs := ValidateCSIDriver(&csiDriver)
|
||||
success := !enabled || withField
|
||||
success := withField
|
||||
if success && len(errs) != 0 {
|
||||
t.Errorf("expected success, got: %v", errs)
|
||||
}
|
||||
@ -2123,13 +2121,9 @@ func TestCSIDriverStorageCapacityEnablement(t *testing.T) {
|
||||
}
|
||||
|
||||
yesNo := []bool{true, false}
|
||||
for _, enabled := range yesNo {
|
||||
t.Run(fmt.Sprintf("CSIStorageCapacity=%v", enabled), func(t *testing.T) {
|
||||
for _, withField := range yesNo {
|
||||
t.Run(fmt.Sprintf("with-field=%v", withField), func(t *testing.T) {
|
||||
run(t, enabled, withField)
|
||||
})
|
||||
}
|
||||
run(t, withField)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -157,6 +157,7 @@ const (
|
||||
// owner: @pohly
|
||||
// alpha: v1.19
|
||||
// beta: v1.21
|
||||
// GA: v1.24
|
||||
//
|
||||
// Enables tracking of available storage capacity that CSI drivers provide.
|
||||
CSIStorageCapacity featuregate.Feature = "CSIStorageCapacity"
|
||||
@ -879,7 +880,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
|
||||
CSIMigrationPortworx: {Default: false, PreRelease: featuregate.Alpha}, // Off by default (requires Portworx CSI driver)
|
||||
InTreePluginPortworxUnregister: {Default: false, PreRelease: featuregate.Alpha},
|
||||
CSIInlineVolume: {Default: true, PreRelease: featuregate.Beta},
|
||||
CSIStorageCapacity: {Default: true, PreRelease: featuregate.Beta},
|
||||
CSIStorageCapacity: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.26
|
||||
CSIServiceAccountToken: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.23
|
||||
GenericEphemeralVolume: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.25
|
||||
CSIVolumeFSGroupPolicy: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.25
|
||||
|
@ -47,7 +47,6 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/duration"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/client-go/util/certificate/csr"
|
||||
"k8s.io/kubernetes/pkg/apis/admissionregistration"
|
||||
"k8s.io/kubernetes/pkg/apis/apiserverinternal"
|
||||
@ -68,7 +67,6 @@ import (
|
||||
"k8s.io/kubernetes/pkg/apis/scheduling"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
storageutil "k8s.io/kubernetes/pkg/apis/storage/util"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/printers"
|
||||
"k8s.io/kubernetes/pkg/util/node"
|
||||
)
|
||||
@ -516,11 +514,7 @@ func AddHandlers(h printers.PrintHandler) {
|
||||
{Name: "Name", Type: "string", Format: "name", Description: metav1.ObjectMeta{}.SwaggerDoc()["name"]},
|
||||
{Name: "AttachRequired", Type: "boolean", Description: storagev1.CSIDriverSpec{}.SwaggerDoc()["attachRequired"]},
|
||||
{Name: "PodInfoOnMount", Type: "boolean", Description: storagev1.CSIDriverSpec{}.SwaggerDoc()["podInfoOnMount"]},
|
||||
}
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.CSIStorageCapacity) {
|
||||
csiDriverColumnDefinitions = append(csiDriverColumnDefinitions, metav1.TableColumnDefinition{
|
||||
Name: "StorageCapacity", Type: "boolean", Description: storagev1.CSIDriverSpec{}.SwaggerDoc()["storageCapacity"],
|
||||
})
|
||||
{Name: "StorageCapacity", Type: "boolean", Description: storagev1.CSIDriverSpec{}.SwaggerDoc()["storageCapacity"]},
|
||||
}
|
||||
csiDriverColumnDefinitions = append(csiDriverColumnDefinitions, []metav1.TableColumnDefinition{
|
||||
{Name: "TokenRequests", Type: "string", Description: storagev1.CSIDriverSpec{}.SwaggerDoc()["tokenRequests"]},
|
||||
@ -1413,13 +1407,11 @@ func printCSIDriver(obj *storage.CSIDriver, options printers.GenerateOptions) ([
|
||||
}
|
||||
|
||||
row.Cells = append(row.Cells, obj.Name, attachRequired, podInfoOnMount)
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.CSIStorageCapacity) {
|
||||
storageCapacity := false
|
||||
if obj.Spec.StorageCapacity != nil {
|
||||
storageCapacity = *obj.Spec.StorageCapacity
|
||||
}
|
||||
row.Cells = append(row.Cells, storageCapacity)
|
||||
}
|
||||
|
||||
tokenRequests := "<unset>"
|
||||
if obj.Spec.TokenRequests != nil {
|
||||
|
@ -47,9 +47,6 @@ func (csiDriverStrategy) NamespaceScoped() bool {
|
||||
// PrepareForCreate clears the fields for which the corresponding feature is disabled.
|
||||
func (csiDriverStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
|
||||
csiDriver := obj.(*storage.CSIDriver)
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.CSIStorageCapacity) {
|
||||
csiDriver.Spec.StorageCapacity = nil
|
||||
}
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
|
||||
csiDriver.Spec.VolumeLifecycleModes = nil
|
||||
}
|
||||
@ -84,10 +81,6 @@ func (csiDriverStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.
|
||||
newCSIDriver := obj.(*storage.CSIDriver)
|
||||
oldCSIDriver := old.(*storage.CSIDriver)
|
||||
|
||||
if oldCSIDriver.Spec.StorageCapacity == nil &&
|
||||
!utilfeature.DefaultFeatureGate.Enabled(features.CSIStorageCapacity) {
|
||||
newCSIDriver.Spec.StorageCapacity = nil
|
||||
}
|
||||
if oldCSIDriver.Spec.VolumeLifecycleModes == nil &&
|
||||
!utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
|
||||
newCSIDriver.Spec.VolumeLifecycleModes = nil
|
||||
|
@ -93,7 +93,6 @@ func TestCSIDriverPrepareForCreate(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
withCapacity bool
|
||||
withInline bool
|
||||
}{
|
||||
{
|
||||
@ -104,19 +103,10 @@ func TestCSIDriverPrepareForCreate(t *testing.T) {
|
||||
name: "inline disabled",
|
||||
withInline: false,
|
||||
},
|
||||
{
|
||||
name: "capacity enabled",
|
||||
withCapacity: true,
|
||||
},
|
||||
{
|
||||
name: "capacity disabled",
|
||||
withCapacity: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIStorageCapacity, test.withCapacity)()
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, test.withInline)()
|
||||
|
||||
csiDriver := &storage.CSIDriver{
|
||||
@ -139,15 +129,9 @@ func TestCSIDriverPrepareForCreate(t *testing.T) {
|
||||
if len(errs) != 0 {
|
||||
t.Errorf("unexpected validating errors: %v", errs)
|
||||
}
|
||||
if test.withCapacity {
|
||||
if csiDriver.Spec.StorageCapacity == nil || *csiDriver.Spec.StorageCapacity != storageCapacity {
|
||||
t.Errorf("StorageCapacity modified: %v", csiDriver.Spec.StorageCapacity)
|
||||
}
|
||||
} else {
|
||||
if csiDriver.Spec.StorageCapacity != nil {
|
||||
t.Errorf("StorageCapacity not stripped: %v", csiDriver.Spec.StorageCapacity)
|
||||
}
|
||||
}
|
||||
if test.withInline {
|
||||
if len(csiDriver.Spec.VolumeLifecycleModes) != 1 {
|
||||
t.Errorf("VolumeLifecycleModes modified: %v", csiDriver.Spec)
|
||||
@ -233,7 +217,6 @@ func TestCSIDriverPrepareForUpdate(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
old, update *storage.CSIDriver
|
||||
csiStorageCapacityEnabled bool
|
||||
csiInlineVolumeEnabled bool
|
||||
wantCapacity *bool
|
||||
wantModes []storage.VolumeLifecycleMode
|
||||
@ -243,19 +226,12 @@ func TestCSIDriverPrepareForUpdate(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
name: "capacity feature enabled, before: none, update: enabled",
|
||||
csiStorageCapacityEnabled: true,
|
||||
old: driverWithNothing,
|
||||
update: driverWithCapacityEnabled,
|
||||
wantCapacity: &enabled,
|
||||
},
|
||||
{
|
||||
name: "capacity feature disabled, before: none, update: disabled",
|
||||
old: driverWithNothing,
|
||||
update: driverWithCapacityDisabled,
|
||||
wantCapacity: nil,
|
||||
},
|
||||
{
|
||||
name: "capacity feature disabled, before: enabled, update: disabled",
|
||||
name: "capacity feature enabled, before: enabled, update: disabled",
|
||||
old: driverWithCapacityEnabled,
|
||||
update: driverWithCapacityDisabled,
|
||||
wantCapacity: &disabled,
|
||||
@ -291,7 +267,6 @@ func TestCSIDriverPrepareForUpdate(t *testing.T) {
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIStorageCapacity, test.csiStorageCapacityEnabled)()
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, test.csiInlineVolumeEnabled)()
|
||||
|
||||
csiDriver := test.update.DeepCopy()
|
||||
|
@ -24,10 +24,7 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
"k8s.io/kubernetes/pkg/apis/storage"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
// getValidCSIStorageCapacity returns a fully-populated CSIStorageCapacity.
|
||||
@ -159,8 +156,6 @@ func TestCSIStorageCapacityValidation(t *testing.T) {
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIStorageCapacity, true)()
|
||||
|
||||
oldCapacity := test.old.DeepCopy()
|
||||
Strategy.PrepareForCreate(ctx, oldCapacity)
|
||||
errs := Strategy.Validate(ctx, oldCapacity)
|
||||
|
@ -25,6 +25,5 @@ type Features struct {
|
||||
EnablePodOverhead bool
|
||||
EnableReadWriteOncePod bool
|
||||
EnableVolumeCapacityPriority bool
|
||||
EnableCSIStorageCapacity bool
|
||||
EnableMinDomainsInPodTopologySpread bool
|
||||
}
|
||||
|
@ -49,7 +49,6 @@ func NewInTreeRegistry() runtime.Registry {
|
||||
EnablePodOverhead: feature.DefaultFeatureGate.Enabled(features.PodOverhead),
|
||||
EnableReadWriteOncePod: feature.DefaultFeatureGate.Enabled(features.ReadWriteOncePod),
|
||||
EnableVolumeCapacityPriority: feature.DefaultFeatureGate.Enabled(features.VolumeCapacityPriority),
|
||||
EnableCSIStorageCapacity: feature.DefaultFeatureGate.Enabled(features.CSIStorageCapacity),
|
||||
EnableMinDomainsInPodTopologySpread: feature.DefaultFeatureGate.Enabled(features.MinDomainsInPodTopologySpread),
|
||||
}
|
||||
|
||||
|
@ -209,7 +209,6 @@ type volumeBinder struct {
|
||||
|
||||
translator InTreeToCSITranslator
|
||||
|
||||
capacityCheckEnabled bool
|
||||
csiDriverLister storagelisters.CSIDriverLister
|
||||
csiStorageCapacityLister storagelistersv1beta1.CSIStorageCapacityLister
|
||||
}
|
||||
@ -224,7 +223,7 @@ type CapacityCheck struct {
|
||||
|
||||
// NewVolumeBinder sets up all the caches needed for the scheduler to make volume binding decisions.
|
||||
//
|
||||
// capacityCheck determines whether storage capacity is checked (CSIStorageCapacity feature).
|
||||
// capacityCheck determines how storage capacity is checked (CSIStorageCapacity feature).
|
||||
func NewVolumeBinder(
|
||||
kubeClient clientset.Interface,
|
||||
podInformer coreinformers.PodInformer,
|
||||
@ -233,7 +232,7 @@ func NewVolumeBinder(
|
||||
pvcInformer coreinformers.PersistentVolumeClaimInformer,
|
||||
pvInformer coreinformers.PersistentVolumeInformer,
|
||||
storageClassInformer storageinformers.StorageClassInformer,
|
||||
capacityCheck *CapacityCheck,
|
||||
capacityCheck CapacityCheck,
|
||||
bindTimeout time.Duration) SchedulerVolumeBinder {
|
||||
b := &volumeBinder{
|
||||
kubeClient: kubeClient,
|
||||
@ -247,11 +246,8 @@ func NewVolumeBinder(
|
||||
translator: csitrans.New(),
|
||||
}
|
||||
|
||||
if capacityCheck != nil {
|
||||
b.capacityCheckEnabled = true
|
||||
b.csiDriverLister = capacityCheck.CSIDriverInformer.Lister()
|
||||
b.csiStorageCapacityLister = capacityCheck.CSIStorageCapacityInformer.Lister()
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
@ -922,12 +918,6 @@ func (b *volumeBinder) revertAssumedPVCs(claims []*v1.PersistentVolumeClaim) {
|
||||
// hasEnoughCapacity checks whether the provisioner has enough capacity left for a new volume of the given size
|
||||
// that is available from the node.
|
||||
func (b *volumeBinder) hasEnoughCapacity(provisioner string, claim *v1.PersistentVolumeClaim, storageClass *storagev1.StorageClass, node *v1.Node) (bool, error) {
|
||||
// This is an optional feature. If disabled, we assume that
|
||||
// there is enough storage.
|
||||
if !b.capacityCheckEnabled {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
quantity, ok := claim.Spec.Resources.Requests[v1.ResourceStorage]
|
||||
if !ok {
|
||||
// No capacity to check for.
|
||||
|
@ -144,7 +144,7 @@ type testEnv struct {
|
||||
internalCSIStorageCapacityInformer storageinformersv1beta1.CSIStorageCapacityInformer
|
||||
}
|
||||
|
||||
func newTestBinder(t *testing.T, stopCh <-chan struct{}, csiStorageCapacity ...bool) *testEnv {
|
||||
func newTestBinder(t *testing.T, stopCh <-chan struct{}) *testEnv {
|
||||
client := &fake.Clientset{}
|
||||
reactor := pvtesting.NewVolumeReactor(client, nil, nil, nil)
|
||||
// TODO refactor all tests to use real watch mechanism, see #72327
|
||||
@ -166,13 +166,10 @@ func newTestBinder(t *testing.T, stopCh <-chan struct{}, csiStorageCapacity ...b
|
||||
classInformer := informerFactory.Storage().V1().StorageClasses()
|
||||
csiDriverInformer := informerFactory.Storage().V1().CSIDrivers()
|
||||
csiStorageCapacityInformer := informerFactory.Storage().V1beta1().CSIStorageCapacities()
|
||||
var capacityCheck *CapacityCheck
|
||||
if len(csiStorageCapacity) > 0 && csiStorageCapacity[0] {
|
||||
capacityCheck = &CapacityCheck{
|
||||
capacityCheck := CapacityCheck{
|
||||
CSIDriverInformer: csiDriverInformer,
|
||||
CSIStorageCapacityInformer: csiStorageCapacityInformer,
|
||||
}
|
||||
}
|
||||
binder := NewVolumeBinder(
|
||||
client,
|
||||
podInformer,
|
||||
@ -970,12 +967,12 @@ func TestFindPodVolumesWithoutProvisioning(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
run := func(t *testing.T, scenario scenarioType, csiStorageCapacity bool, csiDriver *storagev1.CSIDriver) {
|
||||
run := func(t *testing.T, scenario scenarioType, csiDriver *storagev1.CSIDriver) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
// Setup
|
||||
testEnv := newTestBinder(t, ctx.Done(), csiStorageCapacity)
|
||||
testEnv := newTestBinder(t, ctx.Done())
|
||||
testEnv.initVolumes(scenario.pvs, scenario.pvs)
|
||||
if csiDriver != nil {
|
||||
testEnv.addCSIDriver(csiDriver)
|
||||
@ -1009,8 +1006,6 @@ func TestFindPodVolumesWithoutProvisioning(t *testing.T) {
|
||||
testEnv.validatePodCache(t, testNode.Name, scenario.pod, podVolumes, scenario.expectedBindings, nil)
|
||||
}
|
||||
|
||||
for prefix, csiStorageCapacity := range map[string]bool{"with": true, "without": false} {
|
||||
t.Run(fmt.Sprintf("%s CSIStorageCapacity", prefix), func(t *testing.T) {
|
||||
for description, csiDriver := range map[string]*storagev1.CSIDriver{
|
||||
"no CSIDriver": nil,
|
||||
"CSIDriver with capacity tracking": makeCSIDriver(provisioner, true),
|
||||
@ -1018,9 +1013,7 @@ func TestFindPodVolumesWithoutProvisioning(t *testing.T) {
|
||||
} {
|
||||
t.Run(description, func(t *testing.T) {
|
||||
for name, scenario := range scenarios {
|
||||
t.Run(name, func(t *testing.T) { run(t, scenario, csiStorageCapacity, csiDriver) })
|
||||
}
|
||||
})
|
||||
t.Run(name, func(t *testing.T) { run(t, scenario, csiDriver) })
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -1101,12 +1094,12 @@ func TestFindPodVolumesWithProvisioning(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
run := func(t *testing.T, scenario scenarioType, csiStorageCapacity bool, csiDriver *storagev1.CSIDriver) {
|
||||
run := func(t *testing.T, scenario scenarioType, csiDriver *storagev1.CSIDriver) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
// Setup
|
||||
testEnv := newTestBinder(t, ctx.Done(), csiStorageCapacity)
|
||||
testEnv := newTestBinder(t, ctx.Done())
|
||||
testEnv.initVolumes(scenario.pvs, scenario.pvs)
|
||||
if csiDriver != nil {
|
||||
testEnv.addCSIDriver(csiDriver)
|
||||
@ -1138,7 +1131,7 @@ func TestFindPodVolumesWithProvisioning(t *testing.T) {
|
||||
}
|
||||
expectedReasons := scenario.reasons
|
||||
expectedProvisions := scenario.expectedProvisions
|
||||
if scenario.needsCapacity && csiStorageCapacity &&
|
||||
if scenario.needsCapacity &&
|
||||
csiDriver != nil && csiDriver.Spec.StorageCapacity != nil && *csiDriver.Spec.StorageCapacity {
|
||||
// Without CSIStorageCapacity objects, provisioning is blocked.
|
||||
expectedReasons = append(expectedReasons, ErrReasonNotEnoughSpace)
|
||||
@ -1148,8 +1141,6 @@ func TestFindPodVolumesWithProvisioning(t *testing.T) {
|
||||
testEnv.validatePodCache(t, testNode.Name, scenario.pod, podVolumes, scenario.expectedBindings, expectedProvisions)
|
||||
}
|
||||
|
||||
for prefix, csiStorageCapacity := range map[string]bool{"with": true, "without": false} {
|
||||
t.Run(fmt.Sprintf("%s CSIStorageCapacity", prefix), func(t *testing.T) {
|
||||
for description, csiDriver := range map[string]*storagev1.CSIDriver{
|
||||
"no CSIDriver": nil,
|
||||
"CSIDriver with capacity tracking": makeCSIDriver(provisioner, true),
|
||||
@ -1157,9 +1148,7 @@ func TestFindPodVolumesWithProvisioning(t *testing.T) {
|
||||
} {
|
||||
t.Run(description, func(t *testing.T) {
|
||||
for name, scenario := range scenarios {
|
||||
t.Run(name, func(t *testing.T) { run(t, scenario, csiStorageCapacity, csiDriver) })
|
||||
}
|
||||
})
|
||||
t.Run(name, func(t *testing.T) { run(t, scenario, csiDriver) })
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -2261,13 +2250,12 @@ func TestCapacity(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
run := func(t *testing.T, scenario scenarioType, featureEnabled, optIn bool) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIStorageCapacity, featureEnabled)()
|
||||
run := func(t *testing.T, scenario scenarioType, optIn bool) {
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
// Setup: the driver has the feature enabled, but the scheduler might not.
|
||||
testEnv := newTestBinder(t, ctx.Done(), featureEnabled)
|
||||
testEnv := newTestBinder(t, ctx.Done())
|
||||
testEnv.addCSIDriver(makeCSIDriver(provisioner, optIn))
|
||||
testEnv.addCSIStorageCapacities(scenario.capacities)
|
||||
|
||||
@ -2286,7 +2274,7 @@ func TestCapacity(t *testing.T) {
|
||||
// Validate
|
||||
shouldFail := scenario.shouldFail
|
||||
expectedReasons := scenario.reasons
|
||||
if !featureEnabled || !optIn {
|
||||
if !optIn {
|
||||
shouldFail = false
|
||||
expectedReasons = nil
|
||||
}
|
||||
@ -2305,16 +2293,11 @@ func TestCapacity(t *testing.T) {
|
||||
}
|
||||
|
||||
yesNo := []bool{true, false}
|
||||
for _, featureEnabled := range yesNo {
|
||||
name := fmt.Sprintf("CSIStorageCapacity=%v", featureEnabled)
|
||||
t.Run(name, func(t *testing.T) {
|
||||
for _, optIn := range yesNo {
|
||||
name := fmt.Sprintf("CSIDriver.StorageCapacity=%v", optIn)
|
||||
t.Run(name, func(t *testing.T) {
|
||||
for name, scenario := range scenarios {
|
||||
t.Run(name, func(t *testing.T) { run(t, scenario, featureEnabled, optIn) })
|
||||
}
|
||||
})
|
||||
t.Run(name, func(t *testing.T) { run(t, scenario, optIn) })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -107,14 +107,10 @@ func (pl *VolumeBinding) EventsToRegister() []framework.ClusterEvent {
|
||||
{Resource: framework.Node, ActionType: framework.Add | framework.UpdateNodeLabel},
|
||||
// We rely on CSI node to translate in-tree PV to CSI.
|
||||
{Resource: framework.CSINode, ActionType: framework.Add | framework.Update},
|
||||
}
|
||||
if pl.fts.EnableCSIStorageCapacity {
|
||||
// When CSIStorageCapacity is enabled, pods may become schedulable
|
||||
// on CSI driver & storage capacity changes.
|
||||
events = append(events, []framework.ClusterEvent{
|
||||
{Resource: framework.CSIDriver, ActionType: framework.Add | framework.Update},
|
||||
{Resource: framework.CSIStorageCapacity, ActionType: framework.Add | framework.Update},
|
||||
}...)
|
||||
}
|
||||
return events
|
||||
}
|
||||
@ -379,13 +375,10 @@ func New(plArgs runtime.Object, fh framework.Handle, fts feature.Features) (fram
|
||||
pvInformer := fh.SharedInformerFactory().Core().V1().PersistentVolumes()
|
||||
storageClassInformer := fh.SharedInformerFactory().Storage().V1().StorageClasses()
|
||||
csiNodeInformer := fh.SharedInformerFactory().Storage().V1().CSINodes()
|
||||
var capacityCheck *CapacityCheck
|
||||
if fts.EnableCSIStorageCapacity {
|
||||
capacityCheck = &CapacityCheck{
|
||||
capacityCheck := CapacityCheck{
|
||||
CSIDriverInformer: fh.SharedInformerFactory().Storage().V1().CSIDrivers(),
|
||||
CSIStorageCapacityInformer: fh.SharedInformerFactory().Storage().V1beta1().CSIStorageCapacities(),
|
||||
}
|
||||
}
|
||||
binder := NewVolumeBinder(fh.ClientSet(), podInformer, nodeInformer, csiNodeInformer, pvcInformer, pvInformer, storageClassInformer, capacityCheck, time.Duration(args.BindTimeoutSeconds)*time.Second)
|
||||
|
||||
// build score function
|
||||
|
@ -551,12 +551,8 @@ func ClusterRoles() []rbacv1.ClusterRole {
|
||||
rbacv1helpers.NewRule(Read...).Groups(storageGroup).Resources("csinodes").RuleOrDie(),
|
||||
// Needed for namespaceSelector feature in pod affinity
|
||||
rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("namespaces").RuleOrDie(),
|
||||
}
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.CSIStorageCapacity) {
|
||||
kubeSchedulerRules = append(kubeSchedulerRules,
|
||||
rbacv1helpers.NewRule(Read...).Groups(storageGroup).Resources("csidrivers").RuleOrDie(),
|
||||
rbacv1helpers.NewRule(Read...).Groups(storageGroup).Resources("csistoragecapacities").RuleOrDie(),
|
||||
)
|
||||
}
|
||||
roles = append(roles, rbacv1.ClusterRole{
|
||||
// a role to use for the kube-scheduler
|
||||
|
@ -364,11 +364,7 @@ type CSIDriverSpec struct {
|
||||
//
|
||||
// This field was immutable in Kubernetes <= 1.22 and now is mutable.
|
||||
//
|
||||
// This is a beta field and only available when the CSIStorageCapacity
|
||||
// feature is enabled. The default is false.
|
||||
//
|
||||
// +optional
|
||||
// +featureGate=CSIStorageCapacity
|
||||
StorageCapacity *bool `json:"storageCapacity,omitempty" protobuf:"bytes,4,opt,name=storageCapacity"`
|
||||
|
||||
// Defines if the underlying volume supports changing ownership and
|
||||
|
@ -30,16 +30,13 @@ import (
|
||||
metav1beta1 "k8s.io/apimachinery/pkg/apis/meta/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||
diskcached "k8s.io/client-go/discovery/cached/disk"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
"k8s.io/gengo/examples/set-gen/sets"
|
||||
"k8s.io/kubectl/pkg/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/printers"
|
||||
printersinternal "k8s.io/kubernetes/pkg/printers/internalversion"
|
||||
"k8s.io/kubernetes/test/integration/framework"
|
||||
@ -123,8 +120,6 @@ var missingHanlders = sets.NewString(
|
||||
)
|
||||
|
||||
func TestServerSidePrint(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIStorageCapacity, true)()
|
||||
|
||||
s, _, closeFn := setupWithResources(t,
|
||||
// additional groupversions needed for the test to run
|
||||
[]schema.GroupVersion{
|
||||
|
@ -29,14 +29,12 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/uuid"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apiserver/pkg/admission"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/client-go/informers"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/events"
|
||||
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
||||
"k8s.io/kubernetes/pkg/controlplane"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/scheduler"
|
||||
"k8s.io/kubernetes/pkg/scheduler/profile"
|
||||
"k8s.io/kubernetes/test/integration/framework"
|
||||
@ -73,12 +71,6 @@ func initTestAPIServer(t *testing.T, nsPrefix string, admission admission.Interf
|
||||
|
||||
controlPlaneConfig := framework.NewIntegrationTestControlPlaneConfig()
|
||||
resourceConfig := controlplane.DefaultAPIResourceConfigSource()
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.CSIStorageCapacity) {
|
||||
resourceConfig.EnableVersions(schema.GroupVersion{
|
||||
Group: "storage.k8s.io",
|
||||
Version: "v1alpha1",
|
||||
})
|
||||
}
|
||||
controlPlaneConfig.ExtraConfig.APIResourceConfigSource = resourceConfig
|
||||
|
||||
if admission != nil {
|
||||
|
@ -37,13 +37,10 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/rand"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/client-go/informers"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
"k8s.io/kubernetes/pkg/controller/volume/persistentvolume"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/scheduler/framework/plugins/nodevolumelimits"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
volumetest "k8s.io/kubernetes/pkg/volume/testing"
|
||||
@ -704,13 +701,6 @@ func TestPVAffinityConflict(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestVolumeProvision(t *testing.T) {
|
||||
t.Run("with CSIStorageCapacity", func(t *testing.T) { testVolumeProvision(t, true) })
|
||||
t.Run("without CSIStorageCapacity", func(t *testing.T) { testVolumeProvision(t, false) })
|
||||
}
|
||||
|
||||
func testVolumeProvision(t *testing.T, storageCapacity bool) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIStorageCapacity, storageCapacity)()
|
||||
|
||||
config := setupCluster(t, "volume-scheduling", 1, 0, 0)
|
||||
defer config.teardown()
|
||||
|
||||
@ -859,8 +849,6 @@ func testVolumeProvision(t *testing.T, storageCapacity bool) {
|
||||
|
||||
// TestCapacity covers different scenarios involving CSIStorageCapacity objects.
|
||||
func TestCapacity(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIStorageCapacity, true)()
|
||||
|
||||
config := setupCluster(t, "volume-scheduling", 1, 0, 0)
|
||||
defer config.teardown()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user