mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-30 15:05:27 +00:00
CSIStorageCapacity: CSIDriver.Spec.StorageCapacity field
This is needed to inform the Kubernetes pod scheduler whether it has to check CSIStorageCapacity objects for available capacity.
This commit is contained in:
parent
22aeb81e84
commit
1089954fa6
@ -78,6 +78,10 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
|
||||
obj.Spec.PodInfoOnMount = new(bool)
|
||||
*(obj.Spec.PodInfoOnMount) = false
|
||||
}
|
||||
if obj.Spec.StorageCapacity == nil {
|
||||
obj.Spec.StorageCapacity = new(bool)
|
||||
*(obj.Spec.StorageCapacity) = false
|
||||
}
|
||||
if len(obj.Spec.VolumeLifecycleModes) == 0 {
|
||||
obj.Spec.VolumeLifecycleModes = []storage.VolumeLifecycleMode{
|
||||
storage.VolumeLifecyclePersistent,
|
||||
|
@ -309,6 +309,26 @@ type CSIDriverSpec struct {
|
||||
// more modes may be added in the future.
|
||||
// +optional
|
||||
VolumeLifecycleModes []VolumeLifecycleMode
|
||||
|
||||
// If set to true, storageCapacity indicates that the CSI
|
||||
// volume driver wants pod scheduling to consider the storage
|
||||
// capacity that the driver deployment will report by creating
|
||||
// CSIStorageCapacity objects with capacity information.
|
||||
//
|
||||
// The check can be enabled immediately when deploying a driver.
|
||||
// In that case, provisioning new volumes with late binding
|
||||
// will pause until the driver deployment has published
|
||||
// some suitable CSIStorageCapacity object.
|
||||
//
|
||||
// Alternatively, the driver can be deployed with the field
|
||||
// unset or false and it can be flipped later when storage
|
||||
// capacity information has been published.
|
||||
//
|
||||
// This is an alpha field and only available when the CSIStorageCapacity
|
||||
// feature is enabled. The default is false.
|
||||
//
|
||||
// +optional
|
||||
StorageCapacity *bool
|
||||
}
|
||||
|
||||
// VolumeLifecycleMode specifies how a CSI volume is used in Kubernetes.
|
||||
|
@ -49,6 +49,10 @@ 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) {
|
||||
obj.Spec.StorageCapacity = new(bool)
|
||||
*(obj.Spec.StorageCapacity) = false
|
||||
}
|
||||
if len(obj.Spec.VolumeLifecycleModes) == 0 && utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
|
||||
obj.Spec.VolumeLifecycleModes = append(obj.Spec.VolumeLifecycleModes, storagev1.VolumeLifecyclePersistent)
|
||||
}
|
||||
|
@ -22,8 +22,11 @@ import (
|
||||
|
||||
storagev1 "k8s.io/api/storage/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/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 {
|
||||
@ -47,6 +50,33 @@ func roundTrip(t *testing.T, obj runtime.Object) runtime.Object {
|
||||
return obj3
|
||||
}
|
||||
|
||||
func TestSetDefaultStorageCapacityEnabled(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIStorageCapacity, true)()
|
||||
driver := &storagev1.CSIDriver{}
|
||||
|
||||
// field should be defaulted
|
||||
defaultStorageCapacity := false
|
||||
output := roundTrip(t, runtime.Object(driver)).(*storagev1.CSIDriver)
|
||||
outStorageCapacity := output.Spec.StorageCapacity
|
||||
if outStorageCapacity == nil {
|
||||
t.Errorf("Expected StorageCapacity to be defaulted to: %+v, got: nil", defaultStorageCapacity)
|
||||
} else if *outStorageCapacity != defaultStorageCapacity {
|
||||
t.Errorf("Expected StorageCapacity to be defaulted to: %+v, got: %+v", defaultStorageCapacity, outStorageCapacity)
|
||||
}
|
||||
}
|
||||
|
||||
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,6 +49,10 @@ 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) {
|
||||
obj.Spec.StorageCapacity = new(bool)
|
||||
*(obj.Spec.StorageCapacity) = false
|
||||
}
|
||||
if len(obj.Spec.VolumeLifecycleModes) == 0 && utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
|
||||
obj.Spec.VolumeLifecycleModes = append(obj.Spec.VolumeLifecycleModes, storagev1beta1.VolumeLifecyclePersistent)
|
||||
}
|
||||
|
@ -85,6 +85,33 @@ 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
|
||||
defaultStorageCapacity := false
|
||||
output := roundTrip(t, runtime.Object(driver)).(*storagev1beta1.CSIDriver)
|
||||
outStorageCapacity := output.Spec.StorageCapacity
|
||||
if outStorageCapacity == nil {
|
||||
t.Errorf("Expected StorageCapacity to be defaulted to: %+v, got: nil", defaultStorageCapacity)
|
||||
} else if *outStorageCapacity != defaultStorageCapacity {
|
||||
t.Errorf("Expected StorageCapacity to be defaulted to: %+v, got: %+v", defaultStorageCapacity, outStorageCapacity)
|
||||
}
|
||||
}
|
||||
|
||||
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{}
|
||||
|
@ -419,6 +419,7 @@ func validateCSIDriverSpec(
|
||||
allErrs := field.ErrorList{}
|
||||
allErrs = append(allErrs, validateAttachRequired(spec.AttachRequired, fldPath.Child("attachedRequired"))...)
|
||||
allErrs = append(allErrs, validatePodInfoOnMount(spec.PodInfoOnMount, fldPath.Child("podInfoOnMount"))...)
|
||||
allErrs = append(allErrs, validateStorageCapacity(spec.StorageCapacity, fldPath.Child("storageCapacity"))...)
|
||||
allErrs = append(allErrs, validateVolumeLifecycleModes(spec.VolumeLifecycleModes, fldPath.Child("volumeLifecycleModes"))...)
|
||||
return allErrs
|
||||
}
|
||||
@ -443,6 +444,16 @@ func validatePodInfoOnMount(podInfoOnMount *bool, fldPath *field.Path) field.Err
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// 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) {
|
||||
allErrs = append(allErrs, field.Required(fldPath, ""))
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// validateVolumeLifecycleModes tests if mode has one of the allowed values.
|
||||
func validateVolumeLifecycleModes(modes []storage.VolumeLifecycleMode, fldPath *field.Path) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
@ -46,6 +46,7 @@ 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/kubernetes/pkg/apis/admissionregistration"
|
||||
"k8s.io/kubernetes/pkg/apis/apps"
|
||||
"k8s.io/kubernetes/pkg/apis/autoscaling"
|
||||
@ -64,6 +65,7 @@ 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"
|
||||
)
|
||||
@ -510,9 +512,16 @@ 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"],
|
||||
})
|
||||
}
|
||||
csiDriverColumnDefinitions = append(csiDriverColumnDefinitions, []metav1.TableColumnDefinition{
|
||||
{Name: "Modes", Type: "string", Description: storagev1.CSIDriverSpec{}.SwaggerDoc()["volumeLifecycleModes"]},
|
||||
{Name: "Age", Type: "string", Description: metav1.ObjectMeta{}.SwaggerDoc()["creationTimestamp"]},
|
||||
}
|
||||
}...)
|
||||
h.TableHandler(csiDriverColumnDefinitions, printCSIDriver)
|
||||
h.TableHandler(csiDriverColumnDefinitions, printCSIDriverList)
|
||||
|
||||
@ -1366,7 +1375,15 @@ func printCSIDriver(obj *storage.CSIDriver, options printers.GenerateOptions) ([
|
||||
modes = "<none>"
|
||||
}
|
||||
|
||||
row.Cells = append(row.Cells, obj.Name, attachRequired, podInfoOnMount, modes, translateTimestampSince(obj.CreationTimestamp))
|
||||
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)
|
||||
}
|
||||
row.Cells = append(row.Cells, modes, translateTimestampSince(obj.CreationTimestamp))
|
||||
return []metav1.TableRow{row}, nil
|
||||
}
|
||||
|
||||
|
@ -43,8 +43,12 @@ func (csiDriverStrategy) NamespaceScoped() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// PrepareForCreate clears the VolumeLifecycleModes field if the corresponding feature is disabled.
|
||||
// PrepareForCreate clears the fields for which the corresponding feature is disabled.
|
||||
func (csiDriverStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.CSIStorageCapacity) {
|
||||
csiDriver := obj.(*storage.CSIDriver)
|
||||
csiDriver.Spec.StorageCapacity = nil
|
||||
}
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
|
||||
csiDriver := obj.(*storage.CSIDriver)
|
||||
csiDriver.Spec.VolumeLifecycleModes = nil
|
||||
@ -68,10 +72,15 @@ func (csiDriverStrategy) AllowCreateOnUpdate() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// PrepareForUpdate clears the VolumeLifecycleModes field if the corresponding feature is disabled and
|
||||
// PrepareForUpdate clears the fields for which the corresponding feature is disabled and
|
||||
// existing object does not already have that field set. This allows the field to remain when
|
||||
// downgrading to a version that has the feature disabled.
|
||||
func (csiDriverStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
|
||||
if old.(*storage.CSIDriver).Spec.StorageCapacity == nil &&
|
||||
!utilfeature.DefaultFeatureGate.Enabled(features.CSIStorageCapacity) {
|
||||
newCSIDriver := obj.(*storage.CSIDriver)
|
||||
newCSIDriver.Spec.StorageCapacity = nil
|
||||
}
|
||||
if old.(*storage.CSIDriver).Spec.VolumeLifecycleModes == nil &&
|
||||
!utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
|
||||
newCSIDriver := obj.(*storage.CSIDriver)
|
||||
|
@ -30,15 +30,15 @@ import (
|
||||
)
|
||||
|
||||
func getValidCSIDriver(name string) *storage.CSIDriver {
|
||||
attachRequired := true
|
||||
podInfoOnMount := true
|
||||
enabled := true
|
||||
return &storage.CSIDriver{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
},
|
||||
Spec: storage.CSIDriverSpec{
|
||||
AttachRequired: &attachRequired,
|
||||
PodInfoOnMount: &podInfoOnMount,
|
||||
AttachRequired: &enabled,
|
||||
PodInfoOnMount: &enabled,
|
||||
StorageCapacity: &enabled,
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -87,22 +87,12 @@ func TestCSIDriverPrepareForCreate(t *testing.T) {
|
||||
|
||||
attachRequired := true
|
||||
podInfoOnMount := true
|
||||
csiDriver := &storage.CSIDriver{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "foo",
|
||||
},
|
||||
Spec: storage.CSIDriverSpec{
|
||||
AttachRequired: &attachRequired,
|
||||
PodInfoOnMount: &podInfoOnMount,
|
||||
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
|
||||
storage.VolumeLifecyclePersistent,
|
||||
},
|
||||
},
|
||||
}
|
||||
storageCapacity := true
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
withInline bool
|
||||
name string
|
||||
withCapacity bool
|
||||
withInline bool
|
||||
}{
|
||||
{
|
||||
name: "inline enabled",
|
||||
@ -112,17 +102,48 @@ 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{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "foo",
|
||||
},
|
||||
Spec: storage.CSIDriverSpec{
|
||||
AttachRequired: &attachRequired,
|
||||
PodInfoOnMount: &podInfoOnMount,
|
||||
StorageCapacity: &storageCapacity,
|
||||
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
|
||||
storage.VolumeLifecyclePersistent,
|
||||
},
|
||||
},
|
||||
}
|
||||
Strategy.PrepareForCreate(ctx, csiDriver)
|
||||
errs := Strategy.Validate(ctx, csiDriver)
|
||||
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)
|
||||
@ -178,15 +199,69 @@ func TestCSIDriverPrepareForUpdate(t *testing.T) {
|
||||
},
|
||||
},
|
||||
}
|
||||
enabled := true
|
||||
disabled := false
|
||||
driverWithoutCapacity := &storage.CSIDriver{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "foo",
|
||||
},
|
||||
}
|
||||
driverWithCapacityEnabled := &storage.CSIDriver{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "foo",
|
||||
},
|
||||
Spec: storage.CSIDriverSpec{
|
||||
StorageCapacity: &enabled,
|
||||
},
|
||||
}
|
||||
driverWithCapacityDisabled := &storage.CSIDriver{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "foo",
|
||||
},
|
||||
Spec: storage.CSIDriverSpec{
|
||||
StorageCapacity: &disabled,
|
||||
},
|
||||
}
|
||||
|
||||
var resultEmpty []storage.VolumeLifecycleMode
|
||||
resultPersistent := []storage.VolumeLifecycleMode{storage.VolumeLifecyclePersistent}
|
||||
resultEphemeral := []storage.VolumeLifecycleMode{storage.VolumeLifecycleEphemeral}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
old, update *storage.CSIDriver
|
||||
withInline, withoutInline []storage.VolumeLifecycleMode
|
||||
name string
|
||||
old, update *storage.CSIDriver
|
||||
withCapacity, withoutCapacity *bool
|
||||
withInline, withoutInline []storage.VolumeLifecycleMode
|
||||
}{
|
||||
{
|
||||
name: "before: no capacity, update: no capacity",
|
||||
old: driverWithoutCapacity,
|
||||
update: driverWithoutCapacity,
|
||||
withCapacity: nil,
|
||||
withoutCapacity: nil,
|
||||
},
|
||||
{
|
||||
name: "before: no capacity, update: enabled",
|
||||
old: driverWithoutCapacity,
|
||||
update: driverWithCapacityEnabled,
|
||||
withCapacity: &enabled,
|
||||
withoutCapacity: nil,
|
||||
},
|
||||
{
|
||||
name: "before: capacity enabled, update: disabled",
|
||||
old: driverWithCapacityEnabled,
|
||||
update: driverWithCapacityDisabled,
|
||||
withCapacity: &disabled,
|
||||
withoutCapacity: &disabled,
|
||||
},
|
||||
{
|
||||
name: "before: capacity enabled, update: no capacity",
|
||||
old: driverWithCapacityEnabled,
|
||||
update: driverWithoutCapacity,
|
||||
withCapacity: nil,
|
||||
withoutCapacity: nil,
|
||||
},
|
||||
|
||||
{
|
||||
name: "before: no mode, update: no mode",
|
||||
old: driverWithoutModes,
|
||||
@ -217,35 +292,46 @@ func TestCSIDriverPrepareForUpdate(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
runAll := func(t *testing.T, withInline bool) {
|
||||
runAll := func(t *testing.T, withCapacity, withInline bool) {
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIStorageCapacity, withCapacity)()
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, withInline)()
|
||||
|
||||
csiDriver := test.update.DeepCopy()
|
||||
Strategy.PrepareForUpdate(ctx, csiDriver, test.old)
|
||||
if withInline {
|
||||
require.Equal(t, csiDriver.Spec.VolumeLifecycleModes, test.withInline)
|
||||
if withCapacity {
|
||||
require.Equal(t, test.withCapacity, csiDriver.Spec.StorageCapacity)
|
||||
} else {
|
||||
require.Equal(t, csiDriver.Spec.VolumeLifecycleModes, test.withoutInline)
|
||||
require.Equal(t, test.withoutCapacity, csiDriver.Spec.StorageCapacity)
|
||||
}
|
||||
if withInline {
|
||||
require.Equal(t, test.withInline, csiDriver.Spec.VolumeLifecycleModes)
|
||||
} else {
|
||||
require.Equal(t, test.withoutInline, csiDriver.Spec.VolumeLifecycleModes)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("with capacity", func(t *testing.T) {
|
||||
runAll(t, true, false)
|
||||
})
|
||||
t.Run("without capacity", func(t *testing.T) {
|
||||
runAll(t, false, false)
|
||||
})
|
||||
|
||||
t.Run("with inline volumes", func(t *testing.T) {
|
||||
runAll(t, true)
|
||||
runAll(t, false, true)
|
||||
})
|
||||
t.Run("without inline volumes", func(t *testing.T) {
|
||||
runAll(t, false)
|
||||
runAll(t, false, false)
|
||||
})
|
||||
}
|
||||
|
||||
func TestCSIDriverValidation(t *testing.T) {
|
||||
attachRequired := true
|
||||
notAttachRequired := false
|
||||
podInfoOnMount := true
|
||||
notPodInfoOnMount := false
|
||||
enabled := true
|
||||
disabled := true
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
@ -258,27 +344,29 @@ func TestCSIDriverValidation(t *testing.T) {
|
||||
false,
|
||||
},
|
||||
{
|
||||
"true PodInfoOnMount and AttachRequired",
|
||||
"true for all flags",
|
||||
&storage.CSIDriver{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "foo",
|
||||
},
|
||||
Spec: storage.CSIDriverSpec{
|
||||
AttachRequired: &attachRequired,
|
||||
PodInfoOnMount: &podInfoOnMount,
|
||||
AttachRequired: &enabled,
|
||||
PodInfoOnMount: &enabled,
|
||||
StorageCapacity: &enabled,
|
||||
},
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
"false PodInfoOnMount and AttachRequired",
|
||||
"false for all flags",
|
||||
&storage.CSIDriver{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "foo",
|
||||
},
|
||||
Spec: storage.CSIDriverSpec{
|
||||
AttachRequired: ¬AttachRequired,
|
||||
PodInfoOnMount: ¬PodInfoOnMount,
|
||||
AttachRequired: &disabled,
|
||||
PodInfoOnMount: &disabled,
|
||||
StorageCapacity: &disabled,
|
||||
},
|
||||
},
|
||||
false,
|
||||
@ -290,8 +378,9 @@ func TestCSIDriverValidation(t *testing.T) {
|
||||
Name: "*foo#",
|
||||
},
|
||||
Spec: storage.CSIDriverSpec{
|
||||
AttachRequired: &attachRequired,
|
||||
PodInfoOnMount: &podInfoOnMount,
|
||||
AttachRequired: &enabled,
|
||||
PodInfoOnMount: &enabled,
|
||||
StorageCapacity: &enabled,
|
||||
},
|
||||
},
|
||||
true,
|
||||
@ -303,8 +392,9 @@ func TestCSIDriverValidation(t *testing.T) {
|
||||
Name: "foo",
|
||||
},
|
||||
Spec: storage.CSIDriverSpec{
|
||||
AttachRequired: &attachRequired,
|
||||
PodInfoOnMount: &podInfoOnMount,
|
||||
AttachRequired: &enabled,
|
||||
PodInfoOnMount: &enabled,
|
||||
StorageCapacity: &enabled,
|
||||
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
|
||||
storage.VolumeLifecycleMode("no-such-mode"),
|
||||
},
|
||||
@ -319,8 +409,9 @@ func TestCSIDriverValidation(t *testing.T) {
|
||||
Name: "foo",
|
||||
},
|
||||
Spec: storage.CSIDriverSpec{
|
||||
AttachRequired: &attachRequired,
|
||||
PodInfoOnMount: &podInfoOnMount,
|
||||
AttachRequired: &enabled,
|
||||
PodInfoOnMount: &enabled,
|
||||
StorageCapacity: &enabled,
|
||||
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
|
||||
storage.VolumeLifecyclePersistent,
|
||||
},
|
||||
@ -335,8 +426,9 @@ func TestCSIDriverValidation(t *testing.T) {
|
||||
Name: "foo",
|
||||
},
|
||||
Spec: storage.CSIDriverSpec{
|
||||
AttachRequired: &attachRequired,
|
||||
PodInfoOnMount: &podInfoOnMount,
|
||||
AttachRequired: &enabled,
|
||||
PodInfoOnMount: &enabled,
|
||||
StorageCapacity: &enabled,
|
||||
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
|
||||
storage.VolumeLifecycleEphemeral,
|
||||
},
|
||||
@ -351,8 +443,9 @@ func TestCSIDriverValidation(t *testing.T) {
|
||||
Name: "foo",
|
||||
},
|
||||
Spec: storage.CSIDriverSpec{
|
||||
AttachRequired: &attachRequired,
|
||||
PodInfoOnMount: &podInfoOnMount,
|
||||
AttachRequired: &enabled,
|
||||
PodInfoOnMount: &enabled,
|
||||
StorageCapacity: &enabled,
|
||||
VolumeLifecycleModes: []storage.VolumeLifecycleMode{
|
||||
storage.VolumeLifecyclePersistent,
|
||||
storage.VolumeLifecycleEphemeral,
|
||||
|
@ -316,6 +316,26 @@ type CSIDriverSpec struct {
|
||||
// +optional
|
||||
// +listType=set
|
||||
VolumeLifecycleModes []VolumeLifecycleMode `json:"volumeLifecycleModes,omitempty" protobuf:"bytes,3,opt,name=volumeLifecycleModes"`
|
||||
|
||||
// If set to true, storageCapacity indicates that the CSI
|
||||
// volume driver wants pod scheduling to consider the storage
|
||||
// capacity that the driver deployment will report by creating
|
||||
// CSIStorageCapacity objects with capacity information.
|
||||
//
|
||||
// The check can be enabled immediately when deploying a driver.
|
||||
// In that case, provisioning new volumes with late binding
|
||||
// will pause until the driver deployment has published
|
||||
// some suitable CSIStorageCapacity object.
|
||||
//
|
||||
// Alternatively, the driver can be deployed with the field
|
||||
// unset or false and it can be flipped later when storage
|
||||
// capacity information has been published.
|
||||
//
|
||||
// This is an alpha field and only available when the CSIStorageCapacity
|
||||
// feature is enabled. The default is false.
|
||||
//
|
||||
// +optional
|
||||
StorageCapacity *bool `json:"storageCapacity,omitempty" protobuf:"bytes,4,opt,name=storageCapacity"`
|
||||
}
|
||||
|
||||
// VolumeLifecycleMode is an enumeration of possible usage modes for a volume
|
||||
|
@ -335,6 +335,27 @@ type CSIDriverSpec struct {
|
||||
// more modes may be added in the future.
|
||||
// +optional
|
||||
VolumeLifecycleModes []VolumeLifecycleMode `json:"volumeLifecycleModes,omitempty" protobuf:"bytes,3,opt,name=volumeLifecycleModes"`
|
||||
|
||||
// If set to true, storageCapacity indicates that the CSI
|
||||
// volume driver wants pod scheduling to consider the storage
|
||||
// capacity that the driver deployment will report by creating
|
||||
// CSIStorageCapacity objects with capacity information.
|
||||
//
|
||||
//
|
||||
// The check can be enabled immediately when deploying a driver.
|
||||
// In that case, provisioning new volumes with late binding
|
||||
// will pause until the driver deployment has published
|
||||
// some suitable CSIStorageCapacity object.
|
||||
//
|
||||
// Alternatively, the driver can be deployed with the field
|
||||
// unset or false and it can be flipped later when storage
|
||||
// capacity information has been published.
|
||||
//
|
||||
// This is an alpha field and only available when the CSIStorageCapacity
|
||||
// feature is enabled. The default is false.
|
||||
//
|
||||
// +optional
|
||||
StorageCapacity *bool `json:"storageCapacity,omitempty" protobuf:"bytes,4,opt,name=storageCapacity"`
|
||||
}
|
||||
|
||||
// VolumeLifecycleMode is an enumeration of possible usage modes for a volume
|
||||
|
Loading…
Reference in New Issue
Block a user