-
Notifications
You must be signed in to change notification settings - Fork 39.7k
/
util.go
157 lines (137 loc) · 5.34 KB
/
util.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package persistentvolumeclaim
import (
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/features"
)
const (
pvc string = "PersistentVolumeClaim"
volumeSnapshot string = "VolumeSnapshot"
)
// DropDisabledFields removes disabled fields from the pvc spec.
// This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a pvc spec.
func DropDisabledFields(pvcSpec *core.PersistentVolumeClaimSpec) {
// Drop the contents of the dataSourceRef field if the AnyVolumeDataSource
// feature gate is disabled.
if !utilfeature.DefaultFeatureGate.Enabled(features.AnyVolumeDataSource) {
pvcSpec.DataSourceRef = nil
}
}
// EnforceDataSourceBackwardsCompatibility drops the data source field under certain conditions
// to maintain backwards compatibility with old behavior.
// See KEP 1495 for details.
// Specifically, if this is an update of a PVC with no data source, or a creation of a new PVC,
// and the dataSourceRef field is not filled in, then we will drop "invalid" data sources
// (anything other than a PVC or a VolumeSnapshot) from this request as if an empty PVC had
// been requested.
// This should be called after DropDisabledFields so that if the AnyVolumeDataSource feature
// gate is disabled, dataSourceRef will be forced to empty, ensuring pre-1.22 behavior.
// This should be called before NormalizeDataSources, so that data sources other than PVCs
// and VolumeSnapshots can only be set through the dataSourceRef field and not the dataSource
// field.
func EnforceDataSourceBackwardsCompatibility(pvcSpec, oldPVCSpec *core.PersistentVolumeClaimSpec) {
// Check if the old PVC has a data source here is so that on updates from old clients
// that omit dataSourceRef, we preserve the data source, even if it would have been
// invalid to specify it at using the dataSource field at create.
if dataSourceInUse(oldPVCSpec) {
return
}
// Check if dataSourceRef is empty is because if it's not empty, then there is
// definitely a newer client and it definitely either wants to create a non-empty
// volume, or it wants to update a PVC that has a data source. Whether the
// specified data source is valid or satisfiable is a matter for validation and
// the volume populator code, but we can say with certainty that the client is
// not expecting the legacy behavior of ignoring invalid data sources.
if pvcSpec.DataSourceRef != nil {
return
}
// Historically, we only allow PVCs and VolumeSnapshots in the dataSource field.
// All other values are silently dropped.
if !dataSourceIsPvcOrSnapshot(pvcSpec.DataSource) {
pvcSpec.DataSource = nil
}
}
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
}
if oldPVCSpec.DataSource != nil || oldPVCSpec.DataSourceRef != nil {
return true
}
return false
}
func dataSourceIsPvcOrSnapshot(dataSource *core.TypedLocalObjectReference) bool {
if dataSource != nil {
apiGroup := ""
if dataSource.APIGroup != nil {
apiGroup = *dataSource.APIGroup
}
if dataSource.Kind == pvc &&
apiGroup == "" {
return true
}
if dataSource.Kind == volumeSnapshot && apiGroup == "snapshot.storage.k8s.io" {
return true
}
}
return false
}
// NormalizeDataSources ensures that DataSource and DataSourceRef have the same contents
// as long as both are not explicitly set.
// This should be used by creates/gets of PVCs, but not updates
func NormalizeDataSources(pvcSpec *core.PersistentVolumeClaimSpec) {
// Don't enable this behavior if the feature gate is not on
if !utilfeature.DefaultFeatureGate.Enabled(features.AnyVolumeDataSource) {
return
}
if pvcSpec.DataSource != nil && pvcSpec.DataSourceRef == nil {
// Using the old way of setting a data source
pvcSpec.DataSourceRef = pvcSpec.DataSource.DeepCopy()
} else if pvcSpec.DataSourceRef != nil && pvcSpec.DataSource == nil {
// Using the new way of setting a data source
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
}