mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-29 22:46:12 +00:00
Implement API changes necessary for recovery from resize failure
This commit is contained in:
parent
7b9f4f18fe
commit
63fffd37b1
13
api/openapi-spec/swagger.json
generated
13
api/openapi-spec/swagger.json
generated
@ -7767,7 +7767,7 @@
|
||||
},
|
||||
"resources": {
|
||||
"$ref": "#/definitions/io.k8s.api.core.v1.ResourceRequirements",
|
||||
"description": "Resources represents the minimum resources the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources"
|
||||
"description": "Resources represents the minimum resources the volume should have. If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources"
|
||||
},
|
||||
"selector": {
|
||||
"$ref": "#/definitions/io.k8s.apimachinery.pkg.apis.meta.v1.LabelSelector",
|
||||
@ -7798,6 +7798,13 @@
|
||||
},
|
||||
"type": "array"
|
||||
},
|
||||
"allocatedResources": {
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity"
|
||||
},
|
||||
"description": "The storage resource within AllocatedResources tracks the capacity allocated to a PVC. It may be larger than the actual capacity when a volume expansion operation is requested. For storage quota, the larger value from allocatedResources and PVC.spec.resources is used. If allocatedResources is not set, PVC.spec.resources alone is used for quota calculation. If a volume expansion capacity request is lowered, allocatedResources is only lowered if there are no expansion operations in progress and if the actual volume capacity is equal or lower than the requested capacity. This is an alpha field and requires enabling RecoverVolumeExpansionFailure feature.",
|
||||
"type": "object"
|
||||
},
|
||||
"capacity": {
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/io.k8s.apimachinery.pkg.api.resource.Quantity"
|
||||
@ -7817,6 +7824,10 @@
|
||||
"phase": {
|
||||
"description": "Phase represents the current phase of PersistentVolumeClaim.",
|
||||
"type": "string"
|
||||
},
|
||||
"resizeStatus": {
|
||||
"description": "ResizeStatus stores status of resize operation. ResizeStatus is not set by default but when expansion is complete resizeStatus is set to empty string by resize controller or kubelet. This is an alpha field and requires enabling RecoverVolumeExpansionFailure feature.",
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"type": "object"
|
||||
|
@ -74,6 +74,21 @@ func EnforceDataSourceBackwardsCompatibility(pvcSpec, oldPVCSpec *core.Persisten
|
||||
}
|
||||
}
|
||||
|
||||
func DropDisabledFieldsFromStatus(pvc, oldPVC *core.PersistentVolumeClaim) {
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.ExpandPersistentVolumes) && oldPVC.Status.Conditions == nil {
|
||||
pvc.Status.Conditions = nil
|
||||
}
|
||||
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.RecoverVolumeExpansionFailure) {
|
||||
if !allocatedResourcesInUse(oldPVC) {
|
||||
pvc.Status.AllocatedResources = nil
|
||||
}
|
||||
if !resizeStatusInUse(oldPVC) {
|
||||
pvc.Status.ResizeStatus = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func dataSourceInUse(oldPVCSpec *core.PersistentVolumeClaimSpec) bool {
|
||||
if oldPVCSpec == nil {
|
||||
return false
|
||||
@ -118,3 +133,25 @@ func NormalizeDataSources(pvcSpec *core.PersistentVolumeClaimSpec) {
|
||||
pvcSpec.DataSource = pvcSpec.DataSourceRef.DeepCopy()
|
||||
}
|
||||
}
|
||||
|
||||
func resizeStatusInUse(oldPVC *core.PersistentVolumeClaim) bool {
|
||||
if oldPVC == nil {
|
||||
return false
|
||||
}
|
||||
if oldPVC.Status.ResizeStatus != nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func allocatedResourcesInUse(oldPVC *core.PersistentVolumeClaim) bool {
|
||||
if oldPVC == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if oldPVC.Status.AllocatedResources != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
@ -288,3 +289,111 @@ func TestDataSourceRef(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDropDisabledFieldsFromStatus(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
feature bool
|
||||
pvc *core.PersistentVolumeClaim
|
||||
oldPVC *core.PersistentVolumeClaim
|
||||
expected *core.PersistentVolumeClaim
|
||||
}{
|
||||
{
|
||||
name: "for:newPVC=hasAllocatedResource,oldPVC=doesnot,featuregate=false; should drop field",
|
||||
feature: false,
|
||||
pvc: withAllocatedResource("5G"),
|
||||
oldPVC: getPVC(),
|
||||
expected: getPVC(),
|
||||
},
|
||||
{
|
||||
name: "for:newPVC=hasAllocatedResource,oldPVC=doesnot,featuregate=true; should keep field",
|
||||
feature: true,
|
||||
pvc: withAllocatedResource("5G"),
|
||||
oldPVC: getPVC(),
|
||||
expected: withAllocatedResource("5G"),
|
||||
},
|
||||
{
|
||||
name: "for:newPVC=hasAllocatedResource,oldPVC=hasAllocatedResource,featuregate=true; should keep field",
|
||||
feature: true,
|
||||
pvc: withAllocatedResource("5G"),
|
||||
oldPVC: withAllocatedResource("5G"),
|
||||
expected: withAllocatedResource("5G"),
|
||||
},
|
||||
{
|
||||
name: "for:newPVC=hasAllocatedResource,oldPVC=hasAllocatedResource,featuregate=false; should keep field",
|
||||
feature: false,
|
||||
pvc: withAllocatedResource("10G"),
|
||||
oldPVC: withAllocatedResource("5G"),
|
||||
expected: withAllocatedResource("10G"),
|
||||
},
|
||||
{
|
||||
name: "for:newPVC=hasAllocatedResource,oldPVC=nil,featuregate=false; should drop field",
|
||||
feature: false,
|
||||
pvc: withAllocatedResource("5G"),
|
||||
oldPVC: nil,
|
||||
expected: getPVC(),
|
||||
},
|
||||
{
|
||||
name: "for:newPVC=hasResizeStatus,oldPVC=nil, featuregate=false should drop field",
|
||||
feature: false,
|
||||
pvc: withResizeStatus(core.PersistentVolumeClaimNodeExpansionFailed),
|
||||
oldPVC: nil,
|
||||
expected: getPVC(),
|
||||
},
|
||||
{
|
||||
name: "for:newPVC=hasResizeStatus,oldPVC=doesnot,featuregate=true; should keep field",
|
||||
feature: true,
|
||||
pvc: withResizeStatus(core.PersistentVolumeClaimNodeExpansionFailed),
|
||||
oldPVC: getPVC(),
|
||||
expected: withResizeStatus(core.PersistentVolumeClaimNodeExpansionFailed),
|
||||
},
|
||||
{
|
||||
name: "for:newPVC=hasResizeStatus,oldPVC=hasResizeStatus,featuregate=true; should keep field",
|
||||
feature: true,
|
||||
pvc: withResizeStatus(core.PersistentVolumeClaimNodeExpansionFailed),
|
||||
oldPVC: withResizeStatus(core.PersistentVolumeClaimNodeExpansionFailed),
|
||||
expected: withResizeStatus(core.PersistentVolumeClaimNodeExpansionFailed),
|
||||
},
|
||||
{
|
||||
name: "for:newPVC=hasResizeStatus,oldPVC=hasResizeStatus,featuregate=false; should keep field",
|
||||
feature: false,
|
||||
pvc: withResizeStatus(core.PersistentVolumeClaimNodeExpansionFailed),
|
||||
oldPVC: withResizeStatus(core.PersistentVolumeClaimNodeExpansionFailed),
|
||||
expected: withResizeStatus(core.PersistentVolumeClaimNodeExpansionFailed),
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.RecoverVolumeExpansionFailure, test.feature)()
|
||||
|
||||
DropDisabledFieldsFromStatus(test.pvc, test.oldPVC)
|
||||
|
||||
if !reflect.DeepEqual(*test.expected, *test.pvc) {
|
||||
t.Errorf("Unexpected change: %+v", cmp.Diff(test.expected, test.pvc))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func getPVC() *core.PersistentVolumeClaim {
|
||||
return &core.PersistentVolumeClaim{}
|
||||
}
|
||||
|
||||
func withAllocatedResource(q string) *core.PersistentVolumeClaim {
|
||||
return &core.PersistentVolumeClaim{
|
||||
Status: core.PersistentVolumeClaimStatus{
|
||||
AllocatedResources: core.ResourceList{
|
||||
core.ResourceStorage: resource.MustParse(q),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func withResizeStatus(status core.PersistentVolumeClaimResizeStatus) *core.PersistentVolumeClaim {
|
||||
return &core.PersistentVolumeClaim{
|
||||
Status: core.PersistentVolumeClaimStatus{
|
||||
ResizeStatus: &status,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
1
pkg/apis/apps/v1/zz_generated.defaults.go
generated
1
pkg/apis/apps/v1/zz_generated.defaults.go
generated
@ -924,6 +924,7 @@ func SetObjectDefaults_StatefulSet(in *v1.StatefulSet) {
|
||||
corev1.SetDefaults_ResourceList(&a.Spec.Resources.Limits)
|
||||
corev1.SetDefaults_ResourceList(&a.Spec.Resources.Requests)
|
||||
corev1.SetDefaults_ResourceList(&a.Status.Capacity)
|
||||
corev1.SetDefaults_ResourceList(&a.Status.AllocatedResources)
|
||||
}
|
||||
}
|
||||
|
||||
|
1
pkg/apis/apps/v1beta1/zz_generated.defaults.go
generated
1
pkg/apis/apps/v1beta1/zz_generated.defaults.go
generated
@ -478,6 +478,7 @@ func SetObjectDefaults_StatefulSet(in *v1beta1.StatefulSet) {
|
||||
v1.SetDefaults_ResourceList(&a.Spec.Resources.Limits)
|
||||
v1.SetDefaults_ResourceList(&a.Spec.Resources.Requests)
|
||||
v1.SetDefaults_ResourceList(&a.Status.Capacity)
|
||||
v1.SetDefaults_ResourceList(&a.Status.AllocatedResources)
|
||||
}
|
||||
}
|
||||
|
||||
|
1
pkg/apis/apps/v1beta2/zz_generated.defaults.go
generated
1
pkg/apis/apps/v1beta2/zz_generated.defaults.go
generated
@ -924,6 +924,7 @@ func SetObjectDefaults_StatefulSet(in *v1beta2.StatefulSet) {
|
||||
v1.SetDefaults_ResourceList(&a.Spec.Resources.Limits)
|
||||
v1.SetDefaults_ResourceList(&a.Spec.Resources.Requests)
|
||||
v1.SetDefaults_ResourceList(&a.Status.Capacity)
|
||||
v1.SetDefaults_ResourceList(&a.Status.AllocatedResources)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -430,6 +430,9 @@ type PersistentVolumeClaimSpec struct {
|
||||
// +optional
|
||||
Selector *metav1.LabelSelector
|
||||
// Resources represents the minimum resources required
|
||||
// If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements
|
||||
// that are lower than previous value but must still be higher than capacity recorded in the
|
||||
// status field of the claim.
|
||||
// +optional
|
||||
Resources ResourceRequirements
|
||||
// VolumeName is the binding reference to the PersistentVolume backing this
|
||||
@ -486,6 +489,26 @@ const (
|
||||
PersistentVolumeClaimFileSystemResizePending PersistentVolumeClaimConditionType = "FileSystemResizePending"
|
||||
)
|
||||
|
||||
// +enum
|
||||
type PersistentVolumeClaimResizeStatus string
|
||||
|
||||
const (
|
||||
// When expansion is complete, the empty string is set by resize controller or kubelet.
|
||||
PersistentVolumeClaimNoExpansionInProgress PersistentVolumeClaimResizeStatus = ""
|
||||
// State set when resize controller starts expanding the volume in control-plane
|
||||
PersistentVolumeClaimControllerExpansionInProgress PersistentVolumeClaimResizeStatus = "ControllerExpansionInProgress"
|
||||
// State set when expansion has failed in resize controller with a terminal error.
|
||||
// Transient errors such as timeout should not set this status and should leave ResizeStatus
|
||||
// unmodified, so as resize controller can resume the volume expansion.
|
||||
PersistentVolumeClaimControllerExpansionFailed PersistentVolumeClaimResizeStatus = "ControllerExpansionFailed"
|
||||
// State set when resize controller has finished expanding the volume but further expansion is needed on the node.
|
||||
PersistentVolumeClaimNodeExpansionPending PersistentVolumeClaimResizeStatus = "NodeExpansionPending"
|
||||
// State set when kubelet starts expanding the volume.
|
||||
PersistentVolumeClaimNodeExpansionInProgress PersistentVolumeClaimResizeStatus = "NodeExpansionInProgress"
|
||||
// State set when expansion has failed in kubelet with a terminal error. Transient errors don't set NodeExpansionFailed.
|
||||
PersistentVolumeClaimNodeExpansionFailed PersistentVolumeClaimResizeStatus = "NodeExpansionFailed"
|
||||
)
|
||||
|
||||
// PersistentVolumeClaimCondition represents the current condition of PV claim
|
||||
type PersistentVolumeClaimCondition struct {
|
||||
Type PersistentVolumeClaimConditionType
|
||||
@ -513,6 +536,24 @@ type PersistentVolumeClaimStatus struct {
|
||||
Capacity ResourceList
|
||||
// +optional
|
||||
Conditions []PersistentVolumeClaimCondition
|
||||
// The storage resource within AllocatedResources tracks the capacity allocated to a PVC. It may
|
||||
// be larger than the actual capacity when a volume expansion operation is requested.
|
||||
// For storage quota, the larger value from allocatedResources and PVC.spec.resources is used.
|
||||
// If allocatedResources is not set, PVC.spec.resources alone is used for quota calculation.
|
||||
// If a volume expansion capacity request is lowered, allocatedResources is only
|
||||
// lowered if there are no expansion operations in progress and if the actual volume capacity
|
||||
// is equal or lower than the requested capacity.
|
||||
// This is an alpha field and requires enabling RecoverVolumeExpansionFailure feature.
|
||||
// +featureGate=RecoverVolumeExpansionFailure
|
||||
// +optional
|
||||
AllocatedResources ResourceList
|
||||
// ResizeStatus stores status of resize operation.
|
||||
// ResizeStatus is not set by default but when expansion is complete resizeStatus is set to empty
|
||||
// string by resize controller or kubelet.
|
||||
// This is an alpha field and requires enabling RecoverVolumeExpansionFailure feature.
|
||||
// +featureGate=RecoverVolumeExpansionFailure
|
||||
// +optional
|
||||
ResizeStatus *PersistentVolumeClaimResizeStatus
|
||||
}
|
||||
|
||||
// PersistentVolumeAccessMode defines various access modes for PV.
|
||||
|
4
pkg/apis/core/v1/zz_generated.conversion.go
generated
4
pkg/apis/core/v1/zz_generated.conversion.go
generated
@ -5171,6 +5171,8 @@ func autoConvert_v1_PersistentVolumeClaimStatus_To_core_PersistentVolumeClaimSta
|
||||
out.AccessModes = *(*[]core.PersistentVolumeAccessMode)(unsafe.Pointer(&in.AccessModes))
|
||||
out.Capacity = *(*core.ResourceList)(unsafe.Pointer(&in.Capacity))
|
||||
out.Conditions = *(*[]core.PersistentVolumeClaimCondition)(unsafe.Pointer(&in.Conditions))
|
||||
out.AllocatedResources = *(*core.ResourceList)(unsafe.Pointer(&in.AllocatedResources))
|
||||
out.ResizeStatus = (*core.PersistentVolumeClaimResizeStatus)(unsafe.Pointer(in.ResizeStatus))
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -5184,6 +5186,8 @@ func autoConvert_core_PersistentVolumeClaimStatus_To_v1_PersistentVolumeClaimSta
|
||||
out.AccessModes = *(*[]v1.PersistentVolumeAccessMode)(unsafe.Pointer(&in.AccessModes))
|
||||
out.Capacity = *(*v1.ResourceList)(unsafe.Pointer(&in.Capacity))
|
||||
out.Conditions = *(*[]v1.PersistentVolumeClaimCondition)(unsafe.Pointer(&in.Conditions))
|
||||
out.AllocatedResources = *(*v1.ResourceList)(unsafe.Pointer(&in.AllocatedResources))
|
||||
out.ResizeStatus = (*v1.PersistentVolumeClaimResizeStatus)(unsafe.Pointer(in.ResizeStatus))
|
||||
return nil
|
||||
}
|
||||
|
||||
|
1
pkg/apis/core/v1/zz_generated.defaults.go
generated
1
pkg/apis/core/v1/zz_generated.defaults.go
generated
@ -155,6 +155,7 @@ func SetObjectDefaults_PersistentVolumeClaim(in *v1.PersistentVolumeClaim) {
|
||||
SetDefaults_ResourceList(&in.Spec.Resources.Limits)
|
||||
SetDefaults_ResourceList(&in.Spec.Resources.Requests)
|
||||
SetDefaults_ResourceList(&in.Status.Capacity)
|
||||
SetDefaults_ResourceList(&in.Status.AllocatedResources)
|
||||
}
|
||||
|
||||
func SetObjectDefaults_PersistentVolumeClaimList(in *v1.PersistentVolumeClaimList) {
|
||||
|
@ -2020,20 +2020,26 @@ func ValidatePersistentVolumeStatusUpdate(newPv, oldPv *core.PersistentVolume) f
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// PersistentVolumeClaimSpecValidationOptions contains the different settings for PersistentVolumeClaim validation
|
||||
type PersistentVolumeClaimSpecValidationOptions struct {
|
||||
// Allow spec to contain the "ReadWiteOncePod" access mode
|
||||
AllowReadWriteOncePod bool
|
||||
// Allow pvc expansion after PVC is created and bound to a PV
|
||||
EnableExpansion bool
|
||||
// Allow users to recover from previously failing expansion operation
|
||||
EnableRecoverFromExpansionFailure bool
|
||||
}
|
||||
|
||||
func ValidationOptionsForPersistentVolumeClaim(pvc, oldPvc *core.PersistentVolumeClaim) PersistentVolumeClaimSpecValidationOptions {
|
||||
opts := PersistentVolumeClaimSpecValidationOptions{
|
||||
AllowReadWriteOncePod: utilfeature.DefaultFeatureGate.Enabled(features.ReadWriteOncePod),
|
||||
AllowReadWriteOncePod: utilfeature.DefaultFeatureGate.Enabled(features.ReadWriteOncePod),
|
||||
EnableExpansion: utilfeature.DefaultFeatureGate.Enabled(features.ExpandPersistentVolumes),
|
||||
EnableRecoverFromExpansionFailure: utilfeature.DefaultFeatureGate.Enabled(features.RecoverVolumeExpansionFailure),
|
||||
}
|
||||
if oldPvc == nil {
|
||||
// If there's no old PVC, use the options based solely on feature enablement
|
||||
return opts
|
||||
}
|
||||
|
||||
if helper.ContainsAccessMode(oldPvc.Spec.AccessModes, core.ReadWriteOncePod) {
|
||||
// If the old object allowed "ReadWriteOncePod", continue to allow it in the new object
|
||||
opts.AllowReadWriteOncePod = true
|
||||
@ -2173,7 +2179,7 @@ func ValidatePersistentVolumeClaimUpdate(newPvc, oldPvc *core.PersistentVolumeCl
|
||||
allErrs = append(allErrs, ValidateImmutableAnnotation(newPvc.ObjectMeta.Annotations[v1.BetaStorageClassAnnotation], oldPvc.ObjectMeta.Annotations[v1.BetaStorageClassAnnotation], v1.BetaStorageClassAnnotation, field.NewPath("metadata"))...)
|
||||
}
|
||||
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.ExpandPersistentVolumes) {
|
||||
if opts.EnableExpansion {
|
||||
// lets make sure storage values are same.
|
||||
if newPvc.Status.Phase == core.ClaimBound && newPvcClone.Spec.Resources.Requests != nil {
|
||||
newPvcClone.Spec.Resources.Requests["storage"] = oldPvc.Spec.Resources.Requests["storage"] // +k8s:verify-mutation:reason=clone
|
||||
@ -2181,13 +2187,23 @@ func ValidatePersistentVolumeClaimUpdate(newPvc, oldPvc *core.PersistentVolumeCl
|
||||
|
||||
oldSize := oldPvc.Spec.Resources.Requests["storage"]
|
||||
newSize := newPvc.Spec.Resources.Requests["storage"]
|
||||
statusSize := oldPvc.Status.Capacity["storage"]
|
||||
|
||||
if !apiequality.Semantic.DeepEqual(newPvcClone.Spec, oldPvcClone.Spec) {
|
||||
specDiff := diff.ObjectDiff(newPvcClone.Spec, oldPvcClone.Spec)
|
||||
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec"), fmt.Sprintf("spec is immutable after creation except resources.requests for bound claims\n%v", specDiff)))
|
||||
}
|
||||
if newSize.Cmp(oldSize) < 0 {
|
||||
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "resources", "requests", "storage"), "field can not be less than previous value"))
|
||||
if !opts.EnableRecoverFromExpansionFailure {
|
||||
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "resources", "requests", "storage"), "field can not be less than previous value"))
|
||||
} else {
|
||||
// This validation permits reducing pvc requested size up to capacity recorded in pvc.status
|
||||
// so that users can recover from volume expansion failure, but Kubernetes does not actually
|
||||
// support volume shrinking
|
||||
if newSize.Cmp(statusSize) <= 0 {
|
||||
allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "resources", "requests", "storage"), "field can not be less than status.capacity"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -2220,8 +2236,15 @@ func validateStorageClassUpgrade(oldAnnotations, newAnnotations map[string]strin
|
||||
(!newAnnotationExist || newScInAnnotation == oldSc) /* condition 4 */
|
||||
}
|
||||
|
||||
var resizeStatusSet = sets.NewString(string(core.PersistentVolumeClaimNoExpansionInProgress),
|
||||
string(core.PersistentVolumeClaimControllerExpansionInProgress),
|
||||
string(core.PersistentVolumeClaimControllerExpansionFailed),
|
||||
string(core.PersistentVolumeClaimNodeExpansionPending),
|
||||
string(core.PersistentVolumeClaimNodeExpansionInProgress),
|
||||
string(core.PersistentVolumeClaimNodeExpansionFailed))
|
||||
|
||||
// ValidatePersistentVolumeClaimStatusUpdate validates an update to status of a PersistentVolumeClaim
|
||||
func ValidatePersistentVolumeClaimStatusUpdate(newPvc, oldPvc *core.PersistentVolumeClaim) field.ErrorList {
|
||||
func ValidatePersistentVolumeClaimStatusUpdate(newPvc, oldPvc *core.PersistentVolumeClaim, validationOpts PersistentVolumeClaimSpecValidationOptions) field.ErrorList {
|
||||
allErrs := ValidateObjectMetaUpdate(&newPvc.ObjectMeta, &oldPvc.ObjectMeta, field.NewPath("metadata"))
|
||||
if len(newPvc.ResourceVersion) == 0 {
|
||||
allErrs = append(allErrs, field.Required(field.NewPath("resourceVersion"), ""))
|
||||
@ -2229,10 +2252,32 @@ func ValidatePersistentVolumeClaimStatusUpdate(newPvc, oldPvc *core.PersistentVo
|
||||
if len(newPvc.Spec.AccessModes) == 0 {
|
||||
allErrs = append(allErrs, field.Required(field.NewPath("Spec", "accessModes"), ""))
|
||||
}
|
||||
|
||||
capPath := field.NewPath("status", "capacity")
|
||||
for r, qty := range newPvc.Status.Capacity {
|
||||
allErrs = append(allErrs, validateBasicResource(qty, capPath.Key(string(r)))...)
|
||||
}
|
||||
if validationOpts.EnableRecoverFromExpansionFailure {
|
||||
resizeStatusPath := field.NewPath("status", "resizeStatus")
|
||||
if newPvc.Status.ResizeStatus != nil {
|
||||
resizeStatus := *newPvc.Status.ResizeStatus
|
||||
if !resizeStatusSet.Has(string(resizeStatus)) {
|
||||
allErrs = append(allErrs, field.NotSupported(resizeStatusPath, resizeStatus, resizeStatusSet.List()))
|
||||
}
|
||||
}
|
||||
allocPath := field.NewPath("status", "allocatedResources")
|
||||
for r, qty := range newPvc.Status.AllocatedResources {
|
||||
if r != core.ResourceStorage {
|
||||
allErrs = append(allErrs, field.NotSupported(allocPath, r, []string{string(core.ResourceStorage)}))
|
||||
continue
|
||||
}
|
||||
if errs := validateBasicResource(qty, allocPath.Key(string(r))); len(errs) > 0 {
|
||||
allErrs = append(allErrs, errs...)
|
||||
} else {
|
||||
allErrs = append(allErrs, ValidateResourceQuantityValue(string(core.ResourceStorage), qty, allocPath.Key(string(r)))...)
|
||||
}
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
|
@ -1862,12 +1862,97 @@ func TestValidatePersistentVolumeClaimUpdate(t *testing.T) {
|
||||
},
|
||||
VolumeName: "volume",
|
||||
})
|
||||
validClaimShrinkInitial := testVolumeClaimWithStatus("foo", "ns", core.PersistentVolumeClaimSpec{
|
||||
AccessModes: []core.PersistentVolumeAccessMode{
|
||||
core.ReadWriteOnce,
|
||||
core.ReadOnlyMany,
|
||||
},
|
||||
Resources: core.ResourceRequirements{
|
||||
Requests: core.ResourceList{
|
||||
core.ResourceName(core.ResourceStorage): resource.MustParse("15G"),
|
||||
},
|
||||
},
|
||||
}, core.PersistentVolumeClaimStatus{
|
||||
Phase: core.ClaimBound,
|
||||
Capacity: core.ResourceList{
|
||||
core.ResourceStorage: resource.MustParse("10G"),
|
||||
},
|
||||
})
|
||||
|
||||
unboundShrink := testVolumeClaimWithStatus("foo", "ns", core.PersistentVolumeClaimSpec{
|
||||
AccessModes: []core.PersistentVolumeAccessMode{
|
||||
core.ReadWriteOnce,
|
||||
core.ReadOnlyMany,
|
||||
},
|
||||
Resources: core.ResourceRequirements{
|
||||
Requests: core.ResourceList{
|
||||
core.ResourceName(core.ResourceStorage): resource.MustParse("12G"),
|
||||
},
|
||||
},
|
||||
}, core.PersistentVolumeClaimStatus{
|
||||
Phase: core.ClaimPending,
|
||||
Capacity: core.ResourceList{
|
||||
core.ResourceStorage: resource.MustParse("10G"),
|
||||
},
|
||||
})
|
||||
|
||||
validClaimShrink := testVolumeClaimWithStatus("foo", "ns", core.PersistentVolumeClaimSpec{
|
||||
AccessModes: []core.PersistentVolumeAccessMode{
|
||||
core.ReadWriteOnce,
|
||||
core.ReadOnlyMany,
|
||||
},
|
||||
Resources: core.ResourceRequirements{
|
||||
Requests: core.ResourceList{
|
||||
core.ResourceStorage: resource.MustParse("13G"),
|
||||
},
|
||||
},
|
||||
}, core.PersistentVolumeClaimStatus{
|
||||
Phase: core.ClaimBound,
|
||||
Capacity: core.ResourceList{
|
||||
core.ResourceStorage: resource.MustParse("10G"),
|
||||
},
|
||||
})
|
||||
|
||||
invalidShrinkToStatus := testVolumeClaimWithStatus("foo", "ns", core.PersistentVolumeClaimSpec{
|
||||
AccessModes: []core.PersistentVolumeAccessMode{
|
||||
core.ReadWriteOnce,
|
||||
core.ReadOnlyMany,
|
||||
},
|
||||
Resources: core.ResourceRequirements{
|
||||
Requests: core.ResourceList{
|
||||
core.ResourceStorage: resource.MustParse("10G"),
|
||||
},
|
||||
},
|
||||
}, core.PersistentVolumeClaimStatus{
|
||||
Phase: core.ClaimBound,
|
||||
Capacity: core.ResourceList{
|
||||
core.ResourceStorage: resource.MustParse("10G"),
|
||||
},
|
||||
})
|
||||
|
||||
invalidClaimShrink := testVolumeClaimWithStatus("foo", "ns", core.PersistentVolumeClaimSpec{
|
||||
AccessModes: []core.PersistentVolumeAccessMode{
|
||||
core.ReadWriteOnce,
|
||||
core.ReadOnlyMany,
|
||||
},
|
||||
Resources: core.ResourceRequirements{
|
||||
Requests: core.ResourceList{
|
||||
core.ResourceStorage: resource.MustParse("3G"),
|
||||
},
|
||||
},
|
||||
}, core.PersistentVolumeClaimStatus{
|
||||
Phase: core.ClaimBound,
|
||||
Capacity: core.ResourceList{
|
||||
core.ResourceStorage: resource.MustParse("10G"),
|
||||
},
|
||||
})
|
||||
|
||||
scenarios := map[string]struct {
|
||||
isExpectedFailure bool
|
||||
oldClaim *core.PersistentVolumeClaim
|
||||
newClaim *core.PersistentVolumeClaim
|
||||
enableResize bool
|
||||
isExpectedFailure bool
|
||||
oldClaim *core.PersistentVolumeClaim
|
||||
newClaim *core.PersistentVolumeClaim
|
||||
enableResize bool
|
||||
enableRecoverFromExpansion bool
|
||||
}{
|
||||
"valid-update-volumeName-only": {
|
||||
isExpectedFailure: false,
|
||||
@ -2037,12 +2122,53 @@ func TestValidatePersistentVolumeClaimUpdate(t *testing.T) {
|
||||
newClaim: validClaimRWOPAccessModeAddAnnotation,
|
||||
enableResize: false,
|
||||
},
|
||||
"valid-expand-shrink-resize-enabled": {
|
||||
oldClaim: validClaimShrinkInitial,
|
||||
newClaim: validClaimShrink,
|
||||
enableResize: true,
|
||||
enableRecoverFromExpansion: true,
|
||||
},
|
||||
"invalid-expand-shrink-resize-enabled": {
|
||||
oldClaim: validClaimShrinkInitial,
|
||||
newClaim: invalidClaimShrink,
|
||||
enableResize: true,
|
||||
enableRecoverFromExpansion: true,
|
||||
isExpectedFailure: true,
|
||||
},
|
||||
"invalid-expand-shrink-to-status-resize-enabled": {
|
||||
oldClaim: validClaimShrinkInitial,
|
||||
newClaim: invalidShrinkToStatus,
|
||||
enableResize: true,
|
||||
enableRecoverFromExpansion: true,
|
||||
isExpectedFailure: true,
|
||||
},
|
||||
"invalid-expand-shrink-recover-disabled": {
|
||||
oldClaim: validClaimShrinkInitial,
|
||||
newClaim: validClaimShrink,
|
||||
enableResize: true,
|
||||
enableRecoverFromExpansion: false,
|
||||
isExpectedFailure: true,
|
||||
},
|
||||
"invalid-expand-shrink-resize-disabled": {
|
||||
oldClaim: validClaimShrinkInitial,
|
||||
newClaim: validClaimShrink,
|
||||
enableResize: false,
|
||||
enableRecoverFromExpansion: true,
|
||||
isExpectedFailure: true,
|
||||
},
|
||||
"unbound-size-shrink-resize-enabled": {
|
||||
oldClaim: validClaimShrinkInitial,
|
||||
newClaim: unboundShrink,
|
||||
enableResize: true,
|
||||
enableRecoverFromExpansion: true,
|
||||
isExpectedFailure: true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, scenario := range scenarios {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
// ensure we have a resource version specified for updates
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ExpandPersistentVolumes, scenario.enableResize)()
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.RecoverVolumeExpansionFailure, scenario.enableRecoverFromExpansion)()
|
||||
scenario.oldClaim.ResourceVersion = "1"
|
||||
scenario.newClaim.ResourceVersion = "1"
|
||||
opts := ValidationOptionsForPersistentVolumeClaim(scenario.newClaim, scenario.oldClaim)
|
||||
@ -2067,35 +2193,45 @@ func TestValidationOptionsForPersistentVolumeClaim(t *testing.T) {
|
||||
oldPvc: nil,
|
||||
enableReadWriteOncePod: true,
|
||||
expectValidationOpts: PersistentVolumeClaimSpecValidationOptions{
|
||||
AllowReadWriteOncePod: true,
|
||||
AllowReadWriteOncePod: true,
|
||||
EnableExpansion: true,
|
||||
EnableRecoverFromExpansionFailure: false,
|
||||
},
|
||||
},
|
||||
"rwop allowed because feature enabled": {
|
||||
oldPvc: pvcWithAccessModes([]core.PersistentVolumeAccessMode{core.ReadWriteOnce}),
|
||||
enableReadWriteOncePod: true,
|
||||
expectValidationOpts: PersistentVolumeClaimSpecValidationOptions{
|
||||
AllowReadWriteOncePod: true,
|
||||
AllowReadWriteOncePod: true,
|
||||
EnableExpansion: true,
|
||||
EnableRecoverFromExpansionFailure: false,
|
||||
},
|
||||
},
|
||||
"rwop not allowed because not used and feature disabled": {
|
||||
oldPvc: pvcWithAccessModes([]core.PersistentVolumeAccessMode{core.ReadWriteOnce}),
|
||||
enableReadWriteOncePod: false,
|
||||
expectValidationOpts: PersistentVolumeClaimSpecValidationOptions{
|
||||
AllowReadWriteOncePod: false,
|
||||
AllowReadWriteOncePod: false,
|
||||
EnableExpansion: true,
|
||||
EnableRecoverFromExpansionFailure: false,
|
||||
},
|
||||
},
|
||||
"rwop allowed because used and feature enabled": {
|
||||
oldPvc: pvcWithAccessModes([]core.PersistentVolumeAccessMode{core.ReadWriteOncePod}),
|
||||
enableReadWriteOncePod: true,
|
||||
expectValidationOpts: PersistentVolumeClaimSpecValidationOptions{
|
||||
AllowReadWriteOncePod: true,
|
||||
AllowReadWriteOncePod: true,
|
||||
EnableExpansion: true,
|
||||
EnableRecoverFromExpansionFailure: false,
|
||||
},
|
||||
},
|
||||
"rwop allowed because used and feature disabled": {
|
||||
oldPvc: pvcWithAccessModes([]core.PersistentVolumeAccessMode{core.ReadWriteOncePod}),
|
||||
enableReadWriteOncePod: false,
|
||||
expectValidationOpts: PersistentVolumeClaimSpecValidationOptions{
|
||||
AllowReadWriteOncePod: true,
|
||||
AllowReadWriteOncePod: true,
|
||||
EnableExpansion: true,
|
||||
EnableRecoverFromExpansionFailure: false,
|
||||
},
|
||||
},
|
||||
}
|
||||
@ -15771,11 +15907,86 @@ func TestValidatePersistentVolumeClaimStatusUpdate(t *testing.T) {
|
||||
{Type: core.PersistentVolumeClaimResizing, Status: core.ConditionTrue},
|
||||
},
|
||||
})
|
||||
validAllocatedResources := testVolumeClaimWithStatus("foo", "ns", core.PersistentVolumeClaimSpec{
|
||||
AccessModes: []core.PersistentVolumeAccessMode{
|
||||
core.ReadWriteOnce,
|
||||
core.ReadOnlyMany,
|
||||
},
|
||||
Resources: core.ResourceRequirements{
|
||||
Requests: core.ResourceList{
|
||||
core.ResourceName(core.ResourceStorage): resource.MustParse("10G"),
|
||||
},
|
||||
},
|
||||
}, core.PersistentVolumeClaimStatus{
|
||||
Phase: core.ClaimPending,
|
||||
Conditions: []core.PersistentVolumeClaimCondition{
|
||||
{Type: core.PersistentVolumeClaimResizing, Status: core.ConditionTrue},
|
||||
},
|
||||
AllocatedResources: core.ResourceList{
|
||||
core.ResourceName(core.ResourceStorage): resource.MustParse("10G"),
|
||||
},
|
||||
})
|
||||
|
||||
invalidAllocatedResources := testVolumeClaimWithStatus("foo", "ns", core.PersistentVolumeClaimSpec{
|
||||
AccessModes: []core.PersistentVolumeAccessMode{
|
||||
core.ReadWriteOnce,
|
||||
core.ReadOnlyMany,
|
||||
},
|
||||
Resources: core.ResourceRequirements{
|
||||
Requests: core.ResourceList{
|
||||
core.ResourceName(core.ResourceStorage): resource.MustParse("10G"),
|
||||
},
|
||||
},
|
||||
}, core.PersistentVolumeClaimStatus{
|
||||
Phase: core.ClaimPending,
|
||||
Conditions: []core.PersistentVolumeClaimCondition{
|
||||
{Type: core.PersistentVolumeClaimResizing, Status: core.ConditionTrue},
|
||||
},
|
||||
AllocatedResources: core.ResourceList{
|
||||
core.ResourceName(core.ResourceStorage): resource.MustParse("-10G"),
|
||||
},
|
||||
})
|
||||
|
||||
noStoraegeClaimStatus := testVolumeClaimWithStatus("foo", "ns", core.PersistentVolumeClaimSpec{
|
||||
AccessModes: []core.PersistentVolumeAccessMode{
|
||||
core.ReadWriteOnce,
|
||||
},
|
||||
Resources: core.ResourceRequirements{
|
||||
Requests: core.ResourceList{
|
||||
core.ResourceName(core.ResourceStorage): resource.MustParse("10G"),
|
||||
},
|
||||
},
|
||||
}, core.PersistentVolumeClaimStatus{
|
||||
Phase: core.ClaimPending,
|
||||
AllocatedResources: core.ResourceList{
|
||||
core.ResourceName(core.ResourceCPU): resource.MustParse("10G"),
|
||||
},
|
||||
})
|
||||
progressResizeStatus := core.PersistentVolumeClaimControllerExpansionInProgress
|
||||
invalidResizeStatus := core.PersistentVolumeClaimResizeStatus("foo")
|
||||
|
||||
validResizeStatusPVC := testVolumeClaimWithStatus("foo", "ns", core.PersistentVolumeClaimSpec{
|
||||
AccessModes: []core.PersistentVolumeAccessMode{
|
||||
core.ReadWriteOnce,
|
||||
},
|
||||
}, core.PersistentVolumeClaimStatus{
|
||||
ResizeStatus: &progressResizeStatus,
|
||||
})
|
||||
|
||||
invalidResizeStatusPVC := testVolumeClaimWithStatus("foo", "ns", core.PersistentVolumeClaimSpec{
|
||||
AccessModes: []core.PersistentVolumeAccessMode{
|
||||
core.ReadWriteOnce,
|
||||
},
|
||||
}, core.PersistentVolumeClaimStatus{
|
||||
ResizeStatus: &invalidResizeStatus,
|
||||
})
|
||||
|
||||
scenarios := map[string]struct {
|
||||
isExpectedFailure bool
|
||||
oldClaim *core.PersistentVolumeClaim
|
||||
newClaim *core.PersistentVolumeClaim
|
||||
enableResize bool
|
||||
isExpectedFailure bool
|
||||
oldClaim *core.PersistentVolumeClaim
|
||||
newClaim *core.PersistentVolumeClaim
|
||||
enableResize bool
|
||||
enableRecoverFromExpansion bool
|
||||
}{
|
||||
"condition-update-with-enabled-feature-gate": {
|
||||
isExpectedFailure: false,
|
||||
@ -15783,13 +15994,51 @@ func TestValidatePersistentVolumeClaimStatusUpdate(t *testing.T) {
|
||||
newClaim: validConditionUpdate,
|
||||
enableResize: true,
|
||||
},
|
||||
"status-update-with-valid-allocatedResources-feature-enabled": {
|
||||
isExpectedFailure: false,
|
||||
oldClaim: validClaim,
|
||||
newClaim: validAllocatedResources,
|
||||
enableResize: true,
|
||||
enableRecoverFromExpansion: true,
|
||||
},
|
||||
"status-update-with-invalid-allocatedResources-feature-enabled": {
|
||||
isExpectedFailure: true,
|
||||
oldClaim: validClaim,
|
||||
newClaim: invalidAllocatedResources,
|
||||
enableResize: true,
|
||||
enableRecoverFromExpansion: true,
|
||||
},
|
||||
"status-update-with-no-storage-update": {
|
||||
isExpectedFailure: true,
|
||||
oldClaim: validClaim,
|
||||
newClaim: noStoraegeClaimStatus,
|
||||
enableResize: true,
|
||||
enableRecoverFromExpansion: true,
|
||||
},
|
||||
"status-update-with-valid-pvc-resize-status": {
|
||||
isExpectedFailure: false,
|
||||
oldClaim: validClaim,
|
||||
newClaim: validResizeStatusPVC,
|
||||
enableResize: true,
|
||||
enableRecoverFromExpansion: true,
|
||||
},
|
||||
"status-update-with-invalid-pvc-resize-status": {
|
||||
isExpectedFailure: true,
|
||||
oldClaim: validClaim,
|
||||
newClaim: invalidResizeStatusPVC,
|
||||
enableResize: true,
|
||||
enableRecoverFromExpansion: true,
|
||||
},
|
||||
}
|
||||
for name, scenario := range scenarios {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
validateOpts := PersistentVolumeClaimSpecValidationOptions{
|
||||
EnableRecoverFromExpansionFailure: scenario.enableRecoverFromExpansion,
|
||||
}
|
||||
// ensure we have a resource version specified for updates
|
||||
scenario.oldClaim.ResourceVersion = "1"
|
||||
scenario.newClaim.ResourceVersion = "1"
|
||||
errs := ValidatePersistentVolumeClaimStatusUpdate(scenario.newClaim, scenario.oldClaim)
|
||||
errs := ValidatePersistentVolumeClaimStatusUpdate(scenario.newClaim, scenario.oldClaim, validateOpts)
|
||||
if len(errs) == 0 && scenario.isExpectedFailure {
|
||||
t.Errorf("Unexpected success for scenario: %s", name)
|
||||
}
|
||||
|
12
pkg/apis/core/zz_generated.deepcopy.go
generated
12
pkg/apis/core/zz_generated.deepcopy.go
generated
@ -2977,6 +2977,18 @@ func (in *PersistentVolumeClaimStatus) DeepCopyInto(out *PersistentVolumeClaimSt
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.AllocatedResources != nil {
|
||||
in, out := &in.AllocatedResources, &out.AllocatedResources
|
||||
*out = make(ResourceList, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val.DeepCopy()
|
||||
}
|
||||
}
|
||||
if in.ResizeStatus != nil {
|
||||
in, out := &in.ResizeStatus, &out.ResizeStatus
|
||||
*out = new(PersistentVolumeClaimResizeStatus)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -803,6 +803,13 @@ const (
|
||||
// Honor Persistent Volume Reclaim Policy when it is "Delete" irrespective of PV-PVC
|
||||
// deletion ordering.
|
||||
HonorPVReclaimPolicy featuregate.Feature = "HonorPVReclaimPolicy"
|
||||
|
||||
// owner: @gnufied
|
||||
// kep: http://kep.k8s.io/1790
|
||||
// alpha: v1.23
|
||||
//
|
||||
// Allow users to recover from volume expansion failure
|
||||
RecoverVolumeExpansionFailure featuregate.Feature = "RecoverVolumeExpansionFailure"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@ -920,6 +927,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
|
||||
IdentifyPodOS: {Default: false, PreRelease: featuregate.Alpha},
|
||||
PodAndContainerStatsFromCRI: {Default: false, PreRelease: featuregate.Alpha},
|
||||
HonorPVReclaimPolicy: {Default: false, PreRelease: featuregate.Alpha},
|
||||
RecoverVolumeExpansionFailure: {Default: false, PreRelease: featuregate.Alpha},
|
||||
|
||||
// inherited features from generic apiserver, relisted here to get a conflict if it is changed
|
||||
// unintentionally on either side:
|
||||
|
@ -27,12 +27,10 @@ import (
|
||||
"k8s.io/apiserver/pkg/registry/generic"
|
||||
"k8s.io/apiserver/pkg/storage"
|
||||
"k8s.io/apiserver/pkg/storage/names"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
pvcutil "k8s.io/kubernetes/pkg/api/persistentvolumeclaim"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/apis/core/validation"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
|
||||
)
|
||||
|
||||
@ -66,7 +64,6 @@ func (persistentvolumeclaimStrategy) GetResetFields() map[fieldpath.APIVersion]*
|
||||
func (persistentvolumeclaimStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
|
||||
pvc := obj.(*api.PersistentVolumeClaim)
|
||||
pvc.Status = api.PersistentVolumeClaimStatus{}
|
||||
|
||||
pvcutil.DropDisabledFields(&pvc.Spec)
|
||||
|
||||
// For data sources, we need to do 2 things to implement KEP 1495
|
||||
@ -153,16 +150,17 @@ func (persistentvolumeclaimStatusStrategy) GetResetFields() map[fieldpath.APIVer
|
||||
|
||||
// PrepareForUpdate sets the Spec field which is not allowed to be changed when updating a PV's Status
|
||||
func (persistentvolumeclaimStatusStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.Object) {
|
||||
newPv := obj.(*api.PersistentVolumeClaim)
|
||||
oldPv := old.(*api.PersistentVolumeClaim)
|
||||
newPv.Spec = oldPv.Spec
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.ExpandPersistentVolumes) && oldPv.Status.Conditions == nil {
|
||||
newPv.Status.Conditions = nil
|
||||
}
|
||||
newPVC := obj.(*api.PersistentVolumeClaim)
|
||||
oldPVC := old.(*api.PersistentVolumeClaim)
|
||||
newPVC.Spec = oldPVC.Spec
|
||||
pvcutil.DropDisabledFieldsFromStatus(newPVC, oldPVC)
|
||||
}
|
||||
|
||||
func (persistentvolumeclaimStatusStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {
|
||||
return validation.ValidatePersistentVolumeClaimStatusUpdate(obj.(*api.PersistentVolumeClaim), old.(*api.PersistentVolumeClaim))
|
||||
newPvc := obj.(*api.PersistentVolumeClaim)
|
||||
oldPvc := old.(*api.PersistentVolumeClaim)
|
||||
opts := validation.ValidationOptionsForPersistentVolumeClaim(newPvc, oldPvc)
|
||||
return validation.ValidatePersistentVolumeClaimStatusUpdate(newPvc, oldPvc, opts)
|
||||
}
|
||||
|
||||
// WarningsOnUpdate returns warnings for the given update.
|
||||
|
1997
staging/src/k8s.io/api/core/v1/generated.pb.go
generated
1997
staging/src/k8s.io/api/core/v1/generated.pb.go
generated
File diff suppressed because it is too large
Load Diff
@ -2669,6 +2669,9 @@ message PersistentVolumeClaimSpec {
|
||||
optional k8s.io.apimachinery.pkg.apis.meta.v1.LabelSelector selector = 4;
|
||||
|
||||
// Resources represents the minimum resources the volume should have.
|
||||
// If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements
|
||||
// that are lower than previous value but must still be higher than capacity recorded in the
|
||||
// status field of the claim.
|
||||
// More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources
|
||||
// +optional
|
||||
optional ResourceRequirements resources = 2;
|
||||
@ -2739,6 +2742,26 @@ message PersistentVolumeClaimStatus {
|
||||
// +patchMergeKey=type
|
||||
// +patchStrategy=merge
|
||||
repeated PersistentVolumeClaimCondition conditions = 4;
|
||||
|
||||
// The storage resource within AllocatedResources tracks the capacity allocated to a PVC. It may
|
||||
// be larger than the actual capacity when a volume expansion operation is requested.
|
||||
// For storage quota, the larger value from allocatedResources and PVC.spec.resources is used.
|
||||
// If allocatedResources is not set, PVC.spec.resources alone is used for quota calculation.
|
||||
// If a volume expansion capacity request is lowered, allocatedResources is only
|
||||
// lowered if there are no expansion operations in progress and if the actual volume capacity
|
||||
// is equal or lower than the requested capacity.
|
||||
// This is an alpha field and requires enabling RecoverVolumeExpansionFailure feature.
|
||||
// +featureGate=RecoverVolumeExpansionFailure
|
||||
// +optional
|
||||
map<string, k8s.io.apimachinery.pkg.api.resource.Quantity> allocatedResources = 5;
|
||||
|
||||
// ResizeStatus stores status of resize operation.
|
||||
// ResizeStatus is not set by default but when expansion is complete resizeStatus is set to empty
|
||||
// string by resize controller or kubelet.
|
||||
// This is an alpha field and requires enabling RecoverVolumeExpansionFailure feature.
|
||||
// +featureGate=RecoverVolumeExpansionFailure
|
||||
// +optional
|
||||
optional string resizeStatus = 6;
|
||||
}
|
||||
|
||||
// PersistentVolumeClaimTemplate is used to produce
|
||||
|
@ -472,6 +472,9 @@ type PersistentVolumeClaimSpec struct {
|
||||
// +optional
|
||||
Selector *metav1.LabelSelector `json:"selector,omitempty" protobuf:"bytes,4,opt,name=selector"`
|
||||
// Resources represents the minimum resources the volume should have.
|
||||
// If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements
|
||||
// that are lower than previous value but must still be higher than capacity recorded in the
|
||||
// status field of the claim.
|
||||
// More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources
|
||||
// +optional
|
||||
Resources ResourceRequirements `json:"resources,omitempty" protobuf:"bytes,2,opt,name=resources"`
|
||||
@ -526,6 +529,26 @@ const (
|
||||
PersistentVolumeClaimFileSystemResizePending PersistentVolumeClaimConditionType = "FileSystemResizePending"
|
||||
)
|
||||
|
||||
// +enum
|
||||
type PersistentVolumeClaimResizeStatus string
|
||||
|
||||
const (
|
||||
// When expansion is complete, the empty string is set by resize controller or kubelet.
|
||||
PersistentVolumeClaimNoExpansionInProgress PersistentVolumeClaimResizeStatus = ""
|
||||
// State set when resize controller starts expanding the volume in control-plane
|
||||
PersistentVolumeClaimControllerExpansionInProgress PersistentVolumeClaimResizeStatus = "ControllerExpansionInProgress"
|
||||
// State set when expansion has failed in resize controller with a terminal error.
|
||||
// Transient errors such as timeout should not set this status and should leave ResizeStatus
|
||||
// unmodified, so as resize controller can resume the volume expansion.
|
||||
PersistentVolumeClaimControllerExpansionFailed PersistentVolumeClaimResizeStatus = "ControllerExpansionFailed"
|
||||
// State set when resize controller has finished expanding the volume but further expansion is needed on the node.
|
||||
PersistentVolumeClaimNodeExpansionPending PersistentVolumeClaimResizeStatus = "NodeExpansionPending"
|
||||
// State set when kubelet starts expanding the volume.
|
||||
PersistentVolumeClaimNodeExpansionInProgress PersistentVolumeClaimResizeStatus = "NodeExpansionInProgress"
|
||||
// State set when expansion has failed in kubelet with a terminal error. Transient errors don't set NodeExpansionFailed.
|
||||
PersistentVolumeClaimNodeExpansionFailed PersistentVolumeClaimResizeStatus = "NodeExpansionFailed"
|
||||
)
|
||||
|
||||
// PersistentVolumeClaimCondition contails details about state of pvc
|
||||
type PersistentVolumeClaimCondition struct {
|
||||
Type PersistentVolumeClaimConditionType `json:"type" protobuf:"bytes,1,opt,name=type,casttype=PersistentVolumeClaimConditionType"`
|
||||
@ -564,6 +587,24 @@ type PersistentVolumeClaimStatus struct {
|
||||
// +patchMergeKey=type
|
||||
// +patchStrategy=merge
|
||||
Conditions []PersistentVolumeClaimCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,4,rep,name=conditions"`
|
||||
// The storage resource within AllocatedResources tracks the capacity allocated to a PVC. It may
|
||||
// be larger than the actual capacity when a volume expansion operation is requested.
|
||||
// For storage quota, the larger value from allocatedResources and PVC.spec.resources is used.
|
||||
// If allocatedResources is not set, PVC.spec.resources alone is used for quota calculation.
|
||||
// If a volume expansion capacity request is lowered, allocatedResources is only
|
||||
// lowered if there are no expansion operations in progress and if the actual volume capacity
|
||||
// is equal or lower than the requested capacity.
|
||||
// This is an alpha field and requires enabling RecoverVolumeExpansionFailure feature.
|
||||
// +featureGate=RecoverVolumeExpansionFailure
|
||||
// +optional
|
||||
AllocatedResources ResourceList `json:"allocatedResources,omitempty" protobuf:"bytes,5,rep,name=allocatedResources,casttype=ResourceList,castkey=ResourceName"`
|
||||
// ResizeStatus stores status of resize operation.
|
||||
// ResizeStatus is not set by default but when expansion is complete resizeStatus is set to empty
|
||||
// string by resize controller or kubelet.
|
||||
// This is an alpha field and requires enabling RecoverVolumeExpansionFailure feature.
|
||||
// +featureGate=RecoverVolumeExpansionFailure
|
||||
// +optional
|
||||
ResizeStatus *PersistentVolumeClaimResizeStatus `json:"resizeStatus,omitempty" protobuf:"bytes,6,opt,name=resizeStatus,casttype=PersistentVolumeClaimResizeStatus"`
|
||||
}
|
||||
|
||||
type PersistentVolumeAccessMode string
|
||||
|
@ -1297,7 +1297,7 @@ var map_PersistentVolumeClaimSpec = map[string]string{
|
||||
"": "PersistentVolumeClaimSpec describes the common attributes of storage devices and allows a Source for provider-specific attributes",
|
||||
"accessModes": "AccessModes contains the desired access modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1",
|
||||
"selector": "A label query over volumes to consider for binding.",
|
||||
"resources": "Resources represents the minimum resources the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources",
|
||||
"resources": "Resources represents the minimum resources the volume should have. If RecoverVolumeExpansionFailure feature is enabled users are allowed to specify resource requirements that are lower than previous value but must still be higher than capacity recorded in the status field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources",
|
||||
"volumeName": "VolumeName is the binding reference to the PersistentVolume backing this claim.",
|
||||
"storageClassName": "Name of the StorageClass required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1",
|
||||
"volumeMode": "volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec.",
|
||||
@ -1310,11 +1310,13 @@ func (PersistentVolumeClaimSpec) SwaggerDoc() map[string]string {
|
||||
}
|
||||
|
||||
var map_PersistentVolumeClaimStatus = map[string]string{
|
||||
"": "PersistentVolumeClaimStatus is the current status of a persistent volume claim.",
|
||||
"phase": "Phase represents the current phase of PersistentVolumeClaim.",
|
||||
"accessModes": "AccessModes contains the actual access modes the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1",
|
||||
"capacity": "Represents the actual resources of the underlying volume.",
|
||||
"conditions": "Current Condition of persistent volume claim. If underlying persistent volume is being resized then the Condition will be set to 'ResizeStarted'.",
|
||||
"": "PersistentVolumeClaimStatus is the current status of a persistent volume claim.",
|
||||
"phase": "Phase represents the current phase of PersistentVolumeClaim.",
|
||||
"accessModes": "AccessModes contains the actual access modes the volume backing the PVC has. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1",
|
||||
"capacity": "Represents the actual resources of the underlying volume.",
|
||||
"conditions": "Current Condition of persistent volume claim. If underlying persistent volume is being resized then the Condition will be set to 'ResizeStarted'.",
|
||||
"allocatedResources": "The storage resource within AllocatedResources tracks the capacity allocated to a PVC. It may be larger than the actual capacity when a volume expansion operation is requested. For storage quota, the larger value from allocatedResources and PVC.spec.resources is used. If allocatedResources is not set, PVC.spec.resources alone is used for quota calculation. If a volume expansion capacity request is lowered, allocatedResources is only lowered if there are no expansion operations in progress and if the actual volume capacity is equal or lower than the requested capacity. This is an alpha field and requires enabling RecoverVolumeExpansionFailure feature.",
|
||||
"resizeStatus": "ResizeStatus stores status of resize operation. ResizeStatus is not set by default but when expansion is complete resizeStatus is set to empty string by resize controller or kubelet. This is an alpha field and requires enabling RecoverVolumeExpansionFailure feature.",
|
||||
}
|
||||
|
||||
func (PersistentVolumeClaimStatus) SwaggerDoc() map[string]string {
|
||||
|
@ -2975,6 +2975,18 @@ func (in *PersistentVolumeClaimStatus) DeepCopyInto(out *PersistentVolumeClaimSt
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.AllocatedResources != nil {
|
||||
in, out := &in.AllocatedResources, &out.AllocatedResources
|
||||
*out = make(ResourceList, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val.DeepCopy()
|
||||
}
|
||||
}
|
||||
if in.ResizeStatus != nil {
|
||||
in, out := &in.ResizeStatus, &out.ResizeStatus
|
||||
*out = new(PersistentVolumeClaimResizeStatus)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -1642,39 +1642,43 @@
|
||||
"reason": "523",
|
||||
"message": "524"
|
||||
}
|
||||
]
|
||||
],
|
||||
"allocatedResources": {
|
||||
"鐳VDɝ": "844"
|
||||
},
|
||||
"resizeStatus": "但Ǭľa执mÎDƃ"
|
||||
}
|
||||
}
|
||||
],
|
||||
"serviceName": "525",
|
||||
"podManagementPolicy": "婵=ǻ",
|
||||
"podManagementPolicy": "ƌ妜;)t罎j´A",
|
||||
"updateStrategy": {
|
||||
"type": "ɝÔȗ$`Ž#",
|
||||
"type": "徙蔿Yċʤw俣Ǫ",
|
||||
"rollingUpdate": {
|
||||
"partition": -1644040574
|
||||
"partition": 2000146968
|
||||
}
|
||||
},
|
||||
"revisionHistoryLimit": -1205784111,
|
||||
"minReadySeconds": 1505300966
|
||||
"revisionHistoryLimit": 560461224,
|
||||
"minReadySeconds": 2059121580
|
||||
},
|
||||
"status": {
|
||||
"observedGeneration": 7422250233075984176,
|
||||
"replicas": -326265137,
|
||||
"readyReplicas": 1683394621,
|
||||
"currentReplicas": 1862659237,
|
||||
"updatedReplicas": 798811297,
|
||||
"observedGeneration": -632886252136267545,
|
||||
"replicas": 750655684,
|
||||
"readyReplicas": -1012893423,
|
||||
"currentReplicas": -1295777734,
|
||||
"updatedReplicas": -1394190312,
|
||||
"currentRevision": "526",
|
||||
"updateRevision": "527",
|
||||
"collisionCount": -1290326833,
|
||||
"collisionCount": 1077247354,
|
||||
"conditions": [
|
||||
{
|
||||
"type": "´Aƺå嫹^Ȇɀ*ǹ",
|
||||
"status": "蟷尨BABȳ",
|
||||
"lastTransitionTime": "2464-04-30T23:47:03Z",
|
||||
"type": "堏ȑ湸睑L暱ʖ妾崗",
|
||||
"status": "ij敪賻yʗHiv\u003c",
|
||||
"lastTransitionTime": "2814-04-22T10:44:02Z",
|
||||
"reason": "528",
|
||||
"message": "529"
|
||||
}
|
||||
],
|
||||
"availableReplicas": -1012893423
|
||||
"availableReplicas": 747018016
|
||||
}
|
||||
}
|
Binary file not shown.
@ -31,10 +31,10 @@ metadata:
|
||||
selfLink: "5"
|
||||
uid: "7"
|
||||
spec:
|
||||
minReadySeconds: 1505300966
|
||||
podManagementPolicy: 婵=ǻ
|
||||
minReadySeconds: 2059121580
|
||||
podManagementPolicy: ƌ妜;)t罎j´A
|
||||
replicas: 896585016
|
||||
revisionHistoryLimit: -1205784111
|
||||
revisionHistoryLimit: 560461224
|
||||
selector:
|
||||
matchExpressions:
|
||||
- key: 50-u--25cu87--r7p-w1e67-8pj5t-kl-v0q6b68--nu5oii38fn-8.629b-jd-8c45-0-8--6n--w0--w---196g8d--iv1-5--5ht-a-29--0qso796/3___47._49pIB_o61ISU4--A_.XK_._M99
|
||||
@ -1060,8 +1060,8 @@ spec:
|
||||
volumePath: "103"
|
||||
updateStrategy:
|
||||
rollingUpdate:
|
||||
partition: -1644040574
|
||||
type: ɝÔȗ$`Ž#
|
||||
partition: 2000146968
|
||||
type: 徙蔿Yċʤw俣Ǫ
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
annotations:
|
||||
@ -1123,6 +1123,8 @@ spec:
|
||||
status:
|
||||
accessModes:
|
||||
- v}鮩澊聝楧
|
||||
allocatedResources:
|
||||
鐳VDɝ: "844"
|
||||
capacity:
|
||||
问Ð7ɞŶJŖ)j{驟ʦcȃ: "657"
|
||||
conditions:
|
||||
@ -1133,19 +1135,20 @@ spec:
|
||||
status: Q¢鬣_棈Ý泷
|
||||
type: ņȎZȐ樾'Ż£劾ů
|
||||
phase: 忣àÂƺ琰Ȃ芋醳鮩!廊臚cɶċ
|
||||
resizeStatus: 但Ǭľa执mÎDƃ
|
||||
status:
|
||||
availableReplicas: -1012893423
|
||||
collisionCount: -1290326833
|
||||
availableReplicas: 747018016
|
||||
collisionCount: 1077247354
|
||||
conditions:
|
||||
- lastTransitionTime: "2464-04-30T23:47:03Z"
|
||||
- lastTransitionTime: "2814-04-22T10:44:02Z"
|
||||
message: "529"
|
||||
reason: "528"
|
||||
status: 蟷尨BABȳ
|
||||
type: ´Aƺå嫹^Ȇɀ*ǹ
|
||||
currentReplicas: 1862659237
|
||||
status: ij敪賻yʗHiv<
|
||||
type: 堏ȑ湸睑L暱ʖ妾崗
|
||||
currentReplicas: -1295777734
|
||||
currentRevision: "526"
|
||||
observedGeneration: 7422250233075984176
|
||||
readyReplicas: 1683394621
|
||||
replicas: -326265137
|
||||
observedGeneration: -632886252136267545
|
||||
readyReplicas: -1012893423
|
||||
replicas: 750655684
|
||||
updateRevision: "527"
|
||||
updatedReplicas: 798811297
|
||||
updatedReplicas: -1394190312
|
||||
|
@ -1642,39 +1642,43 @@
|
||||
"reason": "523",
|
||||
"message": "524"
|
||||
}
|
||||
]
|
||||
],
|
||||
"allocatedResources": {
|
||||
"鐳VDɝ": "844"
|
||||
},
|
||||
"resizeStatus": "但Ǭľa执mÎDƃ"
|
||||
}
|
||||
}
|
||||
],
|
||||
"serviceName": "525",
|
||||
"podManagementPolicy": "婵=ǻ",
|
||||
"podManagementPolicy": "ƌ妜;)t罎j´A",
|
||||
"updateStrategy": {
|
||||
"type": "ɝÔȗ$`Ž#",
|
||||
"type": "徙蔿Yċʤw俣Ǫ",
|
||||
"rollingUpdate": {
|
||||
"partition": -1644040574
|
||||
"partition": 2000146968
|
||||
}
|
||||
},
|
||||
"revisionHistoryLimit": -1205784111,
|
||||
"minReadySeconds": 1505300966
|
||||
"revisionHistoryLimit": 560461224,
|
||||
"minReadySeconds": 2059121580
|
||||
},
|
||||
"status": {
|
||||
"observedGeneration": 2345785178116014414,
|
||||
"replicas": 923301621,
|
||||
"readyReplicas": 2036280873,
|
||||
"currentReplicas": 2102009515,
|
||||
"updatedReplicas": -1974512490,
|
||||
"observedGeneration": -8200913189823252840,
|
||||
"replicas": 1892314617,
|
||||
"readyReplicas": -1893854851,
|
||||
"currentReplicas": 658548230,
|
||||
"updatedReplicas": -301228056,
|
||||
"currentRevision": "526",
|
||||
"updateRevision": "527",
|
||||
"collisionCount": -1001798049,
|
||||
"collisionCount": 446542989,
|
||||
"conditions": [
|
||||
{
|
||||
"type": "Ǒl徙蔿Yċʤw",
|
||||
"status": "ǹ脡È6",
|
||||
"lastTransitionTime": "2744-07-10T16:37:22Z",
|
||||
"type": "Ǚ3洠º襊Ł靫挕欰ij敪賻yʗHiv",
|
||||
"status": "V汦\u003e蒃U",
|
||||
"lastTransitionTime": "2800-08-07T22:03:04Z",
|
||||
"reason": "528",
|
||||
"message": "529"
|
||||
}
|
||||
],
|
||||
"availableReplicas": -180607525
|
||||
"availableReplicas": -2059927818
|
||||
}
|
||||
}
|
Binary file not shown.
@ -31,10 +31,10 @@ metadata:
|
||||
selfLink: "5"
|
||||
uid: "7"
|
||||
spec:
|
||||
minReadySeconds: 1505300966
|
||||
podManagementPolicy: 婵=ǻ
|
||||
minReadySeconds: 2059121580
|
||||
podManagementPolicy: ƌ妜;)t罎j´A
|
||||
replicas: 896585016
|
||||
revisionHistoryLimit: -1205784111
|
||||
revisionHistoryLimit: 560461224
|
||||
selector:
|
||||
matchExpressions:
|
||||
- key: 50-u--25cu87--r7p-w1e67-8pj5t-kl-v0q6b68--nu5oii38fn-8.629b-jd-8c45-0-8--6n--w0--w---196g8d--iv1-5--5ht-a-29--0qso796/3___47._49pIB_o61ISU4--A_.XK_._M99
|
||||
@ -1060,8 +1060,8 @@ spec:
|
||||
volumePath: "103"
|
||||
updateStrategy:
|
||||
rollingUpdate:
|
||||
partition: -1644040574
|
||||
type: ɝÔȗ$`Ž#
|
||||
partition: 2000146968
|
||||
type: 徙蔿Yċʤw俣Ǫ
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
annotations:
|
||||
@ -1123,6 +1123,8 @@ spec:
|
||||
status:
|
||||
accessModes:
|
||||
- v}鮩澊聝楧
|
||||
allocatedResources:
|
||||
鐳VDɝ: "844"
|
||||
capacity:
|
||||
问Ð7ɞŶJŖ)j{驟ʦcȃ: "657"
|
||||
conditions:
|
||||
@ -1133,19 +1135,20 @@ spec:
|
||||
status: Q¢鬣_棈Ý泷
|
||||
type: ņȎZȐ樾'Ż£劾ů
|
||||
phase: 忣àÂƺ琰Ȃ芋醳鮩!廊臚cɶċ
|
||||
resizeStatus: 但Ǭľa执mÎDƃ
|
||||
status:
|
||||
availableReplicas: -180607525
|
||||
collisionCount: -1001798049
|
||||
availableReplicas: -2059927818
|
||||
collisionCount: 446542989
|
||||
conditions:
|
||||
- lastTransitionTime: "2744-07-10T16:37:22Z"
|
||||
- lastTransitionTime: "2800-08-07T22:03:04Z"
|
||||
message: "529"
|
||||
reason: "528"
|
||||
status: ǹ脡È6
|
||||
type: Ǒl徙蔿Yċʤw
|
||||
currentReplicas: 2102009515
|
||||
status: V汦>蒃U
|
||||
type: Ǚ3洠º襊Ł靫挕欰ij敪賻yʗHiv
|
||||
currentReplicas: 658548230
|
||||
currentRevision: "526"
|
||||
observedGeneration: 2345785178116014414
|
||||
readyReplicas: 2036280873
|
||||
replicas: 923301621
|
||||
observedGeneration: -8200913189823252840
|
||||
readyReplicas: -1893854851
|
||||
replicas: 1892314617
|
||||
updateRevision: "527"
|
||||
updatedReplicas: -1974512490
|
||||
updatedReplicas: -301228056
|
||||
|
@ -1642,39 +1642,43 @@
|
||||
"reason": "523",
|
||||
"message": "524"
|
||||
}
|
||||
]
|
||||
],
|
||||
"allocatedResources": {
|
||||
"鐳VDɝ": "844"
|
||||
},
|
||||
"resizeStatus": "但Ǭľa执mÎDƃ"
|
||||
}
|
||||
}
|
||||
],
|
||||
"serviceName": "525",
|
||||
"podManagementPolicy": "婵=ǻ",
|
||||
"podManagementPolicy": "ƌ妜;)t罎j´A",
|
||||
"updateStrategy": {
|
||||
"type": "ɝÔȗ$`Ž#",
|
||||
"type": "徙蔿Yċʤw俣Ǫ",
|
||||
"rollingUpdate": {
|
||||
"partition": -1644040574
|
||||
"partition": 2000146968
|
||||
}
|
||||
},
|
||||
"revisionHistoryLimit": -1205784111,
|
||||
"minReadySeconds": 1505300966
|
||||
"revisionHistoryLimit": 560461224,
|
||||
"minReadySeconds": 2059121580
|
||||
},
|
||||
"status": {
|
||||
"observedGeneration": 7422250233075984176,
|
||||
"replicas": -326265137,
|
||||
"readyReplicas": 1683394621,
|
||||
"currentReplicas": 1862659237,
|
||||
"updatedReplicas": 798811297,
|
||||
"observedGeneration": -632886252136267545,
|
||||
"replicas": 750655684,
|
||||
"readyReplicas": -1012893423,
|
||||
"currentReplicas": -1295777734,
|
||||
"updatedReplicas": -1394190312,
|
||||
"currentRevision": "526",
|
||||
"updateRevision": "527",
|
||||
"collisionCount": -1290326833,
|
||||
"collisionCount": 1077247354,
|
||||
"conditions": [
|
||||
{
|
||||
"type": "´Aƺå嫹^Ȇɀ*ǹ",
|
||||
"status": "蟷尨BABȳ",
|
||||
"lastTransitionTime": "2464-04-30T23:47:03Z",
|
||||
"type": "堏ȑ湸睑L暱ʖ妾崗",
|
||||
"status": "ij敪賻yʗHiv\u003c",
|
||||
"lastTransitionTime": "2814-04-22T10:44:02Z",
|
||||
"reason": "528",
|
||||
"message": "529"
|
||||
}
|
||||
],
|
||||
"availableReplicas": -1012893423
|
||||
"availableReplicas": 747018016
|
||||
}
|
||||
}
|
Binary file not shown.
@ -31,10 +31,10 @@ metadata:
|
||||
selfLink: "5"
|
||||
uid: "7"
|
||||
spec:
|
||||
minReadySeconds: 1505300966
|
||||
podManagementPolicy: 婵=ǻ
|
||||
minReadySeconds: 2059121580
|
||||
podManagementPolicy: ƌ妜;)t罎j´A
|
||||
replicas: 896585016
|
||||
revisionHistoryLimit: -1205784111
|
||||
revisionHistoryLimit: 560461224
|
||||
selector:
|
||||
matchExpressions:
|
||||
- key: 50-u--25cu87--r7p-w1e67-8pj5t-kl-v0q6b68--nu5oii38fn-8.629b-jd-8c45-0-8--6n--w0--w---196g8d--iv1-5--5ht-a-29--0qso796/3___47._49pIB_o61ISU4--A_.XK_._M99
|
||||
@ -1060,8 +1060,8 @@ spec:
|
||||
volumePath: "103"
|
||||
updateStrategy:
|
||||
rollingUpdate:
|
||||
partition: -1644040574
|
||||
type: ɝÔȗ$`Ž#
|
||||
partition: 2000146968
|
||||
type: 徙蔿Yċʤw俣Ǫ
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
annotations:
|
||||
@ -1123,6 +1123,8 @@ spec:
|
||||
status:
|
||||
accessModes:
|
||||
- v}鮩澊聝楧
|
||||
allocatedResources:
|
||||
鐳VDɝ: "844"
|
||||
capacity:
|
||||
问Ð7ɞŶJŖ)j{驟ʦcȃ: "657"
|
||||
conditions:
|
||||
@ -1133,19 +1135,20 @@ spec:
|
||||
status: Q¢鬣_棈Ý泷
|
||||
type: ņȎZȐ樾'Ż£劾ů
|
||||
phase: 忣àÂƺ琰Ȃ芋醳鮩!廊臚cɶċ
|
||||
resizeStatus: 但Ǭľa执mÎDƃ
|
||||
status:
|
||||
availableReplicas: -1012893423
|
||||
collisionCount: -1290326833
|
||||
availableReplicas: 747018016
|
||||
collisionCount: 1077247354
|
||||
conditions:
|
||||
- lastTransitionTime: "2464-04-30T23:47:03Z"
|
||||
- lastTransitionTime: "2814-04-22T10:44:02Z"
|
||||
message: "529"
|
||||
reason: "528"
|
||||
status: 蟷尨BABȳ
|
||||
type: ´Aƺå嫹^Ȇɀ*ǹ
|
||||
currentReplicas: 1862659237
|
||||
status: ij敪賻yʗHiv<
|
||||
type: 堏ȑ湸睑L暱ʖ妾崗
|
||||
currentReplicas: -1295777734
|
||||
currentRevision: "526"
|
||||
observedGeneration: 7422250233075984176
|
||||
readyReplicas: 1683394621
|
||||
replicas: -326265137
|
||||
observedGeneration: -632886252136267545
|
||||
readyReplicas: -1012893423
|
||||
replicas: 750655684
|
||||
updateRevision: "527"
|
||||
updatedReplicas: 798811297
|
||||
updatedReplicas: -1394190312
|
||||
|
@ -95,6 +95,10 @@
|
||||
"reason": "34",
|
||||
"message": "35"
|
||||
}
|
||||
]
|
||||
],
|
||||
"allocatedResources": {
|
||||
" u衲\u003c¿燥": "98"
|
||||
},
|
||||
"resizeStatus": "{舁吉蓨O澘"
|
||||
}
|
||||
}
|
Binary file not shown.
@ -58,6 +58,8 @@ spec:
|
||||
status:
|
||||
accessModes:
|
||||
- l殛瓷雼浢Ü礽
|
||||
allocatedResources:
|
||||
' u衲<¿燥': "98"
|
||||
capacity:
|
||||
'{囥': "721"
|
||||
conditions:
|
||||
@ -68,3 +70,4 @@ status:
|
||||
status: Ka縳讋ɮ衺勽Ƙq
|
||||
type: n(鲼ƳÐƣKʘńw:5塋訩塶"=
|
||||
phase: gɸ=ǤÆ碛,1ZƜ/C龷Ȫ
|
||||
resizeStatus: '{舁吉蓨O澘'
|
||||
|
@ -25,10 +25,12 @@ import (
|
||||
// PersistentVolumeClaimStatusApplyConfiguration represents an declarative configuration of the PersistentVolumeClaimStatus type for use
|
||||
// with apply.
|
||||
type PersistentVolumeClaimStatusApplyConfiguration struct {
|
||||
Phase *v1.PersistentVolumeClaimPhase `json:"phase,omitempty"`
|
||||
AccessModes []v1.PersistentVolumeAccessMode `json:"accessModes,omitempty"`
|
||||
Capacity *v1.ResourceList `json:"capacity,omitempty"`
|
||||
Conditions []PersistentVolumeClaimConditionApplyConfiguration `json:"conditions,omitempty"`
|
||||
Phase *v1.PersistentVolumeClaimPhase `json:"phase,omitempty"`
|
||||
AccessModes []v1.PersistentVolumeAccessMode `json:"accessModes,omitempty"`
|
||||
Capacity *v1.ResourceList `json:"capacity,omitempty"`
|
||||
Conditions []PersistentVolumeClaimConditionApplyConfiguration `json:"conditions,omitempty"`
|
||||
AllocatedResources *v1.ResourceList `json:"allocatedResources,omitempty"`
|
||||
ResizeStatus *v1.PersistentVolumeClaimResizeStatus `json:"resizeStatus,omitempty"`
|
||||
}
|
||||
|
||||
// PersistentVolumeClaimStatusApplyConfiguration constructs an declarative configuration of the PersistentVolumeClaimStatus type for use with
|
||||
@ -75,3 +77,19 @@ func (b *PersistentVolumeClaimStatusApplyConfiguration) WithConditions(values ..
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// WithAllocatedResources sets the AllocatedResources field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the AllocatedResources field is set to the value of the last call.
|
||||
func (b *PersistentVolumeClaimStatusApplyConfiguration) WithAllocatedResources(value v1.ResourceList) *PersistentVolumeClaimStatusApplyConfiguration {
|
||||
b.AllocatedResources = &value
|
||||
return b
|
||||
}
|
||||
|
||||
// WithResizeStatus sets the ResizeStatus field in the declarative configuration to the given value
|
||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||
// If called multiple times, the ResizeStatus field is set to the value of the last call.
|
||||
func (b *PersistentVolumeClaimStatusApplyConfiguration) WithResizeStatus(value v1.PersistentVolumeClaimResizeStatus) *PersistentVolumeClaimStatusApplyConfiguration {
|
||||
b.ResizeStatus = &value
|
||||
return b
|
||||
}
|
||||
|
@ -5291,6 +5291,11 @@ var schemaYAML = typed.YAMLObject(`types:
|
||||
elementType:
|
||||
scalar: string
|
||||
elementRelationship: atomic
|
||||
- name: allocatedResources
|
||||
type:
|
||||
map:
|
||||
elementType:
|
||||
namedType: io.k8s.apimachinery.pkg.api.resource.Quantity
|
||||
- name: capacity
|
||||
type:
|
||||
map:
|
||||
@ -5307,6 +5312,9 @@ var schemaYAML = typed.YAMLObject(`types:
|
||||
- name: phase
|
||||
type:
|
||||
scalar: string
|
||||
- name: resizeStatus
|
||||
type:
|
||||
scalar: string
|
||||
- name: io.k8s.api.core.v1.PersistentVolumeClaimTemplate
|
||||
map:
|
||||
fields:
|
||||
|
Loading…
Reference in New Issue
Block a user