mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
Merge pull request #88673 from jsafrane/block-feature-ga
Promote block volumes to GA
This commit is contained in:
commit
9d0cbb7503
8
api/openapi-spec/swagger.json
generated
8
api/openapi-spec/swagger.json
generated
@ -5632,7 +5632,7 @@
|
||||
"type": "boolean"
|
||||
},
|
||||
"volumeDevices": {
|
||||
"description": "volumeDevices is the list of block devices to be used by the container. This is a beta feature.",
|
||||
"description": "volumeDevices is the list of block devices to be used by the container.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/io.k8s.api.core.v1.VolumeDevice"
|
||||
},
|
||||
@ -6234,7 +6234,7 @@
|
||||
"type": "boolean"
|
||||
},
|
||||
"volumeDevices": {
|
||||
"description": "volumeDevices is the list of block devices to be used by the container. This is a beta feature.",
|
||||
"description": "volumeDevices is the list of block devices to be used by the container.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/io.k8s.api.core.v1.VolumeDevice"
|
||||
},
|
||||
@ -7847,7 +7847,7 @@
|
||||
"type": "string"
|
||||
},
|
||||
"volumeMode": {
|
||||
"description": "volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec. This is a beta feature.",
|
||||
"description": "volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec.",
|
||||
"type": "string"
|
||||
},
|
||||
"volumeName": {
|
||||
@ -8067,7 +8067,7 @@
|
||||
"description": "StorageOS represents a StorageOS volume that is attached to the kubelet's host machine and mounted into the pod More info: https://examples.k8s.io/volumes/storageos/README.md"
|
||||
},
|
||||
"volumeMode": {
|
||||
"description": "volumeMode defines if a volume is intended to be used with a formatted filesystem or to remain in raw block state. Value of Filesystem is implied when not included in spec. This is a beta feature.",
|
||||
"description": "volumeMode defines if a volume is intended to be used with a formatted filesystem or to remain in raw block state. Value of Filesystem is implied when not included in spec.",
|
||||
"type": "string"
|
||||
},
|
||||
"vsphereVolume": {
|
||||
|
@ -25,10 +25,6 @@ import (
|
||||
// DropDisabledFields removes disabled fields from the pv spec.
|
||||
// This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a pv spec.
|
||||
func DropDisabledFields(pvSpec *api.PersistentVolumeSpec, oldPVSpec *api.PersistentVolumeSpec) {
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) && !volumeModeInUse(oldPVSpec) {
|
||||
pvSpec.VolumeMode = nil
|
||||
}
|
||||
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.ExpandCSIVolumes) && !hasExpansionSecrets(oldPVSpec) {
|
||||
if pvSpec.CSI != nil {
|
||||
pvSpec.CSI.ControllerExpandSecretRef = nil
|
||||
@ -46,13 +42,3 @@ func hasExpansionSecrets(oldPVSpec *api.PersistentVolumeSpec) bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func volumeModeInUse(oldPVSpec *api.PersistentVolumeSpec) bool {
|
||||
if oldPVSpec == nil {
|
||||
return false
|
||||
}
|
||||
if oldPVSpec.VolumeMode != nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@ -28,68 +28,18 @@ import (
|
||||
)
|
||||
|
||||
func TestDropDisabledFields(t *testing.T) {
|
||||
specWithMode := func(mode *api.PersistentVolumeMode) *api.PersistentVolumeSpec {
|
||||
return &api.PersistentVolumeSpec{VolumeMode: mode}
|
||||
}
|
||||
|
||||
secretRef := &api.SecretReference{
|
||||
Name: "expansion-secret",
|
||||
Namespace: "default",
|
||||
}
|
||||
|
||||
modeBlock := api.PersistentVolumeBlock
|
||||
|
||||
tests := map[string]struct {
|
||||
oldSpec *api.PersistentVolumeSpec
|
||||
newSpec *api.PersistentVolumeSpec
|
||||
expectOldSpec *api.PersistentVolumeSpec
|
||||
expectNewSpec *api.PersistentVolumeSpec
|
||||
blockEnabled bool
|
||||
csiExpansionEnabled bool
|
||||
}{
|
||||
"disabled block clears new": {
|
||||
blockEnabled: false,
|
||||
newSpec: specWithMode(&modeBlock),
|
||||
expectNewSpec: specWithMode(nil),
|
||||
oldSpec: nil,
|
||||
expectOldSpec: nil,
|
||||
},
|
||||
"disabled block clears update when old pv did not use block": {
|
||||
blockEnabled: false,
|
||||
newSpec: specWithMode(&modeBlock),
|
||||
expectNewSpec: specWithMode(nil),
|
||||
oldSpec: specWithMode(nil),
|
||||
expectOldSpec: specWithMode(nil),
|
||||
},
|
||||
"disabled block does not clear new on update when old pv did use block": {
|
||||
blockEnabled: false,
|
||||
newSpec: specWithMode(&modeBlock),
|
||||
expectNewSpec: specWithMode(&modeBlock),
|
||||
oldSpec: specWithMode(&modeBlock),
|
||||
expectOldSpec: specWithMode(&modeBlock),
|
||||
},
|
||||
|
||||
"enabled block preserves new": {
|
||||
blockEnabled: true,
|
||||
newSpec: specWithMode(&modeBlock),
|
||||
expectNewSpec: specWithMode(&modeBlock),
|
||||
oldSpec: nil,
|
||||
expectOldSpec: nil,
|
||||
},
|
||||
"enabled block preserves update when old pv did not use block": {
|
||||
blockEnabled: true,
|
||||
newSpec: specWithMode(&modeBlock),
|
||||
expectNewSpec: specWithMode(&modeBlock),
|
||||
oldSpec: specWithMode(nil),
|
||||
expectOldSpec: specWithMode(nil),
|
||||
},
|
||||
"enabled block preserves update when old pv did use block": {
|
||||
blockEnabled: true,
|
||||
newSpec: specWithMode(&modeBlock),
|
||||
expectNewSpec: specWithMode(&modeBlock),
|
||||
oldSpec: specWithMode(&modeBlock),
|
||||
expectOldSpec: specWithMode(&modeBlock),
|
||||
},
|
||||
"disabled csi expansion clears secrets": {
|
||||
csiExpansionEnabled: false,
|
||||
newSpec: specWithCSISecrets(secretRef),
|
||||
@ -129,7 +79,6 @@ func TestDropDisabledFields(t *testing.T) {
|
||||
|
||||
for name, tc := range tests {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, tc.blockEnabled)()
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ExpandCSIVolumes, tc.csiExpansionEnabled)()
|
||||
|
||||
DropDisabledFields(tc.newSpec, tc.oldSpec)
|
||||
|
@ -30,24 +30,11 @@ const (
|
||||
// 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, oldPVCSpec *core.PersistentVolumeClaimSpec) {
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) && !volumeModeInUse(oldPVCSpec) {
|
||||
pvcSpec.VolumeMode = nil
|
||||
}
|
||||
if !dataSourceIsEnabled(pvcSpec) && !dataSourceInUse(oldPVCSpec) {
|
||||
pvcSpec.DataSource = nil
|
||||
}
|
||||
}
|
||||
|
||||
func volumeModeInUse(oldPVCSpec *core.PersistentVolumeClaimSpec) bool {
|
||||
if oldPVCSpec == nil {
|
||||
return false
|
||||
}
|
||||
if oldPVCSpec.VolumeMode != nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func dataSourceInUse(oldPVCSpec *core.PersistentVolumeClaimSpec) bool {
|
||||
if oldPVCSpec == nil {
|
||||
return false
|
||||
|
@ -28,96 +28,6 @@ import (
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
func TestDropAlphaPVCVolumeMode(t *testing.T) {
|
||||
vmode := core.PersistentVolumeFilesystem
|
||||
|
||||
pvcWithoutVolumeMode := func() *core.PersistentVolumeClaim {
|
||||
return &core.PersistentVolumeClaim{
|
||||
Spec: core.PersistentVolumeClaimSpec{
|
||||
VolumeMode: nil,
|
||||
},
|
||||
}
|
||||
}
|
||||
pvcWithVolumeMode := func() *core.PersistentVolumeClaim {
|
||||
return &core.PersistentVolumeClaim{
|
||||
Spec: core.PersistentVolumeClaimSpec{
|
||||
VolumeMode: &vmode,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pvcInfo := []struct {
|
||||
description string
|
||||
hasVolumeMode bool
|
||||
pvc func() *core.PersistentVolumeClaim
|
||||
}{
|
||||
{
|
||||
description: "pvc without VolumeMode",
|
||||
hasVolumeMode: false,
|
||||
pvc: pvcWithoutVolumeMode,
|
||||
},
|
||||
{
|
||||
description: "pvc with Filesystem VolumeMode",
|
||||
hasVolumeMode: true,
|
||||
pvc: pvcWithVolumeMode,
|
||||
},
|
||||
{
|
||||
description: "is nil",
|
||||
hasVolumeMode: false,
|
||||
pvc: func() *core.PersistentVolumeClaim { return nil },
|
||||
},
|
||||
}
|
||||
|
||||
for _, enabled := range []bool{true, false} {
|
||||
for _, oldpvcInfo := range pvcInfo {
|
||||
for _, newpvcInfo := range pvcInfo {
|
||||
oldpvcHasVolumeMode, oldpvc := oldpvcInfo.hasVolumeMode, oldpvcInfo.pvc()
|
||||
newpvcHasVolumeMode, newpvc := newpvcInfo.hasVolumeMode, newpvcInfo.pvc()
|
||||
if newpvc == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
t.Run(fmt.Sprintf("feature enabled=%v, old pvc %v, new pvc %v", enabled, oldpvcInfo.description, newpvcInfo.description), func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, enabled)()
|
||||
|
||||
var oldpvcSpec *core.PersistentVolumeClaimSpec
|
||||
if oldpvc != nil {
|
||||
oldpvcSpec = &oldpvc.Spec
|
||||
}
|
||||
DropDisabledFields(&newpvc.Spec, oldpvcSpec)
|
||||
|
||||
// old pvc should never be changed
|
||||
if !reflect.DeepEqual(oldpvc, oldpvcInfo.pvc()) {
|
||||
t.Errorf("old pvc changed: %v", diff.ObjectReflectDiff(oldpvc, oldpvcInfo.pvc()))
|
||||
}
|
||||
|
||||
switch {
|
||||
case enabled || oldpvcHasVolumeMode:
|
||||
// new pvc should not be changed if the feature is enabled, or if the old pvc had BlockVolume
|
||||
if !reflect.DeepEqual(newpvc, newpvcInfo.pvc()) {
|
||||
t.Errorf("new pvc changed: %v", diff.ObjectReflectDiff(newpvc, newpvcInfo.pvc()))
|
||||
}
|
||||
case newpvcHasVolumeMode:
|
||||
// new pvc should be changed
|
||||
if reflect.DeepEqual(newpvc, newpvcInfo.pvc()) {
|
||||
t.Errorf("new pvc was not changed")
|
||||
}
|
||||
// new pvc should not have BlockVolume
|
||||
if !reflect.DeepEqual(newpvc, pvcWithoutVolumeMode()) {
|
||||
t.Errorf("new pvc had pvcBlockVolume: %v", diff.ObjectReflectDiff(newpvc, pvcWithoutVolumeMode()))
|
||||
}
|
||||
default:
|
||||
// new pvc should not need to be changed
|
||||
if !reflect.DeepEqual(newpvc, newpvcInfo.pvc()) {
|
||||
t.Errorf("new pvc changed: %v", diff.ObjectReflectDiff(newpvc, newpvcInfo.pvc()))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDropDisabledSnapshotDataSource(t *testing.T) {
|
||||
pvcWithoutDataSource := func() *core.PersistentVolumeClaim {
|
||||
return &core.PersistentVolumeClaim{
|
||||
|
@ -385,8 +385,6 @@ func dropDisabledFields(
|
||||
})
|
||||
}
|
||||
|
||||
dropDisabledVolumeDevicesFields(podSpec, oldPodSpec)
|
||||
|
||||
dropDisabledRunAsGroupField(podSpec, oldPodSpec)
|
||||
|
||||
dropDisabledGMSAFields(podSpec, oldPodSpec)
|
||||
@ -484,17 +482,6 @@ func dropDisabledProcMountField(podSpec, oldPodSpec *api.PodSpec) {
|
||||
}
|
||||
}
|
||||
|
||||
// dropDisabledVolumeDevicesFields removes disabled fields from []VolumeDevice if it has not been already populated.
|
||||
// This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a VolumeDevice
|
||||
func dropDisabledVolumeDevicesFields(podSpec, oldPodSpec *api.PodSpec) {
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) && !volumeDevicesInUse(oldPodSpec) {
|
||||
VisitContainers(podSpec, func(c *api.Container) bool {
|
||||
c.VolumeDevices = nil
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// dropDisabledCSIVolumeSourceAlphaFields removes disabled alpha fields from []CSIVolumeSource.
|
||||
// This should be called from PrepareForCreate/PrepareForUpdate for all pod specs resources containing a CSIVolumeSource
|
||||
func dropDisabledCSIVolumeSourceAlphaFields(podSpec, oldPodSpec *api.PodSpec) {
|
||||
@ -646,24 +633,6 @@ func emptyDirSizeLimitInUse(podSpec *api.PodSpec) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// volumeDevicesInUse returns true if the pod spec is non-nil and has VolumeDevices set.
|
||||
func volumeDevicesInUse(podSpec *api.PodSpec) bool {
|
||||
if podSpec == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
var inUse bool
|
||||
VisitContainers(podSpec, func(c *api.Container) bool {
|
||||
if c.VolumeDevices != nil {
|
||||
inUse = true
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
return inUse
|
||||
}
|
||||
|
||||
// runAsGroupInUse returns true if the pod spec is non-nil and has a SecurityContext's RunAsGroup field set
|
||||
func runAsGroupInUse(podSpec *api.PodSpec) bool {
|
||||
if podSpec == nil {
|
||||
|
@ -435,150 +435,6 @@ func TestPodConfigmaps(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestDropAlphaVolumeDevices(t *testing.T) {
|
||||
podWithVolumeDevices := func() *api.Pod {
|
||||
return &api.Pod{
|
||||
Spec: api.PodSpec{
|
||||
RestartPolicy: api.RestartPolicyNever,
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Name: "container1",
|
||||
Image: "testimage",
|
||||
VolumeDevices: []api.VolumeDevice{
|
||||
{
|
||||
Name: "myvolume",
|
||||
DevicePath: "/usr/test",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
InitContainers: []api.Container{
|
||||
{
|
||||
Name: "container1",
|
||||
Image: "testimage",
|
||||
VolumeDevices: []api.VolumeDevice{
|
||||
{
|
||||
Name: "myvolume",
|
||||
DevicePath: "/usr/test",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Volumes: []api.Volume{
|
||||
{
|
||||
Name: "myvolume",
|
||||
VolumeSource: api.VolumeSource{
|
||||
HostPath: &api.HostPathVolumeSource{
|
||||
Path: "/dev/xvdc",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
podWithoutVolumeDevices := func() *api.Pod {
|
||||
return &api.Pod{
|
||||
Spec: api.PodSpec{
|
||||
RestartPolicy: api.RestartPolicyNever,
|
||||
Containers: []api.Container{
|
||||
{
|
||||
Name: "container1",
|
||||
Image: "testimage",
|
||||
},
|
||||
},
|
||||
InitContainers: []api.Container{
|
||||
{
|
||||
Name: "container1",
|
||||
Image: "testimage",
|
||||
},
|
||||
},
|
||||
Volumes: []api.Volume{
|
||||
{
|
||||
Name: "myvolume",
|
||||
VolumeSource: api.VolumeSource{
|
||||
HostPath: &api.HostPathVolumeSource{
|
||||
Path: "/dev/xvdc",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
podInfo := []struct {
|
||||
description string
|
||||
hasVolumeDevices bool
|
||||
pod func() *api.Pod
|
||||
}{
|
||||
{
|
||||
description: "has VolumeDevices",
|
||||
hasVolumeDevices: true,
|
||||
pod: podWithVolumeDevices,
|
||||
},
|
||||
{
|
||||
description: "does not have VolumeDevices",
|
||||
hasVolumeDevices: false,
|
||||
pod: podWithoutVolumeDevices,
|
||||
},
|
||||
{
|
||||
description: "is nil",
|
||||
hasVolumeDevices: false,
|
||||
pod: func() *api.Pod { return nil },
|
||||
},
|
||||
}
|
||||
|
||||
for _, enabled := range []bool{true, false} {
|
||||
for _, oldPodInfo := range podInfo {
|
||||
for _, newPodInfo := range podInfo {
|
||||
oldPodHasVolumeDevices, oldPod := oldPodInfo.hasVolumeDevices, oldPodInfo.pod()
|
||||
newPodHasVolumeDevices, newPod := newPodInfo.hasVolumeDevices, 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.BlockVolume, 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()))
|
||||
}
|
||||
|
||||
switch {
|
||||
case enabled || oldPodHasVolumeDevices:
|
||||
// new pod should not be changed if the feature is enabled, or if the old pod had VolumeDevices
|
||||
if !reflect.DeepEqual(newPod, newPodInfo.pod()) {
|
||||
t.Errorf("new pod changed: %v", diff.ObjectReflectDiff(newPod, newPodInfo.pod()))
|
||||
}
|
||||
case newPodHasVolumeDevices:
|
||||
// new pod should be changed
|
||||
if reflect.DeepEqual(newPod, newPodInfo.pod()) {
|
||||
t.Errorf("new pod was not changed")
|
||||
}
|
||||
// new pod should not have VolumeDevices
|
||||
if !reflect.DeepEqual(newPod, podWithoutVolumeDevices()) {
|
||||
t.Errorf("new pod had VolumeDevices: %v", diff.ObjectReflectDiff(newPod, podWithoutVolumeDevices()))
|
||||
}
|
||||
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()))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestDropSubPath(t *testing.T) {
|
||||
podWithSubpaths := func() *api.Pod {
|
||||
return &api.Pod{
|
||||
|
@ -302,7 +302,6 @@ type PersistentVolumeSpec struct {
|
||||
MountOptions []string
|
||||
// volumeMode defines if a volume is intended to be used with a formatted filesystem
|
||||
// or to remain in raw block state. Value of Filesystem is implied when not included in spec.
|
||||
// This is a beta feature.
|
||||
// +optional
|
||||
VolumeMode *PersistentVolumeMode
|
||||
// NodeAffinity defines constraints that limit what nodes this volume can be accessed from.
|
||||
@ -416,7 +415,6 @@ type PersistentVolumeClaimSpec struct {
|
||||
StorageClassName *string
|
||||
// volumeMode defines what type of volume is required by the claim.
|
||||
// Value of Filesystem is implied when not included in claim spec.
|
||||
// This is a beta feature.
|
||||
// +optional
|
||||
VolumeMode *PersistentVolumeMode
|
||||
// This field can be used to specify either:
|
||||
@ -2057,7 +2055,6 @@ type Container struct {
|
||||
// +optional
|
||||
VolumeMounts []VolumeMount
|
||||
// volumeDevices is the list of block devices to be used by the container.
|
||||
// This is a beta feature.
|
||||
// +optional
|
||||
VolumeDevices []VolumeDevice
|
||||
// +optional
|
||||
@ -2969,7 +2966,6 @@ type EphemeralContainerCommon struct {
|
||||
// +optional
|
||||
VolumeMounts []VolumeMount
|
||||
// volumeDevices is the list of block devices to be used by the container.
|
||||
// This is a beta feature.
|
||||
// +optional
|
||||
VolumeDevices []VolumeDevice
|
||||
// Probes are not allowed for ephemeral containers.
|
||||
|
@ -1475,204 +1475,168 @@ func TestValidatePersistentVolumeClaimUpdate(t *testing.T) {
|
||||
oldClaim *core.PersistentVolumeClaim
|
||||
newClaim *core.PersistentVolumeClaim
|
||||
enableResize bool
|
||||
enableBlock bool
|
||||
}{
|
||||
"valid-update-volumeName-only": {
|
||||
isExpectedFailure: false,
|
||||
oldClaim: validClaim,
|
||||
newClaim: validUpdateClaim,
|
||||
enableResize: false,
|
||||
enableBlock: false,
|
||||
},
|
||||
"valid-no-op-update": {
|
||||
isExpectedFailure: false,
|
||||
oldClaim: validUpdateClaim,
|
||||
newClaim: validUpdateClaim,
|
||||
enableResize: false,
|
||||
enableBlock: false,
|
||||
},
|
||||
"invalid-update-change-resources-on-bound-claim": {
|
||||
isExpectedFailure: true,
|
||||
oldClaim: validUpdateClaim,
|
||||
newClaim: invalidUpdateClaimResources,
|
||||
enableResize: false,
|
||||
enableBlock: false,
|
||||
},
|
||||
"invalid-update-change-access-modes-on-bound-claim": {
|
||||
isExpectedFailure: true,
|
||||
oldClaim: validUpdateClaim,
|
||||
newClaim: invalidUpdateClaimAccessModes,
|
||||
enableResize: false,
|
||||
enableBlock: false,
|
||||
},
|
||||
"valid-update-volume-mode-block-to-block": {
|
||||
isExpectedFailure: false,
|
||||
oldClaim: validClaimVolumeModeBlock,
|
||||
newClaim: validClaimVolumeModeBlock,
|
||||
enableResize: false,
|
||||
enableBlock: true,
|
||||
},
|
||||
"valid-update-volume-mode-file-to-file": {
|
||||
isExpectedFailure: false,
|
||||
oldClaim: validClaimVolumeModeFile,
|
||||
newClaim: validClaimVolumeModeFile,
|
||||
enableResize: false,
|
||||
enableBlock: true,
|
||||
},
|
||||
"invalid-update-volume-mode-to-block": {
|
||||
isExpectedFailure: true,
|
||||
oldClaim: validClaimVolumeModeFile,
|
||||
newClaim: validClaimVolumeModeBlock,
|
||||
enableResize: false,
|
||||
enableBlock: true,
|
||||
},
|
||||
"invalid-update-volume-mode-to-file": {
|
||||
isExpectedFailure: true,
|
||||
oldClaim: validClaimVolumeModeBlock,
|
||||
newClaim: validClaimVolumeModeFile,
|
||||
enableResize: false,
|
||||
enableBlock: true,
|
||||
},
|
||||
"invalid-update-volume-mode-nil-to-file": {
|
||||
isExpectedFailure: true,
|
||||
oldClaim: invalidClaimVolumeModeNil,
|
||||
newClaim: validClaimVolumeModeFile,
|
||||
enableResize: false,
|
||||
enableBlock: true,
|
||||
},
|
||||
"invalid-update-volume-mode-nil-to-block": {
|
||||
isExpectedFailure: true,
|
||||
oldClaim: invalidClaimVolumeModeNil,
|
||||
newClaim: validClaimVolumeModeBlock,
|
||||
enableResize: false,
|
||||
enableBlock: true,
|
||||
},
|
||||
"invalid-update-volume-mode-block-to-nil": {
|
||||
isExpectedFailure: true,
|
||||
oldClaim: validClaimVolumeModeBlock,
|
||||
newClaim: invalidClaimVolumeModeNil,
|
||||
enableResize: false,
|
||||
enableBlock: true,
|
||||
},
|
||||
"invalid-update-volume-mode-file-to-nil": {
|
||||
isExpectedFailure: true,
|
||||
oldClaim: validClaimVolumeModeFile,
|
||||
newClaim: invalidClaimVolumeModeNil,
|
||||
enableResize: false,
|
||||
enableBlock: true,
|
||||
},
|
||||
"invalid-update-volume-mode-empty-to-mode": {
|
||||
isExpectedFailure: true,
|
||||
oldClaim: validClaim,
|
||||
newClaim: validClaimVolumeModeBlock,
|
||||
enableResize: false,
|
||||
enableBlock: true,
|
||||
},
|
||||
"invalid-update-volume-mode-mode-to-empty": {
|
||||
isExpectedFailure: true,
|
||||
oldClaim: validClaimVolumeModeBlock,
|
||||
newClaim: validClaim,
|
||||
enableResize: false,
|
||||
enableBlock: true,
|
||||
},
|
||||
// with the new validation changes this test should not fail
|
||||
"noop-update-volumemode-allowed": {
|
||||
isExpectedFailure: false,
|
||||
oldClaim: validClaimVolumeModeFile,
|
||||
newClaim: validClaimVolumeModeFile,
|
||||
enableResize: false,
|
||||
enableBlock: false,
|
||||
},
|
||||
"invalid-update-change-storage-class-annotation-after-creation": {
|
||||
isExpectedFailure: true,
|
||||
oldClaim: validClaimStorageClass,
|
||||
newClaim: invalidUpdateClaimStorageClass,
|
||||
enableResize: false,
|
||||
enableBlock: false,
|
||||
},
|
||||
"valid-update-mutable-annotation": {
|
||||
isExpectedFailure: false,
|
||||
oldClaim: validClaimAnnotation,
|
||||
newClaim: validUpdateClaimMutableAnnotation,
|
||||
enableResize: false,
|
||||
enableBlock: false,
|
||||
},
|
||||
"valid-update-add-annotation": {
|
||||
isExpectedFailure: false,
|
||||
oldClaim: validClaim,
|
||||
newClaim: validAddClaimAnnotation,
|
||||
enableResize: false,
|
||||
enableBlock: false,
|
||||
},
|
||||
"valid-size-update-resize-disabled": {
|
||||
isExpectedFailure: true,
|
||||
oldClaim: validClaim,
|
||||
newClaim: validSizeUpdate,
|
||||
enableResize: false,
|
||||
enableBlock: false,
|
||||
},
|
||||
"valid-size-update-resize-enabled": {
|
||||
isExpectedFailure: false,
|
||||
oldClaim: validClaim,
|
||||
newClaim: validSizeUpdate,
|
||||
enableResize: true,
|
||||
enableBlock: false,
|
||||
},
|
||||
"invalid-size-update-resize-enabled": {
|
||||
isExpectedFailure: true,
|
||||
oldClaim: validClaim,
|
||||
newClaim: invalidSizeUpdate,
|
||||
enableResize: true,
|
||||
enableBlock: false,
|
||||
},
|
||||
"unbound-size-update-resize-enabled": {
|
||||
isExpectedFailure: true,
|
||||
oldClaim: validClaim,
|
||||
newClaim: unboundSizeUpdate,
|
||||
enableResize: true,
|
||||
enableBlock: false,
|
||||
},
|
||||
"valid-upgrade-storage-class-annotation-to-spec": {
|
||||
isExpectedFailure: false,
|
||||
oldClaim: validClaimStorageClass,
|
||||
newClaim: validClaimStorageClassInSpec,
|
||||
enableResize: false,
|
||||
enableBlock: false,
|
||||
},
|
||||
"invalid-upgrade-storage-class-annotation-to-spec": {
|
||||
isExpectedFailure: true,
|
||||
oldClaim: validClaimStorageClass,
|
||||
newClaim: invalidClaimStorageClassInSpec,
|
||||
enableResize: false,
|
||||
enableBlock: false,
|
||||
},
|
||||
"valid-upgrade-storage-class-annotation-to-annotation-and-spec": {
|
||||
isExpectedFailure: false,
|
||||
oldClaim: validClaimStorageClass,
|
||||
newClaim: validClaimStorageClassInAnnotationAndSpec,
|
||||
enableResize: false,
|
||||
enableBlock: false,
|
||||
},
|
||||
"invalid-upgrade-storage-class-annotation-to-annotation-and-spec": {
|
||||
isExpectedFailure: true,
|
||||
oldClaim: validClaimStorageClass,
|
||||
newClaim: invalidClaimStorageClassInAnnotationAndSpec,
|
||||
enableResize: false,
|
||||
enableBlock: false,
|
||||
},
|
||||
"invalid-upgrade-storage-class-in-spec": {
|
||||
isExpectedFailure: true,
|
||||
oldClaim: validClaimStorageClassInSpec,
|
||||
newClaim: invalidClaimStorageClassInSpec,
|
||||
enableResize: false,
|
||||
enableBlock: false,
|
||||
},
|
||||
"invalid-downgrade-storage-class-spec-to-annotation": {
|
||||
isExpectedFailure: true,
|
||||
oldClaim: validClaimStorageClassInSpec,
|
||||
newClaim: validClaimStorageClass,
|
||||
enableResize: false,
|
||||
enableBlock: false,
|
||||
},
|
||||
}
|
||||
|
||||
@ -1680,7 +1644,6 @@ func TestValidatePersistentVolumeClaimUpdate(t *testing.T) {
|
||||
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.BlockVolume, scenario.enableBlock)()
|
||||
scenario.oldClaim.ResourceVersion = "1"
|
||||
scenario.newClaim.ResourceVersion = "1"
|
||||
errs := ValidatePersistentVolumeClaimUpdate(scenario.newClaim, scenario.oldClaim)
|
||||
@ -4092,9 +4055,6 @@ func TestHugePagesIsolation(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPVCVolumeMode(t *testing.T) {
|
||||
// Enable feature BlockVolume for PVC
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
|
||||
|
||||
block := core.PersistentVolumeBlock
|
||||
file := core.PersistentVolumeFilesystem
|
||||
fake := core.PersistentVolumeMode("fake")
|
||||
@ -4125,9 +4085,6 @@ func TestPVCVolumeMode(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPVVolumeMode(t *testing.T) {
|
||||
// Enable feature BlockVolume for PVC
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
|
||||
|
||||
block := core.PersistentVolumeBlock
|
||||
file := core.PersistentVolumeFilesystem
|
||||
fake := core.PersistentVolumeMode("fake")
|
||||
|
@ -22,10 +22,7 @@ import (
|
||||
v1 "k8s.io/api/core/v1"
|
||||
storage "k8s.io/api/storage/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
pvutil "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/util"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
// Test single call to syncClaim and syncVolume methods.
|
||||
@ -611,68 +608,6 @@ func TestSync(t *testing.T) {
|
||||
}, []*v1.Pod{})
|
||||
}
|
||||
|
||||
func TestSyncBlockVolumeDisabled(t *testing.T) {
|
||||
modeBlock := v1.PersistentVolumeBlock
|
||||
modeFile := v1.PersistentVolumeFilesystem
|
||||
// All of these should bind as feature set is not enabled for BlockVolume
|
||||
// meaning volumeMode will be ignored and dropped
|
||||
tests := []controllerTest{
|
||||
{
|
||||
// syncVolume binds a requested block claim to a block volume
|
||||
"14-1 - binding to volumeMode block",
|
||||
withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-1", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
|
||||
withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-1", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
|
||||
withClaimVolumeMode(&modeBlock, newClaimArray("claim14-1", "uid14-1", "10Gi", "", v1.ClaimPending, nil)),
|
||||
withClaimVolumeMode(&modeBlock, newClaimArray("claim14-1", "uid14-1", "10Gi", "", v1.ClaimPending, nil)),
|
||||
noevents, noerrors, testSyncClaim,
|
||||
},
|
||||
{
|
||||
// syncVolume binds a requested filesystem claim to a filesystem volume
|
||||
"14-2 - binding to volumeMode filesystem",
|
||||
withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-2", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
|
||||
withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-2", "10Gi", "uid14-2", "claim14-2", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, pvutil.AnnBoundByController)),
|
||||
withClaimVolumeMode(&modeFile, newClaimArray("claim14-2", "uid14-2", "10Gi", "", v1.ClaimPending, nil)),
|
||||
withClaimVolumeMode(&modeFile, newClaimArray("claim14-2", "uid14-2", "10Gi", "volume14-2", v1.ClaimBound, nil, pvutil.AnnBoundByController, pvutil.AnnBindCompleted)),
|
||||
noevents, noerrors, testSyncClaim,
|
||||
},
|
||||
{
|
||||
// syncVolume binds an unspecified volumemode for claim to a specified filesystem volume
|
||||
"14-3 - binding to volumeMode filesystem using default for claim",
|
||||
withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-3", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
|
||||
withVolumeVolumeMode(&modeFile, newVolumeArray("volume14-3", "10Gi", "uid14-3", "claim14-3", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, pvutil.AnnBoundByController)),
|
||||
withClaimVolumeMode(nil, newClaimArray("claim14-3", "uid14-3", "10Gi", "", v1.ClaimPending, nil)),
|
||||
withClaimVolumeMode(nil, newClaimArray("claim14-3", "uid14-3", "10Gi", "volume14-3", v1.ClaimBound, nil, pvutil.AnnBoundByController, pvutil.AnnBindCompleted)),
|
||||
noevents, noerrors, testSyncClaim,
|
||||
},
|
||||
{
|
||||
// syncVolume binds a requested filesystem claim to an unspecified volumeMode for volume
|
||||
"14-4 - binding to unspecified volumeMode using requested filesystem for claim",
|
||||
withVolumeVolumeMode(nil, newVolumeArray("volume14-4", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
|
||||
withVolumeVolumeMode(nil, newVolumeArray("volume14-4", "10Gi", "uid14-4", "claim14-4", v1.VolumeBound, v1.PersistentVolumeReclaimRetain, classEmpty, pvutil.AnnBoundByController)),
|
||||
withClaimVolumeMode(&modeFile, newClaimArray("claim14-4", "uid14-4", "10Gi", "", v1.ClaimPending, nil)),
|
||||
withClaimVolumeMode(&modeFile, newClaimArray("claim14-4", "uid14-4", "10Gi", "volume14-4", v1.ClaimBound, nil, pvutil.AnnBoundByController, pvutil.AnnBindCompleted)),
|
||||
noevents, noerrors, testSyncClaim,
|
||||
},
|
||||
{
|
||||
// syncVolume binds a requested filesystem claim to an unspecified volumeMode for volume
|
||||
"14-5 - binding different volumeModes should be ignored",
|
||||
withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-5", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
|
||||
withVolumeVolumeMode(&modeBlock, newVolumeArray("volume14-5", "10Gi", "", "", v1.VolumeAvailable, v1.PersistentVolumeReclaimRetain, classEmpty)),
|
||||
withClaimVolumeMode(&modeFile, newClaimArray("claim14-5", "uid14-5", "10Gi", "", v1.ClaimPending, nil)),
|
||||
withClaimVolumeMode(&modeFile, newClaimArray("claim14-5", "uid14-5", "10Gi", "", v1.ClaimPending, nil)),
|
||||
noevents, noerrors, testSyncClaim,
|
||||
},
|
||||
}
|
||||
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, false)()
|
||||
runSyncTests(t, tests, []*storage.StorageClass{
|
||||
{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: classWait},
|
||||
VolumeBindingMode: &modeWait,
|
||||
},
|
||||
}, []*v1.Pod{})
|
||||
}
|
||||
|
||||
func TestSyncBlockVolume(t *testing.T) {
|
||||
modeBlock := v1.PersistentVolumeBlock
|
||||
modeFile := v1.PersistentVolumeFilesystem
|
||||
@ -853,8 +788,6 @@ func TestSyncBlockVolume(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
|
||||
|
||||
runSyncTests(t, tests, []*storage.StorageClass{}, []*v1.Pod{})
|
||||
}
|
||||
|
||||
|
@ -1060,91 +1060,56 @@ func TestVolumeModeCheck(t *testing.T) {
|
||||
isExpectedMismatch bool
|
||||
vol *v1.PersistentVolume
|
||||
pvc *v1.PersistentVolumeClaim
|
||||
enableBlock bool
|
||||
}{
|
||||
"feature enabled - pvc block and pv filesystem": {
|
||||
"pvc block and pv filesystem": {
|
||||
isExpectedMismatch: true,
|
||||
vol: createVolumeModeFilesystemTestVolume(),
|
||||
pvc: makeVolumeModePVC("8G", &blockMode, nil),
|
||||
enableBlock: true,
|
||||
},
|
||||
"feature enabled - pvc filesystem and pv block": {
|
||||
"pvc filesystem and pv block": {
|
||||
isExpectedMismatch: true,
|
||||
vol: createVolumeModeBlockTestVolume(),
|
||||
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
||||
enableBlock: true,
|
||||
},
|
||||
"feature enabled - pvc block and pv block": {
|
||||
"pvc block and pv block": {
|
||||
isExpectedMismatch: false,
|
||||
vol: createVolumeModeBlockTestVolume(),
|
||||
pvc: makeVolumeModePVC("8G", &blockMode, nil),
|
||||
enableBlock: true,
|
||||
},
|
||||
"feature enabled - pvc filesystem and pv filesystem": {
|
||||
"pvc filesystem and pv filesystem": {
|
||||
isExpectedMismatch: false,
|
||||
vol: createVolumeModeFilesystemTestVolume(),
|
||||
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
||||
enableBlock: true,
|
||||
},
|
||||
"feature enabled - pvc filesystem and pv nil": {
|
||||
"pvc filesystem and pv nil": {
|
||||
isExpectedMismatch: false,
|
||||
vol: createVolumeModeNilTestVolume(),
|
||||
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
||||
enableBlock: true,
|
||||
},
|
||||
"feature enabled - pvc nil and pv filesystem": {
|
||||
"pvc nil and pv filesystem": {
|
||||
isExpectedMismatch: false,
|
||||
vol: createVolumeModeFilesystemTestVolume(),
|
||||
pvc: makeVolumeModePVC("8G", nil, nil),
|
||||
enableBlock: true,
|
||||
},
|
||||
"feature enabled - pvc nil and pv nil": {
|
||||
"pvc nil and pv nil": {
|
||||
isExpectedMismatch: false,
|
||||
vol: createVolumeModeNilTestVolume(),
|
||||
pvc: makeVolumeModePVC("8G", nil, nil),
|
||||
enableBlock: true,
|
||||
},
|
||||
"feature enabled - pvc nil and pv block": {
|
||||
"pvc nil and pv block": {
|
||||
isExpectedMismatch: true,
|
||||
vol: createVolumeModeBlockTestVolume(),
|
||||
pvc: makeVolumeModePVC("8G", nil, nil),
|
||||
enableBlock: true,
|
||||
},
|
||||
"feature enabled - pvc block and pv nil": {
|
||||
"pvc block and pv nil": {
|
||||
isExpectedMismatch: true,
|
||||
vol: createVolumeModeNilTestVolume(),
|
||||
pvc: makeVolumeModePVC("8G", &blockMode, nil),
|
||||
enableBlock: true,
|
||||
},
|
||||
"feature disabled - pvc block and pv filesystem": {
|
||||
isExpectedMismatch: true,
|
||||
vol: createVolumeModeFilesystemTestVolume(),
|
||||
pvc: makeVolumeModePVC("8G", &blockMode, nil),
|
||||
enableBlock: false,
|
||||
},
|
||||
"feature disabled - pvc filesystem and pv block": {
|
||||
isExpectedMismatch: true,
|
||||
vol: createVolumeModeBlockTestVolume(),
|
||||
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
||||
enableBlock: false,
|
||||
},
|
||||
"feature disabled - pvc block and pv block": {
|
||||
isExpectedMismatch: true,
|
||||
vol: createVolumeModeBlockTestVolume(),
|
||||
pvc: makeVolumeModePVC("8G", &blockMode, nil),
|
||||
enableBlock: false,
|
||||
},
|
||||
"feature disabled - pvc filesystem and pv filesystem": {
|
||||
isExpectedMismatch: false,
|
||||
vol: createVolumeModeFilesystemTestVolume(),
|
||||
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
||||
enableBlock: false,
|
||||
},
|
||||
}
|
||||
|
||||
for name, scenario := range scenarios {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, scenario.enableBlock)()
|
||||
expectedMismatch := pvutil.CheckVolumeModeMismatches(&scenario.pvc.Spec, &scenario.vol.Spec)
|
||||
// expected to match but either got an error or no returned pvmatch
|
||||
if expectedMismatch && !scenario.isExpectedMismatch {
|
||||
@ -1167,73 +1132,46 @@ func TestFilteringVolumeModes(t *testing.T) {
|
||||
isExpectedMatch bool
|
||||
vol persistentVolumeOrderedIndex
|
||||
pvc *v1.PersistentVolumeClaim
|
||||
enableBlock bool
|
||||
}{
|
||||
"1-1 feature enabled - pvc block and pv filesystem": {
|
||||
"pvc block and pv filesystem": {
|
||||
isExpectedMatch: false,
|
||||
vol: createTestVolOrderedIndex(createVolumeModeFilesystemTestVolume()),
|
||||
pvc: makeVolumeModePVC("8G", &blockMode, nil),
|
||||
enableBlock: true,
|
||||
},
|
||||
"1-2 feature enabled - pvc filesystem and pv block": {
|
||||
"pvc filesystem and pv block": {
|
||||
isExpectedMatch: false,
|
||||
vol: createTestVolOrderedIndex(createVolumeModeBlockTestVolume()),
|
||||
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
||||
enableBlock: true,
|
||||
},
|
||||
"1-3 feature enabled - pvc block and pv no mode with default filesystem": {
|
||||
"pvc block and pv no mode with default filesystem": {
|
||||
isExpectedMatch: false,
|
||||
vol: createTestVolOrderedIndex(createVolumeModeFilesystemTestVolume()),
|
||||
pvc: makeVolumeModePVC("8G", &blockMode, nil),
|
||||
enableBlock: true,
|
||||
},
|
||||
"1-4 feature enabled - pvc no mode defaulted to filesystem and pv block": {
|
||||
"pvc no mode defaulted to filesystem and pv block": {
|
||||
isExpectedMatch: false,
|
||||
vol: createTestVolOrderedIndex(createVolumeModeBlockTestVolume()),
|
||||
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
||||
enableBlock: true,
|
||||
},
|
||||
"1-5 feature enabled - pvc block and pv block": {
|
||||
"pvc block and pv block": {
|
||||
isExpectedMatch: true,
|
||||
vol: createTestVolOrderedIndex(createVolumeModeBlockTestVolume()),
|
||||
pvc: makeVolumeModePVC("8G", &blockMode, nil),
|
||||
enableBlock: true,
|
||||
},
|
||||
"1-6 feature enabled - pvc filesystem and pv filesystem": {
|
||||
"pvc filesystem and pv filesystem": {
|
||||
isExpectedMatch: true,
|
||||
vol: createTestVolOrderedIndex(createVolumeModeFilesystemTestVolume()),
|
||||
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
||||
enableBlock: true,
|
||||
},
|
||||
"1-7 feature enabled - pvc mode is nil and defaulted and pv mode is nil and defaulted": {
|
||||
"pvc mode is nil and defaulted and pv mode is nil and defaulted": {
|
||||
isExpectedMatch: true,
|
||||
vol: createTestVolOrderedIndex(createVolumeModeFilesystemTestVolume()),
|
||||
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
||||
enableBlock: true,
|
||||
},
|
||||
"2-1 feature disabled - pvc mode is nil and pv mode is nil": {
|
||||
isExpectedMatch: true,
|
||||
vol: createTestVolOrderedIndex(testVolume("nomode-1", "8G")),
|
||||
pvc: makeVolumeModePVC("8G", nil, nil),
|
||||
enableBlock: false,
|
||||
},
|
||||
"2-2 feature disabled - pvc mode is block and pv mode is block - fields should be dropped by api and not analyzed with gate disabled": {
|
||||
isExpectedMatch: false,
|
||||
vol: createTestVolOrderedIndex(createVolumeModeBlockTestVolume()),
|
||||
pvc: makeVolumeModePVC("8G", &blockMode, nil),
|
||||
enableBlock: false,
|
||||
},
|
||||
"2-3 feature disabled - pvc mode is filesystem and pv mode is filesystem - fields should be dropped by api and not analyzed with gate disabled": {
|
||||
isExpectedMatch: true,
|
||||
vol: createTestVolOrderedIndex(createVolumeModeFilesystemTestVolume()),
|
||||
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
||||
enableBlock: false,
|
||||
},
|
||||
}
|
||||
|
||||
for name, scenario := range scenarios {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, scenario.enableBlock)()
|
||||
pvmatch, err := scenario.vol.findBestMatchForClaim(scenario.pvc, false)
|
||||
// expected to match but either got an error or no returned pvmatch
|
||||
if pvmatch == nil && scenario.isExpectedMatch {
|
||||
|
@ -6,7 +6,6 @@ go_library(
|
||||
importpath = "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/testing",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//pkg/features:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
@ -14,7 +13,6 @@ go_library(
|
||||
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/watch:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/testing:go_default_library",
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
|
@ -30,11 +30,9 @@ import (
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
core "k8s.io/client-go/testing"
|
||||
"k8s.io/klog"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
// ErrVersionConflict is the error returned when resource version of requested
|
||||
@ -114,7 +112,7 @@ func (r *VolumeReactor) React(action core.Action) (handled bool, ret runtime.Obj
|
||||
}
|
||||
|
||||
// mimic apiserver defaulting
|
||||
if volume.Spec.VolumeMode == nil && utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
||||
if volume.Spec.VolumeMode == nil {
|
||||
volume.Spec.VolumeMode = new(v1.PersistentVolumeMode)
|
||||
*volume.Spec.VolumeMode = v1.PersistentVolumeFilesystem
|
||||
}
|
||||
|
@ -307,23 +307,6 @@ func FindMatchingVolume(
|
||||
// CheckVolumeModeMismatches is a convenience method that checks volumeMode for PersistentVolume
|
||||
// and PersistentVolumeClaims
|
||||
func CheckVolumeModeMismatches(pvcSpec *v1.PersistentVolumeClaimSpec, pvSpec *v1.PersistentVolumeSpec) bool {
|
||||
if !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
||||
if pvcSpec.VolumeMode != nil && *pvcSpec.VolumeMode == v1.PersistentVolumeBlock {
|
||||
// Block PVC does not match anything when the feature is off. We explicitly want
|
||||
// to prevent binding block PVC to filesystem PV.
|
||||
// The PVC should be ignored by PV controller.
|
||||
return true
|
||||
}
|
||||
if pvSpec.VolumeMode != nil && *pvSpec.VolumeMode == v1.PersistentVolumeBlock {
|
||||
// Block PV does not match anything when the feature is off. We explicitly want
|
||||
// to prevent binding block PV to filesystem PVC.
|
||||
// The PV should be ignored by PV controller.
|
||||
return true
|
||||
}
|
||||
// Both PV + PVC are not block.
|
||||
return false
|
||||
}
|
||||
|
||||
// In HA upgrades, we cannot guarantee that the apiserver is on a version >= controller-manager.
|
||||
// So we default a nil volumeMode to filesystem
|
||||
requestedVolumeMode := v1.PersistentVolumeFilesystem
|
||||
|
@ -183,7 +183,8 @@ const (
|
||||
|
||||
// owner: @screeley44
|
||||
// alpha: v1.9
|
||||
// beta: v1.13
|
||||
// beta: v1.13
|
||||
// ga: v1.18
|
||||
//
|
||||
// Enable Block volume support in containers.
|
||||
BlockVolume featuregate.Feature = "BlockVolume"
|
||||
@ -295,7 +296,8 @@ const (
|
||||
|
||||
// owner: @vladimirvivien
|
||||
// alpha: v1.11
|
||||
// beta: v1.14
|
||||
// beta: v1.14
|
||||
// ga: v1.18
|
||||
//
|
||||
// Enables CSI to use raw block storage volumes
|
||||
CSIBlockVolume featuregate.Feature = "CSIBlockVolume"
|
||||
@ -594,7 +596,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
|
||||
NodeDisruptionExclusion: {Default: false, PreRelease: featuregate.Alpha},
|
||||
CSIDriverRegistry: {Default: true, PreRelease: featuregate.Beta},
|
||||
CSINodeInfo: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.19
|
||||
BlockVolume: {Default: true, PreRelease: featuregate.Beta},
|
||||
BlockVolume: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.20
|
||||
StorageObjectInUseProtection: {Default: true, PreRelease: featuregate.GA},
|
||||
ResourceLimitsPriorityFunction: {Default: false, PreRelease: featuregate.Alpha},
|
||||
SupportIPVSProxyMode: {Default: true, PreRelease: featuregate.GA},
|
||||
@ -621,7 +623,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
|
||||
VolumeSubpath: {Default: true, PreRelease: featuregate.GA},
|
||||
BalanceAttachedNodeVolumes: {Default: false, PreRelease: featuregate.Alpha},
|
||||
VolumeSubpathEnvExpansion: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.19,
|
||||
CSIBlockVolume: {Default: true, PreRelease: featuregate.Beta},
|
||||
CSIBlockVolume: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.20
|
||||
CSIInlineVolume: {Default: true, PreRelease: featuregate.Beta},
|
||||
RuntimeClass: {Default: true, PreRelease: featuregate.Beta},
|
||||
NodeLease: {Default: true, PreRelease: featuregate.GA, LockToDefault: true},
|
||||
|
@ -457,15 +457,12 @@ func (kl *Kubelet) GenerateRunContainerOptions(pod *v1.Pod, container *v1.Contai
|
||||
|
||||
opts.PortMappings = kubecontainer.MakePortMappings(container)
|
||||
|
||||
// TODO: remove feature gate check after no longer needed
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
||||
blkutil := volumepathhandler.NewBlockVolumePathHandler()
|
||||
blkVolumes, err := kl.makeBlockVolumes(pod, container, volumes, blkutil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opts.Devices = append(opts.Devices, blkVolumes...)
|
||||
blkutil := volumepathhandler.NewBlockVolumePathHandler()
|
||||
blkVolumes, err := kl.makeBlockVolumes(pod, container, volumes, blkutil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
opts.Devices = append(opts.Devices, blkVolumes...)
|
||||
|
||||
envs, err := kl.makeEnvironmentVariables(pod, container, podIP, podIPs)
|
||||
if err != nil {
|
||||
|
@ -48,7 +48,6 @@ go_test(
|
||||
srcs = ["volume_manager_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/kubelet/config:go_default_library",
|
||||
"//pkg/kubelet/configmap:go_default_library",
|
||||
"//pkg/kubelet/container/testing:go_default_library",
|
||||
@ -66,12 +65,10 @@ go_test(
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes/fake:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/tools/record:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/util/testing:go_default_library",
|
||||
"//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
|
||||
"//vendor/k8s.io/utils/mount:go_default_library",
|
||||
],
|
||||
)
|
||||
|
@ -541,14 +541,12 @@ func (dswp *desiredStateOfWorldPopulator) createVolumeSpec(
|
||||
podVolume.Name,
|
||||
volumeMode)
|
||||
}
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
||||
// Error if a container has volumeDevices but the volumeMode of PVC isn't Block
|
||||
if devices.Has(podVolume.Name) && volumeMode != v1.PersistentVolumeBlock {
|
||||
return nil, nil, "", fmt.Errorf(
|
||||
"volume %s has volumeMode %s, but is specified in volumeDevices",
|
||||
podVolume.Name,
|
||||
volumeMode)
|
||||
}
|
||||
// Error if a container has volumeDevices but the volumeMode of PVC isn't Block
|
||||
if devices.Has(podVolume.Name) && volumeMode != v1.PersistentVolumeBlock {
|
||||
return nil, nil, "", fmt.Errorf(
|
||||
"volume %s has volumeMode %s, but is specified in volumeDevices",
|
||||
podVolume.Name,
|
||||
volumeMode)
|
||||
}
|
||||
return pvc, volumeSpec, volumeGidValue, nil
|
||||
}
|
||||
|
@ -269,9 +269,6 @@ func TestFindAndRemoveDeletedPodsWithActualState(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestFindAndAddNewPods_FindAndRemoveDeletedPods_Valid_Block_VolumeDevices(t *testing.T) {
|
||||
// Enable BlockVolume feature gate
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
|
||||
|
||||
// create dswp
|
||||
mode := v1.PersistentVolumeBlock
|
||||
pv := &v1.PersistentVolume{
|
||||
@ -471,9 +468,6 @@ func TestCreateVolumeSpec_Valid_Nil_VolumeMounts(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCreateVolumeSpec_Valid_Block_VolumeDevices(t *testing.T) {
|
||||
// Enable BlockVolume feature gate
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
|
||||
|
||||
// create dswp
|
||||
mode := v1.PersistentVolumeBlock
|
||||
pv := &v1.PersistentVolume{
|
||||
@ -520,9 +514,6 @@ func TestCreateVolumeSpec_Valid_Block_VolumeDevices(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCreateVolumeSpec_Invalid_File_VolumeDevices(t *testing.T) {
|
||||
// Enable BlockVolume feature gate
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
|
||||
|
||||
// create dswp
|
||||
mode := v1.PersistentVolumeFilesystem
|
||||
pv := &v1.PersistentVolume{
|
||||
@ -569,9 +560,6 @@ func TestCreateVolumeSpec_Invalid_File_VolumeDevices(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCreateVolumeSpec_Invalid_Block_VolumeMounts(t *testing.T) {
|
||||
// Enable BlockVolume feature gate
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
|
||||
|
||||
// create dswp
|
||||
mode := v1.PersistentVolumeBlock
|
||||
pv := &v1.PersistentVolume{
|
||||
@ -617,56 +605,6 @@ func TestCreateVolumeSpec_Invalid_Block_VolumeMounts(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateVolumeSpec_Invalid_Block_VolumeMounts_Disabled(t *testing.T) {
|
||||
// Enable BlockVolume feature gate
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, false)()
|
||||
|
||||
// create dswp
|
||||
mode := v1.PersistentVolumeBlock
|
||||
pv := &v1.PersistentVolume{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "dswp-test-volume-name",
|
||||
},
|
||||
Spec: v1.PersistentVolumeSpec{
|
||||
ClaimRef: &v1.ObjectReference{Namespace: "ns", Name: "block-bound"},
|
||||
VolumeMode: &mode,
|
||||
},
|
||||
}
|
||||
pvc := &v1.PersistentVolumeClaim{
|
||||
Spec: v1.PersistentVolumeClaimSpec{
|
||||
VolumeName: "dswp-test-volume-name",
|
||||
VolumeMode: &mode,
|
||||
},
|
||||
Status: v1.PersistentVolumeClaimStatus{
|
||||
Phase: v1.ClaimBound,
|
||||
},
|
||||
}
|
||||
dswp, fakePodManager, _ := createDswpWithVolume(t, pv, pvc)
|
||||
|
||||
// create pod
|
||||
containers := []v1.Container{
|
||||
{
|
||||
VolumeMounts: []v1.VolumeMount{
|
||||
{
|
||||
Name: "dswp-test-volume-name",
|
||||
MountPath: "/mnt",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
pod := createPodWithVolume("dswp-test-pod", "dswp-test-volume-name", "block-bound", containers)
|
||||
|
||||
fakePodManager.AddPod(pod)
|
||||
mountsMap, devicesMap := util.GetPodVolumeNames(pod)
|
||||
_, volumeSpec, _, err :=
|
||||
dswp.createVolumeSpec(pod.Spec.Volumes[0], pod.Name, pod.Namespace, mountsMap, devicesMap)
|
||||
|
||||
// Assert
|
||||
if volumeSpec != nil || err == nil {
|
||||
t.Fatalf("Unexpected volumeMode and volumeMounts/volumeDevices combination is accepted")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckVolumeFSResize(t *testing.T) {
|
||||
setCapacity := func(pv *v1.PersistentVolume, pvc *v1.PersistentVolumeClaim, capacity int) {
|
||||
pv.Spec.Capacity = volumeCapacity(capacity)
|
||||
|
@ -487,8 +487,7 @@ func (rc *reconciler) reconstructVolume(volume podVolume) (*reconstructedVolume,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// TODO: remove feature gate check after no longer needed
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) && volume.volumeMode == v1.PersistentVolumeBlock && mapperPlugin == nil {
|
||||
if volume.volumeMode == v1.PersistentVolumeBlock && mapperPlugin == nil {
|
||||
return nil, fmt.Errorf("could not find block volume plugin %q (spec.Name: %q) pod %q (UID: %q)", volume.pluginName, volume.volumeSpecName, volume.podName, pod.UID)
|
||||
}
|
||||
|
||||
@ -521,8 +520,7 @@ func (rc *reconciler) reconstructVolume(volume podVolume) (*reconstructedVolume,
|
||||
// Path to the mount or block device to check
|
||||
var checkPath string
|
||||
|
||||
// TODO: remove feature gate check after no longer needed
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) && volume.volumeMode == v1.PersistentVolumeBlock {
|
||||
if volume.volumeMode == v1.PersistentVolumeBlock {
|
||||
var newMapperErr error
|
||||
volumeMapper, newMapperErr = mapperPlugin.NewBlockVolumeMapper(
|
||||
volumeSpec,
|
||||
@ -697,12 +695,10 @@ func getVolumesFromPodDir(podDir string) ([]podVolume, error) {
|
||||
volumesDirs := map[v1.PersistentVolumeMode]string{
|
||||
v1.PersistentVolumeFilesystem: path.Join(podDir, config.DefaultKubeletVolumesDirName),
|
||||
}
|
||||
// TODO: remove feature gate check after no longer needed
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
||||
// Find block volume information
|
||||
// ex. block volume: /pods/{podUid}/volumeDevices/{escapeQualifiedPluginName}/{volumeName}
|
||||
volumesDirs[v1.PersistentVolumeBlock] = path.Join(podDir, config.DefaultKubeletVolumeDevicesDirName)
|
||||
}
|
||||
// Find block volume information
|
||||
// ex. block volume: /pods/{podUid}/volumeDevices/{escapeQualifiedPluginName}/{volumeName}
|
||||
volumesDirs[v1.PersistentVolumeBlock] = path.Join(podDir, config.DefaultKubeletVolumeDevicesDirName)
|
||||
|
||||
for volumeMode, volumesDir := range volumesDirs {
|
||||
var volumesDirInfo []os.FileInfo
|
||||
if volumesDirInfo, err = ioutil.ReadDir(volumesDir); err != nil {
|
||||
|
@ -443,9 +443,6 @@ func Test_Run_Positive_VolumeUnmountControllerAttachEnabled(t *testing.T) {
|
||||
// Verifies there are attach/get map paths/setupDevice calls and
|
||||
// no detach/teardownDevice calls.
|
||||
func Test_Run_Positive_VolumeAttachAndMap(t *testing.T) {
|
||||
// Enable BlockVolume feature gate
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
|
||||
|
||||
pod := &v1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pod1",
|
||||
@ -543,9 +540,6 @@ func Test_Run_Positive_VolumeAttachAndMap(t *testing.T) {
|
||||
// and no teardownDevice call.
|
||||
// Verifies there are no attach/detach calls.
|
||||
func Test_Run_Positive_BlockVolumeMapControllerAttachEnabled(t *testing.T) {
|
||||
// Enable BlockVolume feature gate
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
|
||||
|
||||
pod := &v1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pod1",
|
||||
@ -647,9 +641,6 @@ func Test_Run_Positive_BlockVolumeMapControllerAttachEnabled(t *testing.T) {
|
||||
// Deletes volume/pod from desired state of world.
|
||||
// Verifies one detach/teardownDevice calls are issued.
|
||||
func Test_Run_Positive_BlockVolumeAttachMapUnmapDetach(t *testing.T) {
|
||||
// Enable BlockVolume feature gate
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
|
||||
|
||||
pod := &v1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pod1",
|
||||
@ -758,9 +749,6 @@ func Test_Run_Positive_BlockVolumeAttachMapUnmapDetach(t *testing.T) {
|
||||
// Verifies one teardownDevice call is made.
|
||||
// Verifies there are no attach/detach calls made.
|
||||
func Test_Run_Positive_VolumeUnmapControllerAttachEnabled(t *testing.T) {
|
||||
// Enable BlockVolume feature gate
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
|
||||
|
||||
pod := &v1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "pod1",
|
||||
@ -883,9 +871,6 @@ func Test_GenerateMapVolumeFunc_Plugin_Not_Found(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
// Enable BlockVolume feature gate
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
volumePluginMgr := &volume.VolumePluginMgr{}
|
||||
@ -937,9 +922,6 @@ func Test_GenerateUnmapVolumeFunc_Plugin_Not_Found(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
// Enable BlockVolume feature gate
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
volumePluginMgr := &volume.VolumePluginMgr{}
|
||||
@ -983,9 +965,6 @@ func Test_GenerateUnmapDeviceFunc_Plugin_Not_Found(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
// Enable BlockVolume feature gate
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
|
||||
|
||||
for name, tc := range testCases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
volumePluginMgr := &volume.VolumePluginMgr{}
|
||||
|
@ -30,13 +30,10 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
"k8s.io/client-go/tools/record"
|
||||
utiltesting "k8s.io/client-go/util/testing"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/kubelet/config"
|
||||
"k8s.io/kubernetes/pkg/kubelet/configmap"
|
||||
containertest "k8s.io/kubernetes/pkg/kubelet/container/testing"
|
||||
@ -58,11 +55,10 @@ const (
|
||||
|
||||
func TestGetMountedVolumesForPodAndGetVolumesInUse(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
pvMode, podMode v1.PersistentVolumeMode
|
||||
disableBlockFeature bool
|
||||
expectMount bool
|
||||
expectError bool
|
||||
name string
|
||||
pvMode, podMode v1.PersistentVolumeMode
|
||||
expectMount bool
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
name: "filesystem volume",
|
||||
@ -78,14 +74,6 @@ func TestGetMountedVolumesForPodAndGetVolumesInUse(t *testing.T) {
|
||||
expectMount: true,
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "block volume with block feature off",
|
||||
pvMode: v1.PersistentVolumeBlock,
|
||||
podMode: v1.PersistentVolumeBlock,
|
||||
disableBlockFeature: true,
|
||||
expectMount: false,
|
||||
expectError: false,
|
||||
},
|
||||
{
|
||||
name: "mismatched volume",
|
||||
pvMode: v1.PersistentVolumeBlock,
|
||||
@ -97,10 +85,6 @@ func TestGetMountedVolumesForPodAndGetVolumesInUse(t *testing.T) {
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
if test.disableBlockFeature {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, false)()
|
||||
}
|
||||
|
||||
tmpDir, err := utiltesting.MkTmpdir("volumeManagerTest")
|
||||
if err != nil {
|
||||
t.Fatalf("can't make a temp dir: %v", err)
|
||||
|
@ -20,7 +20,6 @@ go_library(
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/volume/awsebs",
|
||||
deps = [
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//pkg/volume/util:go_default_library",
|
||||
"//pkg/volume/util/volumepathhandler:go_default_library",
|
||||
@ -29,7 +28,6 @@ go_library(
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/cloud-provider:go_default_library",
|
||||
"//staging/src/k8s.io/cloud-provider/volume/helpers:go_default_library",
|
||||
"//staging/src/k8s.io/legacy-cloud-providers/aws:go_default_library",
|
||||
|
@ -35,8 +35,6 @@ import (
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
"k8s.io/kubernetes/pkg/volume/util"
|
||||
"k8s.io/legacy-cloud-providers/aws"
|
||||
@ -501,13 +499,10 @@ func (c *awsElasticBlockStoreProvisioner) Provision(selectedNode *v1.Node, allow
|
||||
fstype = "ext4"
|
||||
}
|
||||
|
||||
var volumeMode *v1.PersistentVolumeMode
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
||||
volumeMode = c.options.PVC.Spec.VolumeMode
|
||||
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
|
||||
// Block volumes should not have any FSType
|
||||
fstype = ""
|
||||
}
|
||||
volumeMode := c.options.PVC.Spec.VolumeMode
|
||||
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
|
||||
// Block volumes should not have any FSType
|
||||
fstype = ""
|
||||
}
|
||||
|
||||
pv := &v1.PersistentVolume{
|
||||
|
@ -24,7 +24,6 @@ go_library(
|
||||
importpath = "k8s.io/kubernetes/pkg/volume/azure_dd",
|
||||
deps = [
|
||||
"//pkg/apis/core:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//pkg/volume/util:go_default_library",
|
||||
"//pkg/volume/util/volumepathhandler:go_default_library",
|
||||
@ -34,7 +33,6 @@ go_library(
|
||||
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/cloud-provider:go_default_library",
|
||||
"//staging/src/k8s.io/cloud-provider/volume/helpers:go_default_library",
|
||||
"//staging/src/k8s.io/legacy-cloud-providers/azure:go_default_library",
|
||||
|
@ -29,9 +29,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
volumehelpers "k8s.io/cloud-provider/volume/helpers"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
"k8s.io/kubernetes/pkg/volume/util"
|
||||
"k8s.io/legacy-cloud-providers/azure"
|
||||
@ -286,13 +284,10 @@ func (p *azureDiskProvisioner) Provision(selectedNode *v1.Node, allowedTopologie
|
||||
}
|
||||
}
|
||||
|
||||
var volumeMode *v1.PersistentVolumeMode
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
||||
volumeMode = p.options.PVC.Spec.VolumeMode
|
||||
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
|
||||
// Block volumes should not have any FSType
|
||||
fsType = ""
|
||||
}
|
||||
volumeMode := p.options.PVC.Spec.VolumeMode
|
||||
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
|
||||
// Block volumes should not have any FSType
|
||||
fsType = ""
|
||||
}
|
||||
|
||||
pv := &v1.PersistentVolume{
|
||||
|
@ -17,7 +17,6 @@ go_library(
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/volume/cinder",
|
||||
deps = [
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//pkg/volume/util:go_default_library",
|
||||
"//pkg/volume/util/volumepathhandler:go_default_library",
|
||||
@ -27,7 +26,6 @@ go_library(
|
||||
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//staging/src/k8s.io/cloud-provider:go_default_library",
|
||||
"//staging/src/k8s.io/cloud-provider/volume/helpers:go_default_library",
|
||||
|
@ -34,9 +34,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
cloudprovider "k8s.io/cloud-provider"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
"k8s.io/kubernetes/pkg/volume/util"
|
||||
"k8s.io/legacy-cloud-providers/openstack"
|
||||
@ -572,13 +570,10 @@ func (c *cinderVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopolo
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var volumeMode *v1.PersistentVolumeMode
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
||||
volumeMode = c.options.PVC.Spec.VolumeMode
|
||||
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
|
||||
// Block volumes should not have any FSType
|
||||
fstype = ""
|
||||
}
|
||||
volumeMode := c.options.PVC.Spec.VolumeMode
|
||||
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
|
||||
// Block volumes should not have any FSType
|
||||
fstype = ""
|
||||
}
|
||||
|
||||
pv := &v1.PersistentVolume{
|
||||
|
@ -17,14 +17,12 @@ go_library(
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/volume/fc",
|
||||
deps = [
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//pkg/volume/util:go_default_library",
|
||||
"//pkg/volume/util/volumepathhandler:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
"//vendor/k8s.io/utils/mount:go_default_library",
|
||||
|
@ -28,8 +28,6 @@ import (
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
||||
)
|
||||
@ -209,26 +207,17 @@ func volumeSpecToMounter(spec *volume.Spec, host volume.VolumeHost) (*fcDiskMoun
|
||||
wwids: wwids,
|
||||
io: &osIOHandler{},
|
||||
}
|
||||
// TODO: remove feature gate check after no longer needed
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
||||
volumeMode, err := volumeutil.GetVolumeMode(spec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
klog.V(5).Infof("fc: volumeSpecToMounter volumeMode %s", volumeMode)
|
||||
return &fcDiskMounter{
|
||||
fcDisk: fcDisk,
|
||||
fsType: fc.FSType,
|
||||
volumeMode: volumeMode,
|
||||
readOnly: readOnly,
|
||||
mounter: volumeutil.NewSafeFormatAndMountFromHost(fcPluginName, host),
|
||||
deviceUtil: volumeutil.NewDeviceHandler(volumeutil.NewIOHandler()),
|
||||
mountOptions: volumeutil.MountOptionFromSpec(spec),
|
||||
}, nil
|
||||
|
||||
volumeMode, err := volumeutil.GetVolumeMode(spec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
klog.V(5).Infof("fc: volumeSpecToMounter volumeMode %s", volumeMode)
|
||||
return &fcDiskMounter{
|
||||
fcDisk: fcDisk,
|
||||
fsType: fc.FSType,
|
||||
volumeMode: volumeMode,
|
||||
readOnly: readOnly,
|
||||
mounter: volumeutil.NewSafeFormatAndMountFromHost(fcPluginName, host),
|
||||
deviceUtil: volumeutil.NewDeviceHandler(volumeutil.NewIOHandler()),
|
||||
|
@ -31,8 +31,6 @@ import (
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
"k8s.io/kubernetes/pkg/volume/util"
|
||||
"k8s.io/kubernetes/pkg/volume/util/volumepathhandler"
|
||||
@ -134,32 +132,22 @@ func (plugin *fcPlugin) newMounterInternal(spec *volume.Spec, podUID types.UID,
|
||||
io: &osIOHandler{},
|
||||
plugin: plugin,
|
||||
}
|
||||
// TODO: remove feature gate check after no longer needed
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
||||
volumeMode, err := util.GetVolumeMode(spec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
klog.V(5).Infof("fc: newMounterInternal volumeMode %s", volumeMode)
|
||||
return &fcDiskMounter{
|
||||
fcDisk: fcDisk,
|
||||
fsType: fc.FSType,
|
||||
volumeMode: volumeMode,
|
||||
readOnly: readOnly,
|
||||
mounter: &mount.SafeFormatAndMount{Interface: mounter, Exec: exec},
|
||||
deviceUtil: util.NewDeviceHandler(util.NewIOHandler()),
|
||||
mountOptions: util.MountOptionFromSpec(spec),
|
||||
}, nil
|
||||
|
||||
volumeMode, err := util.GetVolumeMode(spec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
klog.V(5).Infof("fc: newMounterInternal volumeMode %s", volumeMode)
|
||||
return &fcDiskMounter{
|
||||
fcDisk: fcDisk,
|
||||
fsType: fc.FSType,
|
||||
volumeMode: volumeMode,
|
||||
readOnly: readOnly,
|
||||
mounter: &mount.SafeFormatAndMount{Interface: mounter, Exec: exec},
|
||||
deviceUtil: util.NewDeviceHandler(util.NewIOHandler()),
|
||||
mountOptions: util.MountOptionFromSpec(spec),
|
||||
}, nil
|
||||
|
||||
}
|
||||
|
||||
func (plugin *fcPlugin) NewBlockVolumeMapper(spec *volume.Spec, pod *v1.Pod, _ volume.VolumeOptions) (volume.BlockVolumeMapper, error) {
|
||||
|
@ -28,8 +28,6 @@ import (
|
||||
"k8s.io/utils/mount"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
||||
)
|
||||
@ -243,14 +241,12 @@ func (util *fcUtil) AttachDisk(b fcDiskMounter) (string, error) {
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// TODO: remove feature gate check after no longer needed
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
||||
// If the volumeMode is 'Block', plugin don't have to format the volume.
|
||||
// The globalPDPath will be created by operationexecutor. Just return devicePath here.
|
||||
klog.V(5).Infof("fc: AttachDisk volumeMode: %s, devicePath: %s", b.volumeMode, devicePath)
|
||||
if b.volumeMode == v1.PersistentVolumeBlock {
|
||||
return devicePath, nil
|
||||
}
|
||||
|
||||
// If the volumeMode is 'Block', plugin don't have to format the volume.
|
||||
// The globalPDPath will be created by operationexecutor. Just return devicePath here.
|
||||
klog.V(5).Infof("fc: AttachDisk volumeMode: %s, devicePath: %s", b.volumeMode, devicePath)
|
||||
if b.volumeMode == v1.PersistentVolumeBlock {
|
||||
return devicePath, nil
|
||||
}
|
||||
|
||||
// mount it
|
||||
|
@ -17,7 +17,6 @@ go_library(
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/volume/gcepd",
|
||||
deps = [
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//pkg/volume/util:go_default_library",
|
||||
"//pkg/volume/util/volumepathhandler:go_default_library",
|
||||
@ -26,7 +25,6 @@ go_library(
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/cloud-provider:go_default_library",
|
||||
"//staging/src/k8s.io/cloud-provider/volume:go_default_library",
|
||||
"//staging/src/k8s.io/cloud-provider/volume/helpers:go_default_library",
|
||||
|
@ -34,9 +34,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
volumehelpers "k8s.io/cloud-provider/volume/helpers"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
"k8s.io/kubernetes/pkg/volume/util"
|
||||
gcecloud "k8s.io/legacy-cloud-providers/gce"
|
||||
@ -500,13 +498,10 @@ func (c *gcePersistentDiskProvisioner) Provision(selectedNode *v1.Node, allowedT
|
||||
fstype = "ext4"
|
||||
}
|
||||
|
||||
var volumeMode *v1.PersistentVolumeMode
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
||||
volumeMode = c.options.PVC.Spec.VolumeMode
|
||||
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
|
||||
// Block volumes should not have any FSType
|
||||
fstype = ""
|
||||
}
|
||||
volumeMode := c.options.PVC.Spec.VolumeMode
|
||||
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
|
||||
// Block volumes should not have any FSType
|
||||
fstype = ""
|
||||
}
|
||||
|
||||
pv := &v1.PersistentVolume{
|
||||
|
@ -17,7 +17,6 @@ go_library(
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/volume/iscsi",
|
||||
deps = [
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/kubelet/config:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//pkg/volume/util:go_default_library",
|
||||
@ -25,7 +24,6 @@ go_library(
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
"//vendor/k8s.io/utils/exec:go_default_library",
|
||||
"//vendor/k8s.io/utils/keymutex:go_default_library",
|
||||
|
@ -27,8 +27,6 @@ import (
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
||||
)
|
||||
@ -209,26 +207,17 @@ func volumeSpecToMounter(spec *volume.Spec, host volume.VolumeHost, targetLocks
|
||||
return nil, err
|
||||
}
|
||||
exec := host.GetExec(iscsiPluginName)
|
||||
// TODO: remove feature gate check after no longer needed
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
||||
volumeMode, err := volumeutil.GetVolumeMode(spec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
klog.V(5).Infof("iscsi: VolumeSpecToMounter volumeMode %s", volumeMode)
|
||||
return &iscsiDiskMounter{
|
||||
iscsiDisk: iscsiDisk,
|
||||
fsType: fsType,
|
||||
volumeMode: volumeMode,
|
||||
readOnly: readOnly,
|
||||
mounter: &mount.SafeFormatAndMount{Interface: host.GetMounter(iscsiPluginName), Exec: exec},
|
||||
exec: exec,
|
||||
deviceUtil: volumeutil.NewDeviceHandler(volumeutil.NewIOHandler()),
|
||||
}, nil
|
||||
|
||||
volumeMode, err := volumeutil.GetVolumeMode(spec)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
klog.V(5).Infof("iscsi: VolumeSpecToMounter volumeMode %s", volumeMode)
|
||||
return &iscsiDiskMounter{
|
||||
iscsiDisk: iscsiDisk,
|
||||
fsType: fsType,
|
||||
volumeMode: volumeMode,
|
||||
readOnly: readOnly,
|
||||
mounter: &mount.SafeFormatAndMount{Interface: host.GetMounter(iscsiPluginName), Exec: exec},
|
||||
exec: exec,
|
||||
|
@ -34,8 +34,6 @@ import (
|
||||
"k8s.io/utils/mount"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/kubelet/config"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
||||
@ -469,25 +467,23 @@ func (util *ISCSIUtil) AttachDisk(b iscsiDiskMounter) (string, error) {
|
||||
// If the volumeMode is 'Block', plugin creates a dir and persists iscsi configurations.
|
||||
// Since volume type is block, plugin doesn't need to format/mount the volume.
|
||||
func globalPDPathOperation(b iscsiDiskMounter) func(iscsiDiskMounter, string, *ISCSIUtil) (string, error) {
|
||||
// TODO: remove feature gate check after no longer needed
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
||||
klog.V(5).Infof("iscsi: AttachDisk volumeMode: %s", b.volumeMode)
|
||||
if b.volumeMode == v1.PersistentVolumeBlock {
|
||||
// If the volumeMode is 'Block', plugin don't need to format the volume.
|
||||
return func(b iscsiDiskMounter, devicePath string, util *ISCSIUtil) (string, error) {
|
||||
globalPDPath := b.manager.MakeGlobalVDPDName(*b.iscsiDisk)
|
||||
// Create dir like /var/lib/kubelet/plugins/kubernetes.io/iscsi/volumeDevices/{ifaceName}/{portal-some_iqn-lun-lun_id}
|
||||
if err := os.MkdirAll(globalPDPath, 0750); err != nil {
|
||||
klog.Errorf("iscsi: failed to mkdir %s, error", globalPDPath)
|
||||
return "", err
|
||||
}
|
||||
// Persist iscsi disk config to json file for DetachDisk path
|
||||
util.persistISCSI(*(b.iscsiDisk), globalPDPath)
|
||||
|
||||
return devicePath, nil
|
||||
klog.V(5).Infof("iscsi: AttachDisk volumeMode: %s", b.volumeMode)
|
||||
if b.volumeMode == v1.PersistentVolumeBlock {
|
||||
// If the volumeMode is 'Block', plugin don't need to format the volume.
|
||||
return func(b iscsiDiskMounter, devicePath string, util *ISCSIUtil) (string, error) {
|
||||
globalPDPath := b.manager.MakeGlobalVDPDName(*b.iscsiDisk)
|
||||
// Create dir like /var/lib/kubelet/plugins/kubernetes.io/iscsi/volumeDevices/{ifaceName}/{portal-some_iqn-lun-lun_id}
|
||||
if err := os.MkdirAll(globalPDPath, 0750); err != nil {
|
||||
klog.Errorf("iscsi: failed to mkdir %s, error", globalPDPath)
|
||||
return "", err
|
||||
}
|
||||
// Persist iscsi disk config to json file for DetachDisk path
|
||||
util.persistISCSI(*(b.iscsiDisk), globalPDPath)
|
||||
|
||||
return devicePath, nil
|
||||
}
|
||||
}
|
||||
|
||||
// If the volumeMode is 'Filesystem', plugin needs to format the volume
|
||||
// and mount it to globalPDPath.
|
||||
return func(b iscsiDiskMounter, devicePath string, util *ISCSIUtil) (string, error) {
|
||||
|
@ -17,7 +17,6 @@ go_library(
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/volume/rbd",
|
||||
deps = [
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/util/node:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//pkg/volume/util:go_default_library",
|
||||
@ -30,7 +29,6 @@ go_library(
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/uuid:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//staging/src/k8s.io/cloud-provider/volume/helpers:go_default_library",
|
||||
"//vendor/k8s.io/klog:go_default_library",
|
||||
|
@ -35,9 +35,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/uuid"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
"k8s.io/kubernetes/pkg/volume/util"
|
||||
volutil "k8s.io/kubernetes/pkg/volume/util"
|
||||
@ -717,13 +715,10 @@ func (r *rbdVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopologie
|
||||
rbd.Keyring = keyring
|
||||
}
|
||||
|
||||
var volumeMode *v1.PersistentVolumeMode
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
||||
volumeMode = r.options.PVC.Spec.VolumeMode
|
||||
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
|
||||
// Block volumes should not have any FSType
|
||||
fstype = ""
|
||||
}
|
||||
volumeMode := r.options.PVC.Spec.VolumeMode
|
||||
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
|
||||
// Block volumes should not have any FSType
|
||||
fstype = ""
|
||||
}
|
||||
|
||||
rbd.RadosUser = r.ID
|
||||
|
@ -22,7 +22,6 @@ go_library(
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/api/v1/pod:go_default_library",
|
||||
"//pkg/apis/core/v1/helper:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/util/resizefs:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//pkg/volume/util/types:go_default_library",
|
||||
@ -38,7 +37,6 @@ go_library(
|
||||
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//staging/src/k8s.io/component-base/metrics:go_default_library",
|
||||
"//staging/src/k8s.io/component-base/metrics/legacyregistry:go_default_library",
|
||||
|
@ -39,12 +39,10 @@ import (
|
||||
apiruntime "k8s.io/apimachinery/pkg/runtime"
|
||||
utypes "k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
||||
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
"k8s.io/kubernetes/pkg/volume/util/types"
|
||||
"k8s.io/kubernetes/pkg/volume/util/volumepathhandler"
|
||||
@ -436,14 +434,12 @@ func GetPersistentVolumeClaimQualifiedName(claim *v1.PersistentVolumeClaim) stri
|
||||
// CheckVolumeModeFilesystem checks VolumeMode.
|
||||
// If the mode is Filesystem, return true otherwise return false.
|
||||
func CheckVolumeModeFilesystem(volumeSpec *volume.Spec) (bool, error) {
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
||||
volumeMode, err := GetVolumeMode(volumeSpec)
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
if volumeMode == v1.PersistentVolumeBlock {
|
||||
return false, nil
|
||||
}
|
||||
volumeMode, err := GetVolumeMode(volumeSpec)
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
if volumeMode == v1.PersistentVolumeBlock {
|
||||
return false, nil
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
@ -451,7 +447,7 @@ func CheckVolumeModeFilesystem(volumeSpec *volume.Spec) (bool, error) {
|
||||
// CheckPersistentVolumeClaimModeBlock checks VolumeMode.
|
||||
// If the mode is Block, return true otherwise return false.
|
||||
func CheckPersistentVolumeClaimModeBlock(pvc *v1.PersistentVolumeClaim) bool {
|
||||
return utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) && pvc.Spec.VolumeMode != nil && *pvc.Spec.VolumeMode == v1.PersistentVolumeBlock
|
||||
return pvc.Spec.VolumeMode != nil && *pvc.Spec.VolumeMode == v1.PersistentVolumeBlock
|
||||
}
|
||||
|
||||
// IsWindowsUNCPath checks if path is prefixed with \\
|
||||
@ -602,9 +598,7 @@ func GetPodVolumeNames(pod *v1.Pod) (mounts sets.String, devices sets.String) {
|
||||
mounts.Insert(mount.Name)
|
||||
}
|
||||
}
|
||||
// TODO: remove feature gate check after no longer needed
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) &&
|
||||
container.VolumeDevices != nil {
|
||||
if container.VolumeDevices != nil {
|
||||
for _, device := range container.VolumeDevices {
|
||||
devices.Insert(device.Name)
|
||||
}
|
||||
|
@ -20,7 +20,6 @@ go_library(
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/volume/vsphere_volume",
|
||||
deps = [
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//pkg/volume/util:go_default_library",
|
||||
"//pkg/volume/util/volumepathhandler:go_default_library",
|
||||
@ -28,7 +27,6 @@ go_library(
|
||||
"//staging/src/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//staging/src/k8s.io/cloud-provider:go_default_library",
|
||||
"//staging/src/k8s.io/cloud-provider/volume/helpers:go_default_library",
|
||||
"//staging/src/k8s.io/legacy-cloud-providers/vsphere:go_default_library",
|
||||
|
@ -33,9 +33,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
volumehelpers "k8s.io/cloud-provider/volume/helpers"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
"k8s.io/kubernetes/pkg/volume/util"
|
||||
)
|
||||
@ -382,13 +380,10 @@ func (v *vsphereVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopol
|
||||
volSpec.Fstype = "ext4"
|
||||
}
|
||||
|
||||
var volumeMode *v1.PersistentVolumeMode
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
||||
volumeMode = v.options.PVC.Spec.VolumeMode
|
||||
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
|
||||
klog.V(5).Infof("vSphere block volume should not have any FSType")
|
||||
volSpec.Fstype = ""
|
||||
}
|
||||
volumeMode := v.options.PVC.Spec.VolumeMode
|
||||
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
|
||||
klog.V(5).Infof("vSphere block volume should not have any FSType")
|
||||
volSpec.Fstype = ""
|
||||
}
|
||||
|
||||
pv := &v1.PersistentVolume{
|
||||
|
@ -689,7 +689,6 @@ message Container {
|
||||
repeated VolumeMount volumeMounts = 9;
|
||||
|
||||
// volumeDevices is the list of block devices to be used by the container.
|
||||
// This is a beta feature.
|
||||
// +patchMergeKey=devicePath
|
||||
// +patchStrategy=merge
|
||||
// +optional
|
||||
@ -1276,7 +1275,6 @@ message EphemeralContainerCommon {
|
||||
repeated VolumeMount volumeMounts = 9;
|
||||
|
||||
// volumeDevices is the list of block devices to be used by the container.
|
||||
// This is a beta feature.
|
||||
// +patchMergeKey=devicePath
|
||||
// +patchStrategy=merge
|
||||
// +optional
|
||||
@ -2636,7 +2634,6 @@ message PersistentVolumeClaimSpec {
|
||||
|
||||
// volumeMode defines what type of volume is required by the claim.
|
||||
// Value of Filesystem is implied when not included in claim spec.
|
||||
// This is a beta feature.
|
||||
// +optional
|
||||
optional string volumeMode = 6;
|
||||
|
||||
@ -2852,7 +2849,6 @@ message PersistentVolumeSpec {
|
||||
|
||||
// volumeMode defines if a volume is intended to be used with a formatted filesystem
|
||||
// or to remain in raw block state. Value of Filesystem is implied when not included in spec.
|
||||
// This is a beta feature.
|
||||
// +optional
|
||||
optional string volumeMode = 8;
|
||||
|
||||
|
@ -331,7 +331,6 @@ type PersistentVolumeSpec struct {
|
||||
MountOptions []string `json:"mountOptions,omitempty" protobuf:"bytes,7,opt,name=mountOptions"`
|
||||
// volumeMode defines if a volume is intended to be used with a formatted filesystem
|
||||
// or to remain in raw block state. Value of Filesystem is implied when not included in spec.
|
||||
// This is a beta feature.
|
||||
// +optional
|
||||
VolumeMode *PersistentVolumeMode `json:"volumeMode,omitempty" protobuf:"bytes,8,opt,name=volumeMode,casttype=PersistentVolumeMode"`
|
||||
// NodeAffinity defines constraints that limit what nodes this volume can be accessed from.
|
||||
@ -460,7 +459,6 @@ type PersistentVolumeClaimSpec struct {
|
||||
StorageClassName *string `json:"storageClassName,omitempty" protobuf:"bytes,5,opt,name=storageClassName"`
|
||||
// volumeMode defines what type of volume is required by the claim.
|
||||
// Value of Filesystem is implied when not included in claim spec.
|
||||
// This is a beta feature.
|
||||
// +optional
|
||||
VolumeMode *PersistentVolumeMode `json:"volumeMode,omitempty" protobuf:"bytes,6,opt,name=volumeMode,casttype=PersistentVolumeMode"`
|
||||
// This field requires the VolumeSnapshotDataSource alpha feature gate to be
|
||||
@ -2181,7 +2179,6 @@ type Container struct {
|
||||
// +patchStrategy=merge
|
||||
VolumeMounts []VolumeMount `json:"volumeMounts,omitempty" patchStrategy:"merge" patchMergeKey:"mountPath" protobuf:"bytes,9,rep,name=volumeMounts"`
|
||||
// volumeDevices is the list of block devices to be used by the container.
|
||||
// This is a beta feature.
|
||||
// +patchMergeKey=devicePath
|
||||
// +patchStrategy=merge
|
||||
// +optional
|
||||
@ -3298,7 +3295,6 @@ type EphemeralContainerCommon struct {
|
||||
// +patchStrategy=merge
|
||||
VolumeMounts []VolumeMount `json:"volumeMounts,omitempty" patchStrategy:"merge" patchMergeKey:"mountPath" protobuf:"bytes,9,rep,name=volumeMounts"`
|
||||
// volumeDevices is the list of block devices to be used by the container.
|
||||
// This is a beta feature.
|
||||
// +patchMergeKey=devicePath
|
||||
// +patchStrategy=merge
|
||||
// +optional
|
||||
|
@ -336,7 +336,7 @@ var map_Container = map[string]string{
|
||||
"env": "List of environment variables to set in the container. Cannot be updated.",
|
||||
"resources": "Compute Resources required by this container. Cannot be updated. More info: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/",
|
||||
"volumeMounts": "Pod volumes to mount into the container's filesystem. Cannot be updated.",
|
||||
"volumeDevices": "volumeDevices is the list of block devices to be used by the container. This is a beta feature.",
|
||||
"volumeDevices": "volumeDevices is the list of block devices to be used by the container.",
|
||||
"livenessProbe": "Periodic probe of container liveness. Container will be restarted if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes",
|
||||
"readinessProbe": "Periodic probe of container service readiness. Container will be removed from service endpoints if the probe fails. Cannot be updated. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes",
|
||||
"startupProbe": "StartupProbe indicates that the Pod has successfully initialized. If specified, no other probes are executed until this completes successfully. If this probe fails, the Pod will be restarted, just as if the livenessProbe failed. This can be used to provide different probe parameters at the beginning of a Pod's lifecycle, when it might take a long time to load data or warm a cache, than during steady-state operation. This cannot be updated. This is a beta feature enabled by the StartupProbe feature flag. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#container-probes",
|
||||
@ -599,7 +599,7 @@ var map_EphemeralContainerCommon = map[string]string{
|
||||
"env": "List of environment variables to set in the container. Cannot be updated.",
|
||||
"resources": "Resources are not allowed for ephemeral containers. Ephemeral containers use spare resources already allocated to the pod.",
|
||||
"volumeMounts": "Pod volumes to mount into the container's filesystem. Cannot be updated.",
|
||||
"volumeDevices": "volumeDevices is the list of block devices to be used by the container. This is a beta feature.",
|
||||
"volumeDevices": "volumeDevices is the list of block devices to be used by the container.",
|
||||
"livenessProbe": "Probes are not allowed for ephemeral containers.",
|
||||
"readinessProbe": "Probes are not allowed for ephemeral containers.",
|
||||
"startupProbe": "Probes are not allowed for ephemeral containers.",
|
||||
@ -1300,7 +1300,7 @@ var map_PersistentVolumeClaimSpec = map[string]string{
|
||||
"resources": "Resources represents the minimum resources the volume should have. 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. This is a beta feature.",
|
||||
"volumeMode": "volumeMode defines what type of volume is required by the claim. Value of Filesystem is implied when not included in claim spec.",
|
||||
"dataSource": "This field requires the VolumeSnapshotDataSource alpha feature gate to be enabled and currently VolumeSnapshot is the only supported data source. If the provisioner can support VolumeSnapshot data source, it will create a new volume and data will be restored to the volume at the same time. If the provisioner does not support VolumeSnapshot data source, volume will not be created and the failure will be reported as an event. In the future, we plan to support more data source types and the behavior of the provisioner may change.",
|
||||
}
|
||||
|
||||
@ -1378,7 +1378,7 @@ var map_PersistentVolumeSpec = map[string]string{
|
||||
"persistentVolumeReclaimPolicy": "What happens to a persistent volume when released from its claim. Valid options are Retain (default for manually created PersistentVolumes), Delete (default for dynamically provisioned PersistentVolumes), and Recycle (deprecated). Recycle must be supported by the volume plugin underlying this PersistentVolume. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#reclaiming",
|
||||
"storageClassName": "Name of StorageClass to which this persistent volume belongs. Empty value means that this volume does not belong to any StorageClass.",
|
||||
"mountOptions": "A list of mount options, e.g. [\"ro\", \"soft\"]. Not validated - mount will simply fail if one is invalid. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes/#mount-options",
|
||||
"volumeMode": "volumeMode defines if a volume is intended to be used with a formatted filesystem or to remain in raw block state. Value of Filesystem is implied when not included in spec. This is a beta feature.",
|
||||
"volumeMode": "volumeMode defines if a volume is intended to be used with a formatted filesystem or to remain in raw block state. Value of Filesystem is implied when not included in spec.",
|
||||
"nodeAffinity": "NodeAffinity defines constraints that limit what nodes this volume can be accessed from. This field influences the scheduling of pods that use this volume.",
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user