mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-25 12:43:23 +00:00
Add validation options for PersistentVolumes
These options provide an extensible way of configuring how PVs are validated
This commit is contained in:
parent
d92f6c424d
commit
9ba0eed7c5
@ -1638,6 +1638,10 @@ var allowedPVCTemplateObjectMetaFields = map[string]bool{
|
||||
"Labels": true,
|
||||
}
|
||||
|
||||
// PersistentVolumeSpecValidationOptions contains the different settings for PeristentVolume validation
|
||||
type PersistentVolumeSpecValidationOptions struct {
|
||||
}
|
||||
|
||||
// ValidatePersistentVolumeName checks that a name is appropriate for a
|
||||
// PersistentVolumeName object.
|
||||
var ValidatePersistentVolumeName = apimachineryvalidation.NameIsDNSSubdomain
|
||||
@ -1648,7 +1652,11 @@ var supportedReclaimPolicy = sets.NewString(string(core.PersistentVolumeReclaimD
|
||||
|
||||
var supportedVolumeModes = sets.NewString(string(core.PersistentVolumeBlock), string(core.PersistentVolumeFilesystem))
|
||||
|
||||
func ValidatePersistentVolumeSpec(pvSpec *core.PersistentVolumeSpec, pvName string, validateInlinePersistentVolumeSpec bool, fldPath *field.Path) field.ErrorList {
|
||||
func ValidationOptionsForPersistentVolume(pv, oldPv *core.PersistentVolume) PersistentVolumeSpecValidationOptions {
|
||||
return PersistentVolumeSpecValidationOptions{}
|
||||
}
|
||||
|
||||
func ValidatePersistentVolumeSpec(pvSpec *core.PersistentVolumeSpec, pvName string, validateInlinePersistentVolumeSpec bool, fldPath *field.Path, opts PersistentVolumeSpecValidationOptions) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
||||
if validateInlinePersistentVolumeSpec {
|
||||
@ -1922,17 +1930,17 @@ func ValidatePersistentVolumeSpec(pvSpec *core.PersistentVolumeSpec, pvName stri
|
||||
return allErrs
|
||||
}
|
||||
|
||||
func ValidatePersistentVolume(pv *core.PersistentVolume) field.ErrorList {
|
||||
func ValidatePersistentVolume(pv *core.PersistentVolume, opts PersistentVolumeSpecValidationOptions) field.ErrorList {
|
||||
metaPath := field.NewPath("metadata")
|
||||
allErrs := ValidateObjectMeta(&pv.ObjectMeta, false, ValidatePersistentVolumeName, metaPath)
|
||||
allErrs = append(allErrs, ValidatePersistentVolumeSpec(&pv.Spec, pv.ObjectMeta.Name, false, field.NewPath("spec"))...)
|
||||
allErrs = append(allErrs, ValidatePersistentVolumeSpec(&pv.Spec, pv.ObjectMeta.Name, false, field.NewPath("spec"), opts)...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidatePersistentVolumeUpdate tests to see if the update is legal for an end user to make.
|
||||
// newPv is updated with fields that cannot be changed.
|
||||
func ValidatePersistentVolumeUpdate(newPv, oldPv *core.PersistentVolume) field.ErrorList {
|
||||
allErrs := ValidatePersistentVolume(newPv)
|
||||
func ValidatePersistentVolumeUpdate(newPv, oldPv *core.PersistentVolume, opts PersistentVolumeSpecValidationOptions) field.ErrorList {
|
||||
allErrs := ValidatePersistentVolume(newPv, opts)
|
||||
|
||||
// if oldPV does not have ControllerExpandSecretRef then allow it to be set
|
||||
if (oldPv.Spec.CSI != nil && oldPv.Spec.CSI.ControllerExpandSecretRef == nil) &&
|
||||
|
@ -415,7 +415,8 @@ func TestValidatePersistentVolumes(t *testing.T) {
|
||||
|
||||
for name, scenario := range scenarios {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
errs := ValidatePersistentVolume(scenario.volume)
|
||||
opts := ValidationOptionsForPersistentVolume(scenario.volume, nil)
|
||||
errs := ValidatePersistentVolume(scenario.volume, opts)
|
||||
if len(errs) == 0 && scenario.isExpectedFailure {
|
||||
t.Errorf("Unexpected success for scenario: %s", name)
|
||||
}
|
||||
@ -558,7 +559,8 @@ func TestValidatePersistentVolumeSpec(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for name, scenario := range scenarios {
|
||||
errs := ValidatePersistentVolumeSpec(scenario.pvSpec, "", scenario.isInlineSpec, field.NewPath("field"))
|
||||
opts := PersistentVolumeSpecValidationOptions{}
|
||||
errs := ValidatePersistentVolumeSpec(scenario.pvSpec, "", scenario.isInlineSpec, field.NewPath("field"), opts)
|
||||
if len(errs) == 0 && scenario.isExpectedFailure {
|
||||
t.Errorf("Unexpected success for scenario: %s", name)
|
||||
}
|
||||
@ -655,7 +657,8 @@ func TestValidatePersistentVolumeSourceUpdate(t *testing.T) {
|
||||
},
|
||||
}
|
||||
for name, scenario := range scenarios {
|
||||
errs := ValidatePersistentVolumeUpdate(scenario.newVolume, scenario.oldVolume)
|
||||
opts := ValidationOptionsForPersistentVolume(scenario.newVolume, scenario.oldVolume)
|
||||
errs := ValidatePersistentVolumeUpdate(scenario.newVolume, scenario.oldVolume, opts)
|
||||
if len(errs) == 0 && scenario.isExpectedFailure {
|
||||
t.Errorf("Unexpected success for scenario: %s", name)
|
||||
}
|
||||
@ -665,6 +668,14 @@ func TestValidatePersistentVolumeSourceUpdate(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidationOptionsForPersistentVolume(t *testing.T) {
|
||||
expectedValidationOpts := PersistentVolumeSpecValidationOptions{}
|
||||
opts := ValidationOptionsForPersistentVolume(nil, nil)
|
||||
if opts != expectedValidationOpts {
|
||||
t.Errorf("Expected opts: %+v, received: %+v", opts, expectedValidationOpts)
|
||||
}
|
||||
}
|
||||
|
||||
func getCSIVolumeWithSecret(pv *core.PersistentVolume, secret *core.SecretReference) *core.PersistentVolume {
|
||||
pvCopy := pv.DeepCopy()
|
||||
if secret != nil {
|
||||
@ -729,7 +740,8 @@ func TestValidateLocalVolumes(t *testing.T) {
|
||||
}
|
||||
|
||||
for name, scenario := range scenarios {
|
||||
errs := ValidatePersistentVolume(scenario.volume)
|
||||
opts := ValidationOptionsForPersistentVolume(scenario.volume, nil)
|
||||
errs := ValidatePersistentVolume(scenario.volume, opts)
|
||||
if len(errs) == 0 && scenario.isExpectedFailure {
|
||||
t.Errorf("Unexpected success for scenario: %s", name)
|
||||
}
|
||||
@ -808,7 +820,8 @@ func TestValidateVolumeNodeAffinityUpdate(t *testing.T) {
|
||||
}
|
||||
|
||||
for name, scenario := range scenarios {
|
||||
errs := ValidatePersistentVolumeUpdate(scenario.newPV, scenario.oldPV)
|
||||
opts := ValidationOptionsForPersistentVolume(scenario.newPV, scenario.oldPV)
|
||||
errs := ValidatePersistentVolumeUpdate(scenario.newPV, scenario.oldPV, opts)
|
||||
if len(errs) == 0 && scenario.isExpectedFailure {
|
||||
t.Errorf("Unexpected success for scenario: %s", name)
|
||||
}
|
||||
@ -1393,8 +1406,9 @@ func TestAlphaPVVolumeModeUpdate(t *testing.T) {
|
||||
|
||||
for name, scenario := range scenarios {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
opts := ValidationOptionsForPersistentVolume(scenario.newPV, scenario.oldPV)
|
||||
// ensure we have a resource version specified for updates
|
||||
errs := ValidatePersistentVolumeUpdate(scenario.newPV, scenario.oldPV)
|
||||
errs := ValidatePersistentVolumeUpdate(scenario.newPV, scenario.oldPV, opts)
|
||||
if len(errs) == 0 && scenario.isExpectedFailure {
|
||||
t.Errorf("Unexpected success for scenario: %s", name)
|
||||
}
|
||||
@ -4337,7 +4351,8 @@ func TestPVVolumeMode(t *testing.T) {
|
||||
"valid nil value": createTestVolModePV(nil),
|
||||
}
|
||||
for k, v := range successCasesPV {
|
||||
if errs := ValidatePersistentVolume(v); len(errs) != 0 {
|
||||
opts := ValidationOptionsForPersistentVolume(v, nil)
|
||||
if errs := ValidatePersistentVolume(v, opts); len(errs) != 0 {
|
||||
t.Errorf("expected success for %s", k)
|
||||
}
|
||||
}
|
||||
@ -4348,7 +4363,8 @@ func TestPVVolumeMode(t *testing.T) {
|
||||
"empty value": createTestVolModePV(&empty),
|
||||
}
|
||||
for k, v := range errorCasesPV {
|
||||
if errs := ValidatePersistentVolume(v); len(errs) == 0 {
|
||||
opts := ValidationOptionsForPersistentVolume(v, nil)
|
||||
if errs := ValidatePersistentVolume(v, opts); len(errs) == 0 {
|
||||
t.Errorf("expected failure for %s", k)
|
||||
}
|
||||
}
|
||||
|
@ -192,7 +192,8 @@ func validateVolumeAttachmentSource(source *storage.VolumeAttachmentSource, fldP
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("persistentVolumeName"), "must specify non empty persistentVolumeName"))
|
||||
}
|
||||
case source.InlineVolumeSpec != nil:
|
||||
allErrs = append(allErrs, apivalidation.ValidatePersistentVolumeSpec(source.InlineVolumeSpec, "", true, fldPath.Child("inlineVolumeSpec"))...)
|
||||
opts := apivalidation.PersistentVolumeSpecValidationOptions{}
|
||||
allErrs = append(allErrs, apivalidation.ValidatePersistentVolumeSpec(source.InlineVolumeSpec, "", true, fldPath.Child("inlineVolumeSpec"), opts)...)
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
@ -71,7 +71,8 @@ func (persistentvolumeStrategy) PrepareForCreate(ctx context.Context, obj runtim
|
||||
|
||||
func (persistentvolumeStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
|
||||
persistentvolume := obj.(*api.PersistentVolume)
|
||||
errorList := validation.ValidatePersistentVolume(persistentvolume)
|
||||
opts := validation.ValidationOptionsForPersistentVolume(persistentvolume, nil)
|
||||
errorList := validation.ValidatePersistentVolume(persistentvolume, opts)
|
||||
return append(errorList, volumevalidation.ValidatePersistentVolume(persistentvolume)...)
|
||||
}
|
||||
|
||||
@ -99,9 +100,11 @@ func (persistentvolumeStrategy) PrepareForUpdate(ctx context.Context, obj, old r
|
||||
|
||||
func (persistentvolumeStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
|
||||
newPv := obj.(*api.PersistentVolume)
|
||||
errorList := validation.ValidatePersistentVolume(newPv)
|
||||
oldPv := old.(*api.PersistentVolume)
|
||||
opts := validation.ValidationOptionsForPersistentVolume(newPv, oldPv)
|
||||
errorList := validation.ValidatePersistentVolume(newPv, opts)
|
||||
errorList = append(errorList, volumevalidation.ValidatePersistentVolume(newPv)...)
|
||||
return append(errorList, validation.ValidatePersistentVolumeUpdate(newPv, old.(*api.PersistentVolume))...)
|
||||
return append(errorList, validation.ValidatePersistentVolumeUpdate(newPv, oldPv, opts)...)
|
||||
}
|
||||
|
||||
// WarningsOnUpdate returns warnings for the given update.
|
||||
|
Loading…
Reference in New Issue
Block a user