mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-03 19:58:17 +00:00 
			
		
		
		
	Promote VolumeSubpathEnvExpansion feature gate to GA
This commit is contained in:
		
							
								
								
									
										2
									
								
								api/openapi-spec/swagger.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								api/openapi-spec/swagger.json
									
									
									
										generated
									
									
									
								
							@@ -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"
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
 
 | 
			
		||||
@@ -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()))
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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 {
 | 
			
		||||
 
 | 
			
		||||
@@ -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},
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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"`
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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 {
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user