Skip to content

Commit c766a52

Browse files
authored
Implement KEP 4876 Mutable CSINode (kubernetes#130007)
* Implement KEP-4876 Mutable CSINode Allocatable Count Signed-off-by: torredil <[email protected]> * Update TestGetNodeAllocatableUpdatePeriod Signed-off-by: torredil <[email protected]> * Implement CSINodeUpdater Signed-off-by: torredil <[email protected]> * Use sync.Once in csiNodeUpdater Signed-off-by: torredil <[email protected]> * ImVerify driver is installed before running periodic updates Signed-off-by: torredil <[email protected]> * Update NodeAllocatableUpdatePeriodSeconds type comment Signed-off-by: torredil <[email protected]> * Leverage apivalidation.ValidateImmutableField in ValidateCSINodeUpdate Signed-off-by: torredil <[email protected]> * Update strategy functions Signed-off-by: torredil <[email protected]> * Run hack/update-openapi-spec.sh Signed-off-by: torredil <[email protected]> * Update VolumeError.ErrorCode field Signed-off-by: torredil <[email protected]> * CSINodeUpdater improvements Signed-off-by: torredil <[email protected]> * Iron out concurrency in syncDriverUpdater Signed-off-by: torredil <[email protected]> * Run hack/update-openapi-spec.sh Signed-off-by: torredil <[email protected]> * Revise logging Signed-off-by: torredil <[email protected]> * Revise log in VerifyExhaustedResource Signed-off-by: torredil <[email protected]> * Update API validation Signed-off-by: torredil <[email protected]> * Add more code coverage Signed-off-by: torredil <[email protected]> * Fix pull-kubernetes-linter-hints Signed-off-by: torredil <[email protected]> * Update API types documentation Signed-off-by: torredil <[email protected]> * Update strategy and validation for new errorCode field Signed-off-by: torredil <[email protected]> * Update validation tests after strategy changes Signed-off-by: torredil <[email protected]> * Update VA status strategy Signed-off-by: torredil <[email protected]> --------- Signed-off-by: torredil <[email protected]>
1 parent 55573a0 commit c766a52

File tree

67 files changed

+2094
-412
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+2094
-412
lines changed

api/openapi-spec/swagger.json

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/openapi-spec/v3/apis__storage.k8s.io__v1_openapi.json

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/apis/storage/types.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,14 @@ type VolumeError struct {
203203
// information.
204204
// +optional
205205
Message string
206+
207+
// errorCode is a numeric gRPC code representing the error encountered during Attach or Detach operations.
208+
//
209+
// This is an optional, alpha field that requires the MutableCSINodeAllocatableCount feature gate being enabled to be set.
210+
//
211+
// +featureGate=MutableCSINodeAllocatableCount
212+
// +optional
213+
ErrorCode *int32
206214
}
207215

208216
// VolumeBindingMode indicates how PersistentVolumeClaims should be bound.
@@ -412,6 +420,20 @@ type CSIDriverSpec struct {
412420
// +featureGate=SELinuxMountReadWriteOncePod
413421
// +optional
414422
SELinuxMount *bool
423+
424+
// nodeAllocatableUpdatePeriodSeconds specifies the interval between periodic updates of
425+
// the CSINode allocatable capacity for this driver. When set, both periodic updates and
426+
// updates triggered by capacity-related failures are enabled. If not set, no updates
427+
// occur (neither periodic nor upon detecting capacity-related failures), and the
428+
// allocatable.count remains static. The minimum allowed value for this field is 10 seconds.
429+
//
430+
// This is an alpha feature and requires the MutableCSINodeAllocatableCount feature gate to be enabled.
431+
//
432+
// This field is mutable.
433+
//
434+
// +featureGate=MutableCSINodeAllocatableCount
435+
// +optional
436+
NodeAllocatableUpdatePeriodSeconds *int64
415437
}
416438

417439
// FSGroupPolicy specifies if a CSI Driver supports modifying
@@ -495,6 +517,8 @@ const (
495517
// there are no CSI Drivers available on the node, or the Kubelet version is low
496518
// enough that it doesn't create this object.
497519
// CSINode has an OwnerReference that points to the corresponding node object.
520+
// When the MutableCSINodeAllocatableCount feature gate is enabled, the allocatable.count
521+
// field in CSINodeDriver can be updated.
498522
type CSINode struct {
499523
metav1.TypeMeta
500524

pkg/apis/storage/v1/zz_generated.conversion.go

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/apis/storage/v1alpha1/zz_generated.conversion.go

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/apis/storage/v1beta1/zz_generated.conversion.go

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/apis/storage/validation/validation.go

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package validation
1818

1919
import (
2020
"fmt"
21+
"math"
2122
"reflect"
2223
"strings"
2324
"time"
@@ -26,6 +27,7 @@ import (
2627
apimachineryvalidation "k8s.io/apimachinery/pkg/api/validation"
2728
metav1validation "k8s.io/apimachinery/pkg/apis/meta/v1/validation"
2829
"k8s.io/apimachinery/pkg/util/sets"
30+
"k8s.io/apimachinery/pkg/util/validation"
2931
"k8s.io/apimachinery/pkg/util/validation/field"
3032
utilfeature "k8s.io/apiserver/pkg/util/feature"
3133
api "k8s.io/kubernetes/pkg/apis/core"
@@ -237,6 +239,13 @@ func validateVolumeError(e *storage.VolumeError, fldPath *field.Path) field.Erro
237239
if len(e.Message) > maxVolumeErrorMessageSize {
238240
allErrs = append(allErrs, field.TooLong(fldPath.Child("message"), "" /*unused*/, maxAttachedVolumeMetadataSize))
239241
}
242+
243+
if e.ErrorCode != nil {
244+
value := *e.ErrorCode
245+
if value < 0 {
246+
allErrs = append(allErrs, field.Invalid(fldPath.Child("errorCode"), value, validation.InclusiveRangeError(0, math.MaxInt32)))
247+
}
248+
}
240249
return allErrs
241250
}
242251

@@ -304,17 +313,28 @@ func ValidateCSINode(csiNode *storage.CSINode, validationOpts CSINodeValidationO
304313
func ValidateCSINodeUpdate(new, old *storage.CSINode, validationOpts CSINodeValidationOptions) field.ErrorList {
305314
allErrs := ValidateCSINode(new, validationOpts)
306315

307-
// Validate modifying fields inside an existing CSINodeDriver entry is not allowed
316+
// Validate modifying fields inside an existing CSINodeDriver entry
308317
for _, oldDriver := range old.Spec.Drivers {
309318
for _, newDriver := range new.Spec.Drivers {
310319
if oldDriver.Name == newDriver.Name {
311-
if !apiequality.Semantic.DeepEqual(oldDriver, newDriver) {
312-
allErrs = append(allErrs, field.Invalid(field.NewPath("CSINodeDriver"), newDriver, "field is immutable"))
320+
// If MutableCSINodeAllocatableCount feature gate is enabled, compare drivers without the Allocatable field
321+
if utilfeature.DefaultFeatureGate.Enabled(features.MutableCSINodeAllocatableCount) {
322+
oldDriverCopy := oldDriver.DeepCopy()
323+
newDriverCopy := newDriver.DeepCopy()
324+
oldDriverCopy.Allocatable = nil // +k8s:verify-mutation:reason=clone
325+
newDriverCopy.Allocatable = nil // +k8s:verify-mutation:reason=clone
326+
327+
allErrs = append(allErrs,
328+
apivalidation.ValidateImmutableField(newDriverCopy, oldDriverCopy, field.NewPath("spec").Child("drivers"))...,
329+
)
330+
} else {
331+
allErrs = append(allErrs,
332+
apivalidation.ValidateImmutableField(newDriver, oldDriver, field.NewPath("spec").Child("drivers"))...,
333+
)
313334
}
314335
}
315336
}
316337
}
317-
318338
return allErrs
319339
}
320340

@@ -435,6 +455,16 @@ func validateCSIDriverSpec(
435455
allErrs = append(allErrs, validateTokenRequests(spec.TokenRequests, fldPath.Child("tokenRequests"))...)
436456
allErrs = append(allErrs, validateVolumeLifecycleModes(spec.VolumeLifecycleModes, fldPath.Child("volumeLifecycleModes"))...)
437457
allErrs = append(allErrs, validateSELinuxMount(spec.SELinuxMount, fldPath.Child("seLinuxMount"))...)
458+
allErrs = append(allErrs, validateNodeAllocatableUpdatePeriodSeconds(spec.NodeAllocatableUpdatePeriodSeconds, fldPath.Child("nodeAllocatableUpdatePeriodSeconds"))...)
459+
return allErrs
460+
}
461+
462+
// validateNodeAllocatableUpdatePeriodSeconds tests if NodeAllocatableUpdatePeriodSeconds is valid for CSIDriver.
463+
func validateNodeAllocatableUpdatePeriodSeconds(period *int64, fldPath *field.Path) field.ErrorList {
464+
allErrs := field.ErrorList{}
465+
if period != nil && *period < 10 {
466+
allErrs = append(allErrs, field.Invalid(fldPath, *period, "must be greater than or equal to 10 seconds"))
467+
}
438468
return allErrs
439469
}
440470

0 commit comments

Comments
 (0)