Promote VolumeSubpathEnvExpansion feature gate to GA

This commit is contained in:
Kevin Taylor 2019-09-04 16:18:14 +01:00
parent 2d8b8703de
commit cb8a7c1a4c
9 changed files with 51 additions and 92 deletions

View File

@ -11917,7 +11917,7 @@
"type": "string"
},
"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"
}
},

View File

@ -1935,52 +1935,51 @@ func TestDropSubPathExpr(t *testing.T) {
},
}
for _, enabled := range []bool{true, false} {
for _, oldPodInfo := range podInfo {
for _, newPodInfo := range podInfo {
oldPodHasSubpaths, oldPod := oldPodInfo.hasSubpaths, oldPodInfo.pod()
newPodHasSubpaths, newPod := newPodInfo.hasSubpaths, newPodInfo.pod()
if newPod == nil {
continue
enabled := true
for _, oldPodInfo := range podInfo {
for _, newPodInfo := range podInfo {
oldPodHasSubpaths, oldPod := oldPodInfo.hasSubpaths, oldPodInfo.pod()
newPodHasSubpaths, newPod := newPodInfo.hasSubpaths, newPodInfo.pod()
if newPod == nil {
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) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeSubpathEnvExpansion, enabled)()
var oldPodSpec *api.PodSpec
if oldPod != nil {
oldPodSpec = &oldPod.Spec
switch {
case enabled || oldPodHasSubpaths:
// 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()))
}
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()))
case newPodHasSubpaths:
// new pod should be changed
if reflect.DeepEqual(newPod, newPodInfo.pod()) {
t.Errorf("new pod was not changed")
}
switch {
case enabled || oldPodHasSubpaths:
// 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()))
}
// 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()))
}
}
})
}
}
}

View File

@ -1715,7 +1715,6 @@ type VolumeMount struct {
// 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.
// +optional
SubPathExpr string
}

View File

@ -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
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.VolumeSubpath, false)()
cases = map[string]struct {

View File

@ -299,7 +299,9 @@ const (
BalanceAttachedNodeVolumes featuregate.Feature = "BalanceAttachedNodeVolumes"
// owner: @kevtaylor
// alpha: v1.14
// beta: v1.15
// ga: v1.17
//
// Allow subpath environment variable substitution
// 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},
VolumeSubpath: {Default: true, PreRelease: featuregate.GA},
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},
CSIBlockVolume: {Default: true, PreRelease: featuregate.Beta},
CSIInlineVolume: {Default: true, PreRelease: featuregate.Beta},

View File

@ -5032,7 +5032,6 @@ message VolumeMount {
// 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.
// +optional
optional string subPathExpr = 6;
}

View File

@ -1784,7 +1784,6 @@ type VolumeMount struct {
// 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.
// +optional
SubPathExpr string `json:"subPathExpr,omitempty" protobuf:"bytes,6,opt,name=subPathExpr"`
}

View File

@ -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 ':'.",
"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.",
"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 {

View File

@ -158,7 +158,7 @@ var _ = framework.KubeDescribe("Variable Expansion", func() {
Description: Make sure a container's subpath can be set using an
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())
pod := &v1.Pod{
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
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())
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
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())
pod := &v1.Pod{
@ -315,7 +315,7 @@ var _ = framework.KubeDescribe("Variable Expansion", func() {
Testname: var-expansion-subpath-ready-from-failed-state
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())
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
*/
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())
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())
podName := fmt.Sprintf("var-expansion-%s", suffix)