mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-21 10:51:29 +00:00
Promote VolumeSubpathEnvExpansion feature gate to GA
This commit is contained in:
parent
2d8b8703de
commit
cb8a7c1a4c
2
api/openapi-spec/swagger.json
generated
2
api/openapi-spec/swagger.json
generated
@ -11917,7 +11917,7 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"subPathExpr": {
|
"subPathExpr": {
|
||||||
"description": "Expanded path within the volume from which the container's volume should be mounted. Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. Defaults to \"\" (volume's root). SubPathExpr and SubPath are mutually exclusive. This field is beta in 1.15.",
|
"description": "Expanded path within the volume from which the container's volume should be mounted. Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. Defaults to \"\" (volume's root). SubPathExpr and SubPath are mutually exclusive.",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -1935,52 +1935,51 @@ func TestDropSubPathExpr(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, enabled := range []bool{true, false} {
|
enabled := true
|
||||||
for _, oldPodInfo := range podInfo {
|
for _, oldPodInfo := range podInfo {
|
||||||
for _, newPodInfo := range podInfo {
|
for _, newPodInfo := range podInfo {
|
||||||
oldPodHasSubpaths, oldPod := oldPodInfo.hasSubpaths, oldPodInfo.pod()
|
oldPodHasSubpaths, oldPod := oldPodInfo.hasSubpaths, oldPodInfo.pod()
|
||||||
newPodHasSubpaths, newPod := newPodInfo.hasSubpaths, newPodInfo.pod()
|
newPodHasSubpaths, newPod := newPodInfo.hasSubpaths, newPodInfo.pod()
|
||||||
if newPod == nil {
|
if newPod == nil {
|
||||||
continue
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run(fmt.Sprintf("feature enabled=%v, old pod %v, new pod %v", enabled, oldPodInfo.description, newPodInfo.description), func(t *testing.T) {
|
||||||
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeSubpathEnvExpansion, enabled)()
|
||||||
|
|
||||||
|
var oldPodSpec *api.PodSpec
|
||||||
|
if oldPod != nil {
|
||||||
|
oldPodSpec = &oldPod.Spec
|
||||||
|
}
|
||||||
|
dropDisabledFields(&newPod.Spec, nil, oldPodSpec, nil)
|
||||||
|
|
||||||
|
// old pod should never be changed
|
||||||
|
if !reflect.DeepEqual(oldPod, oldPodInfo.pod()) {
|
||||||
|
t.Errorf("old pod changed: %v", diff.ObjectReflectDiff(oldPod, oldPodInfo.pod()))
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Run(fmt.Sprintf("feature enabled=%v, old pod %v, new pod %v", enabled, oldPodInfo.description, newPodInfo.description), func(t *testing.T) {
|
switch {
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeSubpathEnvExpansion, enabled)()
|
case enabled || oldPodHasSubpaths:
|
||||||
|
// new pod should not be changed if the feature is enabled, or if the old pod had subpaths
|
||||||
var oldPodSpec *api.PodSpec
|
if !reflect.DeepEqual(newPod, newPodInfo.pod()) {
|
||||||
if oldPod != nil {
|
t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodInfo.pod()))
|
||||||
oldPodSpec = &oldPod.Spec
|
|
||||||
}
|
}
|
||||||
dropDisabledFields(&newPod.Spec, nil, oldPodSpec, nil)
|
case newPodHasSubpaths:
|
||||||
|
// new pod should be changed
|
||||||
// old pod should never be changed
|
if reflect.DeepEqual(newPod, newPodInfo.pod()) {
|
||||||
if !reflect.DeepEqual(oldPod, oldPodInfo.pod()) {
|
t.Errorf("new pod was not changed")
|
||||||
t.Errorf("old pod changed: %v", diff.ObjectReflectDiff(oldPod, oldPodInfo.pod()))
|
|
||||||
}
|
}
|
||||||
|
// new pod should not have subpaths
|
||||||
switch {
|
if !reflect.DeepEqual(newPod, podWithoutSubpaths()) {
|
||||||
case enabled || oldPodHasSubpaths:
|
t.Errorf("new pod had subpaths: %v", diff.ObjectReflectDiff(newPod, podWithoutSubpaths()))
|
||||||
// new pod should not be changed if the feature is enabled, or if the old pod had subpaths
|
|
||||||
if !reflect.DeepEqual(newPod, newPodInfo.pod()) {
|
|
||||||
t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodInfo.pod()))
|
|
||||||
}
|
|
||||||
case newPodHasSubpaths:
|
|
||||||
// new pod should be changed
|
|
||||||
if reflect.DeepEqual(newPod, newPodInfo.pod()) {
|
|
||||||
t.Errorf("new pod was not changed")
|
|
||||||
}
|
|
||||||
// new pod should not have subpaths
|
|
||||||
if !reflect.DeepEqual(newPod, podWithoutSubpaths()) {
|
|
||||||
t.Errorf("new pod had subpaths: %v", diff.ObjectReflectDiff(newPod, podWithoutSubpaths()))
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
// new pod should not need to be changed
|
|
||||||
if !reflect.DeepEqual(newPod, newPodInfo.pod()) {
|
|
||||||
t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodInfo.pod()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
default:
|
||||||
}
|
// new pod should not need to be changed
|
||||||
|
if !reflect.DeepEqual(newPod, newPodInfo.pod()) {
|
||||||
|
t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodInfo.pod()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1715,7 +1715,6 @@ type VolumeMount struct {
|
|||||||
// Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment.
|
// Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment.
|
||||||
// Defaults to "" (volume's root).
|
// Defaults to "" (volume's root).
|
||||||
// SubPathExpr and SubPath are mutually exclusive.
|
// SubPathExpr and SubPath are mutually exclusive.
|
||||||
// This field is beta in 1.15.
|
|
||||||
// +optional
|
// +optional
|
||||||
SubPathExpr string
|
SubPathExpr string
|
||||||
}
|
}
|
||||||
|
@ -5160,45 +5160,6 @@ func TestValidateDisabledSubpathExpr(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Repeat with feature gate off
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeSubpathEnvExpansion, false)()
|
|
||||||
cases = map[string]struct {
|
|
||||||
mounts []core.VolumeMount
|
|
||||||
expectError bool
|
|
||||||
}{
|
|
||||||
"subpath expr not specified": {
|
|
||||||
[]core.VolumeMount{
|
|
||||||
{
|
|
||||||
Name: "abc-123",
|
|
||||||
MountPath: "/bab",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
false,
|
|
||||||
},
|
|
||||||
"subpath expr specified": {
|
|
||||||
[]core.VolumeMount{
|
|
||||||
{
|
|
||||||
Name: "abc-123",
|
|
||||||
MountPath: "/bab",
|
|
||||||
SubPathExpr: "$(POD_NAME)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
false, // validation should not fail, dropping the field is handled in PrepareForCreate/PrepareForUpdate
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
for name, test := range cases {
|
|
||||||
errs := ValidateVolumeMounts(test.mounts, GetVolumeDeviceMap(goodVolumeDevices), vols, &container, field.NewPath("field"))
|
|
||||||
|
|
||||||
if len(errs) != 0 && !test.expectError {
|
|
||||||
t.Errorf("test %v failed: %+v", name, errs)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(errs) == 0 && test.expectError {
|
|
||||||
t.Errorf("test %v failed, expected error", name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Repeat with subpath feature gate off
|
// Repeat with subpath feature gate off
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeSubpath, false)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeSubpath, false)()
|
||||||
cases = map[string]struct {
|
cases = map[string]struct {
|
||||||
|
@ -299,7 +299,9 @@ const (
|
|||||||
BalanceAttachedNodeVolumes featuregate.Feature = "BalanceAttachedNodeVolumes"
|
BalanceAttachedNodeVolumes featuregate.Feature = "BalanceAttachedNodeVolumes"
|
||||||
|
|
||||||
// owner: @kevtaylor
|
// owner: @kevtaylor
|
||||||
|
// alpha: v1.14
|
||||||
// beta: v1.15
|
// beta: v1.15
|
||||||
|
// ga: v1.17
|
||||||
//
|
//
|
||||||
// Allow subpath environment variable substitution
|
// Allow subpath environment variable substitution
|
||||||
// Only applicable if the VolumeSubpath feature is also enabled
|
// Only applicable if the VolumeSubpath feature is also enabled
|
||||||
@ -539,7 +541,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
|
|||||||
CSIMigrationOpenStack: {Default: false, PreRelease: featuregate.Alpha},
|
CSIMigrationOpenStack: {Default: false, PreRelease: featuregate.Alpha},
|
||||||
VolumeSubpath: {Default: true, PreRelease: featuregate.GA},
|
VolumeSubpath: {Default: true, PreRelease: featuregate.GA},
|
||||||
BalanceAttachedNodeVolumes: {Default: false, PreRelease: featuregate.Alpha},
|
BalanceAttachedNodeVolumes: {Default: false, PreRelease: featuregate.Alpha},
|
||||||
VolumeSubpathEnvExpansion: {Default: true, PreRelease: featuregate.Beta},
|
VolumeSubpathEnvExpansion: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.19,
|
||||||
ResourceQuotaScopeSelectors: {Default: true, PreRelease: featuregate.Beta},
|
ResourceQuotaScopeSelectors: {Default: true, PreRelease: featuregate.Beta},
|
||||||
CSIBlockVolume: {Default: true, PreRelease: featuregate.Beta},
|
CSIBlockVolume: {Default: true, PreRelease: featuregate.Beta},
|
||||||
CSIInlineVolume: {Default: true, PreRelease: featuregate.Beta},
|
CSIInlineVolume: {Default: true, PreRelease: featuregate.Beta},
|
||||||
|
@ -5032,7 +5032,6 @@ message VolumeMount {
|
|||||||
// Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment.
|
// Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment.
|
||||||
// Defaults to "" (volume's root).
|
// Defaults to "" (volume's root).
|
||||||
// SubPathExpr and SubPath are mutually exclusive.
|
// SubPathExpr and SubPath are mutually exclusive.
|
||||||
// This field is beta in 1.15.
|
|
||||||
// +optional
|
// +optional
|
||||||
optional string subPathExpr = 6;
|
optional string subPathExpr = 6;
|
||||||
}
|
}
|
||||||
|
@ -1784,7 +1784,6 @@ type VolumeMount struct {
|
|||||||
// Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment.
|
// Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment.
|
||||||
// Defaults to "" (volume's root).
|
// Defaults to "" (volume's root).
|
||||||
// SubPathExpr and SubPath are mutually exclusive.
|
// SubPathExpr and SubPath are mutually exclusive.
|
||||||
// This field is beta in 1.15.
|
|
||||||
// +optional
|
// +optional
|
||||||
SubPathExpr string `json:"subPathExpr,omitempty" protobuf:"bytes,6,opt,name=subPathExpr"`
|
SubPathExpr string `json:"subPathExpr,omitempty" protobuf:"bytes,6,opt,name=subPathExpr"`
|
||||||
}
|
}
|
||||||
|
@ -2366,7 +2366,7 @@ var map_VolumeMount = map[string]string{
|
|||||||
"mountPath": "Path within the container at which the volume should be mounted. Must not contain ':'.",
|
"mountPath": "Path within the container at which the volume should be mounted. Must not contain ':'.",
|
||||||
"subPath": "Path within the volume from which the container's volume should be mounted. Defaults to \"\" (volume's root).",
|
"subPath": "Path within the volume from which the container's volume should be mounted. Defaults to \"\" (volume's root).",
|
||||||
"mountPropagation": "mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10.",
|
"mountPropagation": "mountPropagation determines how mounts are propagated from the host to container and the other way around. When not set, MountPropagationNone is used. This field is beta in 1.10.",
|
||||||
"subPathExpr": "Expanded path within the volume from which the container's volume should be mounted. Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. Defaults to \"\" (volume's root). SubPathExpr and SubPath are mutually exclusive. This field is beta in 1.15.",
|
"subPathExpr": "Expanded path within the volume from which the container's volume should be mounted. Behaves similarly to SubPath but environment variable references $(VAR_NAME) are expanded using the container's environment. Defaults to \"\" (volume's root). SubPathExpr and SubPath are mutually exclusive.",
|
||||||
}
|
}
|
||||||
|
|
||||||
func (VolumeMount) SwaggerDoc() map[string]string {
|
func (VolumeMount) SwaggerDoc() map[string]string {
|
||||||
|
@ -158,7 +158,7 @@ var _ = framework.KubeDescribe("Variable Expansion", func() {
|
|||||||
Description: Make sure a container's subpath can be set using an
|
Description: Make sure a container's subpath can be set using an
|
||||||
expansion of environment variables.
|
expansion of environment variables.
|
||||||
*/
|
*/
|
||||||
ginkgo.It("should allow substituting values in a volume subpath [sig-storage][NodeFeature:VolumeSubpathEnvExpansion]", func() {
|
ginkgo.It("should allow substituting values in a volume subpath [sig-storage]", func() {
|
||||||
podName := "var-expansion-" + string(uuid.NewUUID())
|
podName := "var-expansion-" + string(uuid.NewUUID())
|
||||||
pod := &v1.Pod{
|
pod := &v1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
@ -218,7 +218,7 @@ var _ = framework.KubeDescribe("Variable Expansion", func() {
|
|||||||
Description: Make sure a container's subpath can not be set using an
|
Description: Make sure a container's subpath can not be set using an
|
||||||
expansion of environment variables when backticks are supplied.
|
expansion of environment variables when backticks are supplied.
|
||||||
*/
|
*/
|
||||||
ginkgo.It("should fail substituting values in a volume subpath with backticks [sig-storage][NodeFeature:VolumeSubpathEnvExpansion][Slow]", func() {
|
ginkgo.It("should fail substituting values in a volume subpath with backticks [sig-storage][Slow]", func() {
|
||||||
|
|
||||||
podName := "var-expansion-" + string(uuid.NewUUID())
|
podName := "var-expansion-" + string(uuid.NewUUID())
|
||||||
pod := &v1.Pod{
|
pod := &v1.Pod{
|
||||||
@ -267,7 +267,7 @@ var _ = framework.KubeDescribe("Variable Expansion", func() {
|
|||||||
Description: Make sure a container's subpath can not be set using an
|
Description: Make sure a container's subpath can not be set using an
|
||||||
expansion of environment variables when absolute path is supplied.
|
expansion of environment variables when absolute path is supplied.
|
||||||
*/
|
*/
|
||||||
ginkgo.It("should fail substituting values in a volume subpath with absolute path [sig-storage][NodeFeature:VolumeSubpathEnvExpansion][Slow]", func() {
|
ginkgo.It("should fail substituting values in a volume subpath with absolute path [sig-storage][Slow]", func() {
|
||||||
|
|
||||||
podName := "var-expansion-" + string(uuid.NewUUID())
|
podName := "var-expansion-" + string(uuid.NewUUID())
|
||||||
pod := &v1.Pod{
|
pod := &v1.Pod{
|
||||||
@ -315,7 +315,7 @@ var _ = framework.KubeDescribe("Variable Expansion", func() {
|
|||||||
Testname: var-expansion-subpath-ready-from-failed-state
|
Testname: var-expansion-subpath-ready-from-failed-state
|
||||||
Description: Verify that a failing subpath expansion can be modified during the lifecycle of a container.
|
Description: Verify that a failing subpath expansion can be modified during the lifecycle of a container.
|
||||||
*/
|
*/
|
||||||
ginkgo.It("should verify that a failing subpath expansion can be modified during the lifecycle of a container [sig-storage][NodeFeature:VolumeSubpathEnvExpansion][Slow]", func() {
|
ginkgo.It("should verify that a failing subpath expansion can be modified during the lifecycle of a container [sig-storage][Slow]", func() {
|
||||||
|
|
||||||
podName := "var-expansion-" + string(uuid.NewUUID())
|
podName := "var-expansion-" + string(uuid.NewUUID())
|
||||||
containerName := "dapi-container"
|
containerName := "dapi-container"
|
||||||
@ -406,7 +406,7 @@ var _ = framework.KubeDescribe("Variable Expansion", func() {
|
|||||||
3. successful expansion of the subpathexpr isn't required for volume cleanup
|
3. successful expansion of the subpathexpr isn't required for volume cleanup
|
||||||
|
|
||||||
*/
|
*/
|
||||||
ginkgo.It("should succeed in writing subpaths in container [sig-storage][NodeFeature:VolumeSubpathEnvExpansion][Slow]", func() {
|
ginkgo.It("should succeed in writing subpaths in container [sig-storage][Slow]", func() {
|
||||||
|
|
||||||
podName := "var-expansion-" + string(uuid.NewUUID())
|
podName := "var-expansion-" + string(uuid.NewUUID())
|
||||||
containerName := "dapi-container"
|
containerName := "dapi-container"
|
||||||
@ -515,7 +515,7 @@ var _ = framework.KubeDescribe("Variable Expansion", func() {
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
ginkgo.It("should not change the subpath mount on a container restart if the environment variable changes [sig-storage][NodeFeature:VolumeSubpathEnvExpansion][Slow]", func() {
|
ginkgo.It("should not change the subpath mount on a container restart if the environment variable changes [sig-storage][Slow]", func() {
|
||||||
|
|
||||||
suffix := string(uuid.NewUUID())
|
suffix := string(uuid.NewUUID())
|
||||||
podName := fmt.Sprintf("var-expansion-%s", suffix)
|
podName := fmt.Sprintf("var-expansion-%s", suffix)
|
||||||
|
Loading…
Reference in New Issue
Block a user