mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-29 22:46:12 +00:00
Promote block volume features to GA
This commit is contained in:
parent
a9c7529f99
commit
2c1b743766
@ -25,10 +25,6 @@ import (
|
|||||||
// DropDisabledFields removes disabled fields from the pv spec.
|
// DropDisabledFields removes disabled fields from the pv spec.
|
||||||
// This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a pv spec.
|
// This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a pv spec.
|
||||||
func DropDisabledFields(pvSpec *api.PersistentVolumeSpec, oldPVSpec *api.PersistentVolumeSpec) {
|
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 !utilfeature.DefaultFeatureGate.Enabled(features.ExpandCSIVolumes) && !hasExpansionSecrets(oldPVSpec) {
|
||||||
if pvSpec.CSI != nil {
|
if pvSpec.CSI != nil {
|
||||||
pvSpec.CSI.ControllerExpandSecretRef = nil
|
pvSpec.CSI.ControllerExpandSecretRef = nil
|
||||||
@ -46,13 +42,3 @@ func hasExpansionSecrets(oldPVSpec *api.PersistentVolumeSpec) bool {
|
|||||||
}
|
}
|
||||||
return false
|
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) {
|
func TestDropDisabledFields(t *testing.T) {
|
||||||
specWithMode := func(mode *api.PersistentVolumeMode) *api.PersistentVolumeSpec {
|
|
||||||
return &api.PersistentVolumeSpec{VolumeMode: mode}
|
|
||||||
}
|
|
||||||
|
|
||||||
secretRef := &api.SecretReference{
|
secretRef := &api.SecretReference{
|
||||||
Name: "expansion-secret",
|
Name: "expansion-secret",
|
||||||
Namespace: "default",
|
Namespace: "default",
|
||||||
}
|
}
|
||||||
|
|
||||||
modeBlock := api.PersistentVolumeBlock
|
|
||||||
|
|
||||||
tests := map[string]struct {
|
tests := map[string]struct {
|
||||||
oldSpec *api.PersistentVolumeSpec
|
oldSpec *api.PersistentVolumeSpec
|
||||||
newSpec *api.PersistentVolumeSpec
|
newSpec *api.PersistentVolumeSpec
|
||||||
expectOldSpec *api.PersistentVolumeSpec
|
expectOldSpec *api.PersistentVolumeSpec
|
||||||
expectNewSpec *api.PersistentVolumeSpec
|
expectNewSpec *api.PersistentVolumeSpec
|
||||||
blockEnabled bool
|
|
||||||
csiExpansionEnabled 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": {
|
"disabled csi expansion clears secrets": {
|
||||||
csiExpansionEnabled: false,
|
csiExpansionEnabled: false,
|
||||||
newSpec: specWithCSISecrets(secretRef),
|
newSpec: specWithCSISecrets(secretRef),
|
||||||
@ -129,7 +79,6 @@ func TestDropDisabledFields(t *testing.T) {
|
|||||||
|
|
||||||
for name, tc := range tests {
|
for name, tc := range tests {
|
||||||
t.Run(name, func(t *testing.T) {
|
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)()
|
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ExpandCSIVolumes, tc.csiExpansionEnabled)()
|
||||||
|
|
||||||
DropDisabledFields(tc.newSpec, tc.oldSpec)
|
DropDisabledFields(tc.newSpec, tc.oldSpec)
|
||||||
|
@ -30,24 +30,11 @@ const (
|
|||||||
// DropDisabledFields removes disabled fields from the pvc spec.
|
// DropDisabledFields removes disabled fields from the pvc spec.
|
||||||
// This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a pvc spec.
|
// This should be called from PrepareForCreate/PrepareForUpdate for all resources containing a pvc spec.
|
||||||
func DropDisabledFields(pvcSpec, oldPVCSpec *core.PersistentVolumeClaimSpec) {
|
func DropDisabledFields(pvcSpec, oldPVCSpec *core.PersistentVolumeClaimSpec) {
|
||||||
if !utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) && !volumeModeInUse(oldPVCSpec) {
|
|
||||||
pvcSpec.VolumeMode = nil
|
|
||||||
}
|
|
||||||
if !dataSourceIsEnabled(pvcSpec) && !dataSourceInUse(oldPVCSpec) {
|
if !dataSourceIsEnabled(pvcSpec) && !dataSourceInUse(oldPVCSpec) {
|
||||||
pvcSpec.DataSource = nil
|
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 {
|
func dataSourceInUse(oldPVCSpec *core.PersistentVolumeClaimSpec) bool {
|
||||||
if oldPVCSpec == nil {
|
if oldPVCSpec == nil {
|
||||||
return false
|
return false
|
||||||
|
@ -28,96 +28,6 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/features"
|
"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) {
|
func TestDropDisabledSnapshotDataSource(t *testing.T) {
|
||||||
pvcWithoutDataSource := func() *core.PersistentVolumeClaim {
|
pvcWithoutDataSource := func() *core.PersistentVolumeClaim {
|
||||||
return &core.PersistentVolumeClaim{
|
return &core.PersistentVolumeClaim{
|
||||||
|
@ -385,8 +385,6 @@ func dropDisabledFields(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
dropDisabledVolumeDevicesFields(podSpec, oldPodSpec)
|
|
||||||
|
|
||||||
dropDisabledRunAsGroupField(podSpec, oldPodSpec)
|
dropDisabledRunAsGroupField(podSpec, oldPodSpec)
|
||||||
|
|
||||||
dropDisabledGMSAFields(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.
|
// dropDisabledCSIVolumeSourceAlphaFields removes disabled alpha fields from []CSIVolumeSource.
|
||||||
// This should be called from PrepareForCreate/PrepareForUpdate for all pod specs resources containing a CSIVolumeSource
|
// This should be called from PrepareForCreate/PrepareForUpdate for all pod specs resources containing a CSIVolumeSource
|
||||||
func dropDisabledCSIVolumeSourceAlphaFields(podSpec, oldPodSpec *api.PodSpec) {
|
func dropDisabledCSIVolumeSourceAlphaFields(podSpec, oldPodSpec *api.PodSpec) {
|
||||||
@ -646,24 +633,6 @@ func emptyDirSizeLimitInUse(podSpec *api.PodSpec) bool {
|
|||||||
return false
|
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
|
// runAsGroupInUse returns true if the pod spec is non-nil and has a SecurityContext's RunAsGroup field set
|
||||||
func runAsGroupInUse(podSpec *api.PodSpec) bool {
|
func runAsGroupInUse(podSpec *api.PodSpec) bool {
|
||||||
if podSpec == nil {
|
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) {
|
func TestDropSubPath(t *testing.T) {
|
||||||
podWithSubpaths := func() *api.Pod {
|
podWithSubpaths := func() *api.Pod {
|
||||||
return &api.Pod{
|
return &api.Pod{
|
||||||
|
@ -302,7 +302,6 @@ type PersistentVolumeSpec struct {
|
|||||||
MountOptions []string
|
MountOptions []string
|
||||||
// volumeMode defines if a volume is intended to be used with a formatted filesystem
|
// 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.
|
// or to remain in raw block state. Value of Filesystem is implied when not included in spec.
|
||||||
// This is a beta feature.
|
|
||||||
// +optional
|
// +optional
|
||||||
VolumeMode *PersistentVolumeMode
|
VolumeMode *PersistentVolumeMode
|
||||||
// NodeAffinity defines constraints that limit what nodes this volume can be accessed from.
|
// NodeAffinity defines constraints that limit what nodes this volume can be accessed from.
|
||||||
@ -416,7 +415,6 @@ type PersistentVolumeClaimSpec struct {
|
|||||||
StorageClassName *string
|
StorageClassName *string
|
||||||
// volumeMode defines what type of volume is required by the claim.
|
// volumeMode defines what type of volume is required by the claim.
|
||||||
// Value of Filesystem is implied when not included in claim spec.
|
// Value of Filesystem is implied when not included in claim spec.
|
||||||
// This is a beta feature.
|
|
||||||
// +optional
|
// +optional
|
||||||
VolumeMode *PersistentVolumeMode
|
VolumeMode *PersistentVolumeMode
|
||||||
// This field can be used to specify either:
|
// This field can be used to specify either:
|
||||||
@ -2057,7 +2055,6 @@ type Container struct {
|
|||||||
// +optional
|
// +optional
|
||||||
VolumeMounts []VolumeMount
|
VolumeMounts []VolumeMount
|
||||||
// volumeDevices is the list of block devices to be used by the container.
|
// volumeDevices is the list of block devices to be used by the container.
|
||||||
// This is a beta feature.
|
|
||||||
// +optional
|
// +optional
|
||||||
VolumeDevices []VolumeDevice
|
VolumeDevices []VolumeDevice
|
||||||
// +optional
|
// +optional
|
||||||
@ -2969,7 +2966,6 @@ type EphemeralContainerCommon struct {
|
|||||||
// +optional
|
// +optional
|
||||||
VolumeMounts []VolumeMount
|
VolumeMounts []VolumeMount
|
||||||
// volumeDevices is the list of block devices to be used by the container.
|
// volumeDevices is the list of block devices to be used by the container.
|
||||||
// This is a beta feature.
|
|
||||||
// +optional
|
// +optional
|
||||||
VolumeDevices []VolumeDevice
|
VolumeDevices []VolumeDevice
|
||||||
// Probes are not allowed for ephemeral containers.
|
// Probes are not allowed for ephemeral containers.
|
||||||
|
@ -1475,204 +1475,168 @@ func TestValidatePersistentVolumeClaimUpdate(t *testing.T) {
|
|||||||
oldClaim *core.PersistentVolumeClaim
|
oldClaim *core.PersistentVolumeClaim
|
||||||
newClaim *core.PersistentVolumeClaim
|
newClaim *core.PersistentVolumeClaim
|
||||||
enableResize bool
|
enableResize bool
|
||||||
enableBlock bool
|
|
||||||
}{
|
}{
|
||||||
"valid-update-volumeName-only": {
|
"valid-update-volumeName-only": {
|
||||||
isExpectedFailure: false,
|
isExpectedFailure: false,
|
||||||
oldClaim: validClaim,
|
oldClaim: validClaim,
|
||||||
newClaim: validUpdateClaim,
|
newClaim: validUpdateClaim,
|
||||||
enableResize: false,
|
enableResize: false,
|
||||||
enableBlock: false,
|
|
||||||
},
|
},
|
||||||
"valid-no-op-update": {
|
"valid-no-op-update": {
|
||||||
isExpectedFailure: false,
|
isExpectedFailure: false,
|
||||||
oldClaim: validUpdateClaim,
|
oldClaim: validUpdateClaim,
|
||||||
newClaim: validUpdateClaim,
|
newClaim: validUpdateClaim,
|
||||||
enableResize: false,
|
enableResize: false,
|
||||||
enableBlock: false,
|
|
||||||
},
|
},
|
||||||
"invalid-update-change-resources-on-bound-claim": {
|
"invalid-update-change-resources-on-bound-claim": {
|
||||||
isExpectedFailure: true,
|
isExpectedFailure: true,
|
||||||
oldClaim: validUpdateClaim,
|
oldClaim: validUpdateClaim,
|
||||||
newClaim: invalidUpdateClaimResources,
|
newClaim: invalidUpdateClaimResources,
|
||||||
enableResize: false,
|
enableResize: false,
|
||||||
enableBlock: false,
|
|
||||||
},
|
},
|
||||||
"invalid-update-change-access-modes-on-bound-claim": {
|
"invalid-update-change-access-modes-on-bound-claim": {
|
||||||
isExpectedFailure: true,
|
isExpectedFailure: true,
|
||||||
oldClaim: validUpdateClaim,
|
oldClaim: validUpdateClaim,
|
||||||
newClaim: invalidUpdateClaimAccessModes,
|
newClaim: invalidUpdateClaimAccessModes,
|
||||||
enableResize: false,
|
enableResize: false,
|
||||||
enableBlock: false,
|
|
||||||
},
|
},
|
||||||
"valid-update-volume-mode-block-to-block": {
|
"valid-update-volume-mode-block-to-block": {
|
||||||
isExpectedFailure: false,
|
isExpectedFailure: false,
|
||||||
oldClaim: validClaimVolumeModeBlock,
|
oldClaim: validClaimVolumeModeBlock,
|
||||||
newClaim: validClaimVolumeModeBlock,
|
newClaim: validClaimVolumeModeBlock,
|
||||||
enableResize: false,
|
enableResize: false,
|
||||||
enableBlock: true,
|
|
||||||
},
|
},
|
||||||
"valid-update-volume-mode-file-to-file": {
|
"valid-update-volume-mode-file-to-file": {
|
||||||
isExpectedFailure: false,
|
isExpectedFailure: false,
|
||||||
oldClaim: validClaimVolumeModeFile,
|
oldClaim: validClaimVolumeModeFile,
|
||||||
newClaim: validClaimVolumeModeFile,
|
newClaim: validClaimVolumeModeFile,
|
||||||
enableResize: false,
|
enableResize: false,
|
||||||
enableBlock: true,
|
|
||||||
},
|
},
|
||||||
"invalid-update-volume-mode-to-block": {
|
"invalid-update-volume-mode-to-block": {
|
||||||
isExpectedFailure: true,
|
isExpectedFailure: true,
|
||||||
oldClaim: validClaimVolumeModeFile,
|
oldClaim: validClaimVolumeModeFile,
|
||||||
newClaim: validClaimVolumeModeBlock,
|
newClaim: validClaimVolumeModeBlock,
|
||||||
enableResize: false,
|
enableResize: false,
|
||||||
enableBlock: true,
|
|
||||||
},
|
},
|
||||||
"invalid-update-volume-mode-to-file": {
|
"invalid-update-volume-mode-to-file": {
|
||||||
isExpectedFailure: true,
|
isExpectedFailure: true,
|
||||||
oldClaim: validClaimVolumeModeBlock,
|
oldClaim: validClaimVolumeModeBlock,
|
||||||
newClaim: validClaimVolumeModeFile,
|
newClaim: validClaimVolumeModeFile,
|
||||||
enableResize: false,
|
enableResize: false,
|
||||||
enableBlock: true,
|
|
||||||
},
|
},
|
||||||
"invalid-update-volume-mode-nil-to-file": {
|
"invalid-update-volume-mode-nil-to-file": {
|
||||||
isExpectedFailure: true,
|
isExpectedFailure: true,
|
||||||
oldClaim: invalidClaimVolumeModeNil,
|
oldClaim: invalidClaimVolumeModeNil,
|
||||||
newClaim: validClaimVolumeModeFile,
|
newClaim: validClaimVolumeModeFile,
|
||||||
enableResize: false,
|
enableResize: false,
|
||||||
enableBlock: true,
|
|
||||||
},
|
},
|
||||||
"invalid-update-volume-mode-nil-to-block": {
|
"invalid-update-volume-mode-nil-to-block": {
|
||||||
isExpectedFailure: true,
|
isExpectedFailure: true,
|
||||||
oldClaim: invalidClaimVolumeModeNil,
|
oldClaim: invalidClaimVolumeModeNil,
|
||||||
newClaim: validClaimVolumeModeBlock,
|
newClaim: validClaimVolumeModeBlock,
|
||||||
enableResize: false,
|
enableResize: false,
|
||||||
enableBlock: true,
|
|
||||||
},
|
},
|
||||||
"invalid-update-volume-mode-block-to-nil": {
|
"invalid-update-volume-mode-block-to-nil": {
|
||||||
isExpectedFailure: true,
|
isExpectedFailure: true,
|
||||||
oldClaim: validClaimVolumeModeBlock,
|
oldClaim: validClaimVolumeModeBlock,
|
||||||
newClaim: invalidClaimVolumeModeNil,
|
newClaim: invalidClaimVolumeModeNil,
|
||||||
enableResize: false,
|
enableResize: false,
|
||||||
enableBlock: true,
|
|
||||||
},
|
},
|
||||||
"invalid-update-volume-mode-file-to-nil": {
|
"invalid-update-volume-mode-file-to-nil": {
|
||||||
isExpectedFailure: true,
|
isExpectedFailure: true,
|
||||||
oldClaim: validClaimVolumeModeFile,
|
oldClaim: validClaimVolumeModeFile,
|
||||||
newClaim: invalidClaimVolumeModeNil,
|
newClaim: invalidClaimVolumeModeNil,
|
||||||
enableResize: false,
|
enableResize: false,
|
||||||
enableBlock: true,
|
|
||||||
},
|
},
|
||||||
"invalid-update-volume-mode-empty-to-mode": {
|
"invalid-update-volume-mode-empty-to-mode": {
|
||||||
isExpectedFailure: true,
|
isExpectedFailure: true,
|
||||||
oldClaim: validClaim,
|
oldClaim: validClaim,
|
||||||
newClaim: validClaimVolumeModeBlock,
|
newClaim: validClaimVolumeModeBlock,
|
||||||
enableResize: false,
|
enableResize: false,
|
||||||
enableBlock: true,
|
|
||||||
},
|
},
|
||||||
"invalid-update-volume-mode-mode-to-empty": {
|
"invalid-update-volume-mode-mode-to-empty": {
|
||||||
isExpectedFailure: true,
|
isExpectedFailure: true,
|
||||||
oldClaim: validClaimVolumeModeBlock,
|
oldClaim: validClaimVolumeModeBlock,
|
||||||
newClaim: validClaim,
|
newClaim: validClaim,
|
||||||
enableResize: false,
|
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": {
|
"invalid-update-change-storage-class-annotation-after-creation": {
|
||||||
isExpectedFailure: true,
|
isExpectedFailure: true,
|
||||||
oldClaim: validClaimStorageClass,
|
oldClaim: validClaimStorageClass,
|
||||||
newClaim: invalidUpdateClaimStorageClass,
|
newClaim: invalidUpdateClaimStorageClass,
|
||||||
enableResize: false,
|
enableResize: false,
|
||||||
enableBlock: false,
|
|
||||||
},
|
},
|
||||||
"valid-update-mutable-annotation": {
|
"valid-update-mutable-annotation": {
|
||||||
isExpectedFailure: false,
|
isExpectedFailure: false,
|
||||||
oldClaim: validClaimAnnotation,
|
oldClaim: validClaimAnnotation,
|
||||||
newClaim: validUpdateClaimMutableAnnotation,
|
newClaim: validUpdateClaimMutableAnnotation,
|
||||||
enableResize: false,
|
enableResize: false,
|
||||||
enableBlock: false,
|
|
||||||
},
|
},
|
||||||
"valid-update-add-annotation": {
|
"valid-update-add-annotation": {
|
||||||
isExpectedFailure: false,
|
isExpectedFailure: false,
|
||||||
oldClaim: validClaim,
|
oldClaim: validClaim,
|
||||||
newClaim: validAddClaimAnnotation,
|
newClaim: validAddClaimAnnotation,
|
||||||
enableResize: false,
|
enableResize: false,
|
||||||
enableBlock: false,
|
|
||||||
},
|
},
|
||||||
"valid-size-update-resize-disabled": {
|
"valid-size-update-resize-disabled": {
|
||||||
isExpectedFailure: true,
|
isExpectedFailure: true,
|
||||||
oldClaim: validClaim,
|
oldClaim: validClaim,
|
||||||
newClaim: validSizeUpdate,
|
newClaim: validSizeUpdate,
|
||||||
enableResize: false,
|
enableResize: false,
|
||||||
enableBlock: false,
|
|
||||||
},
|
},
|
||||||
"valid-size-update-resize-enabled": {
|
"valid-size-update-resize-enabled": {
|
||||||
isExpectedFailure: false,
|
isExpectedFailure: false,
|
||||||
oldClaim: validClaim,
|
oldClaim: validClaim,
|
||||||
newClaim: validSizeUpdate,
|
newClaim: validSizeUpdate,
|
||||||
enableResize: true,
|
enableResize: true,
|
||||||
enableBlock: false,
|
|
||||||
},
|
},
|
||||||
"invalid-size-update-resize-enabled": {
|
"invalid-size-update-resize-enabled": {
|
||||||
isExpectedFailure: true,
|
isExpectedFailure: true,
|
||||||
oldClaim: validClaim,
|
oldClaim: validClaim,
|
||||||
newClaim: invalidSizeUpdate,
|
newClaim: invalidSizeUpdate,
|
||||||
enableResize: true,
|
enableResize: true,
|
||||||
enableBlock: false,
|
|
||||||
},
|
},
|
||||||
"unbound-size-update-resize-enabled": {
|
"unbound-size-update-resize-enabled": {
|
||||||
isExpectedFailure: true,
|
isExpectedFailure: true,
|
||||||
oldClaim: validClaim,
|
oldClaim: validClaim,
|
||||||
newClaim: unboundSizeUpdate,
|
newClaim: unboundSizeUpdate,
|
||||||
enableResize: true,
|
enableResize: true,
|
||||||
enableBlock: false,
|
|
||||||
},
|
},
|
||||||
"valid-upgrade-storage-class-annotation-to-spec": {
|
"valid-upgrade-storage-class-annotation-to-spec": {
|
||||||
isExpectedFailure: false,
|
isExpectedFailure: false,
|
||||||
oldClaim: validClaimStorageClass,
|
oldClaim: validClaimStorageClass,
|
||||||
newClaim: validClaimStorageClassInSpec,
|
newClaim: validClaimStorageClassInSpec,
|
||||||
enableResize: false,
|
enableResize: false,
|
||||||
enableBlock: false,
|
|
||||||
},
|
},
|
||||||
"invalid-upgrade-storage-class-annotation-to-spec": {
|
"invalid-upgrade-storage-class-annotation-to-spec": {
|
||||||
isExpectedFailure: true,
|
isExpectedFailure: true,
|
||||||
oldClaim: validClaimStorageClass,
|
oldClaim: validClaimStorageClass,
|
||||||
newClaim: invalidClaimStorageClassInSpec,
|
newClaim: invalidClaimStorageClassInSpec,
|
||||||
enableResize: false,
|
enableResize: false,
|
||||||
enableBlock: false,
|
|
||||||
},
|
},
|
||||||
"valid-upgrade-storage-class-annotation-to-annotation-and-spec": {
|
"valid-upgrade-storage-class-annotation-to-annotation-and-spec": {
|
||||||
isExpectedFailure: false,
|
isExpectedFailure: false,
|
||||||
oldClaim: validClaimStorageClass,
|
oldClaim: validClaimStorageClass,
|
||||||
newClaim: validClaimStorageClassInAnnotationAndSpec,
|
newClaim: validClaimStorageClassInAnnotationAndSpec,
|
||||||
enableResize: false,
|
enableResize: false,
|
||||||
enableBlock: false,
|
|
||||||
},
|
},
|
||||||
"invalid-upgrade-storage-class-annotation-to-annotation-and-spec": {
|
"invalid-upgrade-storage-class-annotation-to-annotation-and-spec": {
|
||||||
isExpectedFailure: true,
|
isExpectedFailure: true,
|
||||||
oldClaim: validClaimStorageClass,
|
oldClaim: validClaimStorageClass,
|
||||||
newClaim: invalidClaimStorageClassInAnnotationAndSpec,
|
newClaim: invalidClaimStorageClassInAnnotationAndSpec,
|
||||||
enableResize: false,
|
enableResize: false,
|
||||||
enableBlock: false,
|
|
||||||
},
|
},
|
||||||
"invalid-upgrade-storage-class-in-spec": {
|
"invalid-upgrade-storage-class-in-spec": {
|
||||||
isExpectedFailure: true,
|
isExpectedFailure: true,
|
||||||
oldClaim: validClaimStorageClassInSpec,
|
oldClaim: validClaimStorageClassInSpec,
|
||||||
newClaim: invalidClaimStorageClassInSpec,
|
newClaim: invalidClaimStorageClassInSpec,
|
||||||
enableResize: false,
|
enableResize: false,
|
||||||
enableBlock: false,
|
|
||||||
},
|
},
|
||||||
"invalid-downgrade-storage-class-spec-to-annotation": {
|
"invalid-downgrade-storage-class-spec-to-annotation": {
|
||||||
isExpectedFailure: true,
|
isExpectedFailure: true,
|
||||||
oldClaim: validClaimStorageClassInSpec,
|
oldClaim: validClaimStorageClassInSpec,
|
||||||
newClaim: validClaimStorageClass,
|
newClaim: validClaimStorageClass,
|
||||||
enableResize: false,
|
enableResize: false,
|
||||||
enableBlock: false,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1680,7 +1644,6 @@ func TestValidatePersistentVolumeClaimUpdate(t *testing.T) {
|
|||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
// ensure we have a resource version specified for updates
|
// 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.ExpandPersistentVolumes, scenario.enableResize)()
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, scenario.enableBlock)()
|
|
||||||
scenario.oldClaim.ResourceVersion = "1"
|
scenario.oldClaim.ResourceVersion = "1"
|
||||||
scenario.newClaim.ResourceVersion = "1"
|
scenario.newClaim.ResourceVersion = "1"
|
||||||
errs := ValidatePersistentVolumeClaimUpdate(scenario.newClaim, scenario.oldClaim)
|
errs := ValidatePersistentVolumeClaimUpdate(scenario.newClaim, scenario.oldClaim)
|
||||||
@ -4092,9 +4055,6 @@ func TestHugePagesIsolation(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestPVCVolumeMode(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
|
block := core.PersistentVolumeBlock
|
||||||
file := core.PersistentVolumeFilesystem
|
file := core.PersistentVolumeFilesystem
|
||||||
fake := core.PersistentVolumeMode("fake")
|
fake := core.PersistentVolumeMode("fake")
|
||||||
@ -4125,9 +4085,6 @@ func TestPVCVolumeMode(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestPVVolumeMode(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
|
block := core.PersistentVolumeBlock
|
||||||
file := core.PersistentVolumeFilesystem
|
file := core.PersistentVolumeFilesystem
|
||||||
fake := core.PersistentVolumeMode("fake")
|
fake := core.PersistentVolumeMode("fake")
|
||||||
|
@ -22,10 +22,7 @@ import (
|
|||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
storage "k8s.io/api/storage/v1"
|
storage "k8s.io/api/storage/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/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"
|
pvutil "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/util"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Test single call to syncClaim and syncVolume methods.
|
// Test single call to syncClaim and syncVolume methods.
|
||||||
@ -611,68 +608,6 @@ func TestSync(t *testing.T) {
|
|||||||
}, []*v1.Pod{})
|
}, []*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) {
|
func TestSyncBlockVolume(t *testing.T) {
|
||||||
modeBlock := v1.PersistentVolumeBlock
|
modeBlock := v1.PersistentVolumeBlock
|
||||||
modeFile := v1.PersistentVolumeFilesystem
|
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{})
|
runSyncTests(t, tests, []*storage.StorageClass{}, []*v1.Pod{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1060,91 +1060,56 @@ func TestVolumeModeCheck(t *testing.T) {
|
|||||||
isExpectedMismatch bool
|
isExpectedMismatch bool
|
||||||
vol *v1.PersistentVolume
|
vol *v1.PersistentVolume
|
||||||
pvc *v1.PersistentVolumeClaim
|
pvc *v1.PersistentVolumeClaim
|
||||||
enableBlock bool
|
|
||||||
}{
|
}{
|
||||||
"feature enabled - pvc block and pv filesystem": {
|
"pvc block and pv filesystem": {
|
||||||
isExpectedMismatch: true,
|
isExpectedMismatch: true,
|
||||||
vol: createVolumeModeFilesystemTestVolume(),
|
vol: createVolumeModeFilesystemTestVolume(),
|
||||||
pvc: makeVolumeModePVC("8G", &blockMode, nil),
|
pvc: makeVolumeModePVC("8G", &blockMode, nil),
|
||||||
enableBlock: true,
|
|
||||||
},
|
},
|
||||||
"feature enabled - pvc filesystem and pv block": {
|
"pvc filesystem and pv block": {
|
||||||
isExpectedMismatch: true,
|
isExpectedMismatch: true,
|
||||||
vol: createVolumeModeBlockTestVolume(),
|
vol: createVolumeModeBlockTestVolume(),
|
||||||
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
||||||
enableBlock: true,
|
|
||||||
},
|
},
|
||||||
"feature enabled - pvc block and pv block": {
|
"pvc block and pv block": {
|
||||||
isExpectedMismatch: false,
|
isExpectedMismatch: false,
|
||||||
vol: createVolumeModeBlockTestVolume(),
|
vol: createVolumeModeBlockTestVolume(),
|
||||||
pvc: makeVolumeModePVC("8G", &blockMode, nil),
|
pvc: makeVolumeModePVC("8G", &blockMode, nil),
|
||||||
enableBlock: true,
|
|
||||||
},
|
},
|
||||||
"feature enabled - pvc filesystem and pv filesystem": {
|
"pvc filesystem and pv filesystem": {
|
||||||
isExpectedMismatch: false,
|
isExpectedMismatch: false,
|
||||||
vol: createVolumeModeFilesystemTestVolume(),
|
vol: createVolumeModeFilesystemTestVolume(),
|
||||||
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
||||||
enableBlock: true,
|
|
||||||
},
|
},
|
||||||
"feature enabled - pvc filesystem and pv nil": {
|
"pvc filesystem and pv nil": {
|
||||||
isExpectedMismatch: false,
|
isExpectedMismatch: false,
|
||||||
vol: createVolumeModeNilTestVolume(),
|
vol: createVolumeModeNilTestVolume(),
|
||||||
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
||||||
enableBlock: true,
|
|
||||||
},
|
},
|
||||||
"feature enabled - pvc nil and pv filesystem": {
|
"pvc nil and pv filesystem": {
|
||||||
isExpectedMismatch: false,
|
isExpectedMismatch: false,
|
||||||
vol: createVolumeModeFilesystemTestVolume(),
|
vol: createVolumeModeFilesystemTestVolume(),
|
||||||
pvc: makeVolumeModePVC("8G", nil, nil),
|
pvc: makeVolumeModePVC("8G", nil, nil),
|
||||||
enableBlock: true,
|
|
||||||
},
|
},
|
||||||
"feature enabled - pvc nil and pv nil": {
|
"pvc nil and pv nil": {
|
||||||
isExpectedMismatch: false,
|
isExpectedMismatch: false,
|
||||||
vol: createVolumeModeNilTestVolume(),
|
vol: createVolumeModeNilTestVolume(),
|
||||||
pvc: makeVolumeModePVC("8G", nil, nil),
|
pvc: makeVolumeModePVC("8G", nil, nil),
|
||||||
enableBlock: true,
|
|
||||||
},
|
},
|
||||||
"feature enabled - pvc nil and pv block": {
|
"pvc nil and pv block": {
|
||||||
isExpectedMismatch: true,
|
isExpectedMismatch: true,
|
||||||
vol: createVolumeModeBlockTestVolume(),
|
vol: createVolumeModeBlockTestVolume(),
|
||||||
pvc: makeVolumeModePVC("8G", nil, nil),
|
pvc: makeVolumeModePVC("8G", nil, nil),
|
||||||
enableBlock: true,
|
|
||||||
},
|
},
|
||||||
"feature enabled - pvc block and pv nil": {
|
"pvc block and pv nil": {
|
||||||
isExpectedMismatch: true,
|
isExpectedMismatch: true,
|
||||||
vol: createVolumeModeNilTestVolume(),
|
vol: createVolumeModeNilTestVolume(),
|
||||||
pvc: makeVolumeModePVC("8G", &blockMode, nil),
|
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 {
|
for name, scenario := range scenarios {
|
||||||
t.Run(name, func(t *testing.T) {
|
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)
|
expectedMismatch := pvutil.CheckVolumeModeMismatches(&scenario.pvc.Spec, &scenario.vol.Spec)
|
||||||
// expected to match but either got an error or no returned pvmatch
|
// expected to match but either got an error or no returned pvmatch
|
||||||
if expectedMismatch && !scenario.isExpectedMismatch {
|
if expectedMismatch && !scenario.isExpectedMismatch {
|
||||||
@ -1167,73 +1132,46 @@ func TestFilteringVolumeModes(t *testing.T) {
|
|||||||
isExpectedMatch bool
|
isExpectedMatch bool
|
||||||
vol persistentVolumeOrderedIndex
|
vol persistentVolumeOrderedIndex
|
||||||
pvc *v1.PersistentVolumeClaim
|
pvc *v1.PersistentVolumeClaim
|
||||||
enableBlock bool
|
|
||||||
}{
|
}{
|
||||||
"1-1 feature enabled - pvc block and pv filesystem": {
|
"pvc block and pv filesystem": {
|
||||||
isExpectedMatch: false,
|
isExpectedMatch: false,
|
||||||
vol: createTestVolOrderedIndex(createVolumeModeFilesystemTestVolume()),
|
vol: createTestVolOrderedIndex(createVolumeModeFilesystemTestVolume()),
|
||||||
pvc: makeVolumeModePVC("8G", &blockMode, nil),
|
pvc: makeVolumeModePVC("8G", &blockMode, nil),
|
||||||
enableBlock: true,
|
|
||||||
},
|
},
|
||||||
"1-2 feature enabled - pvc filesystem and pv block": {
|
"pvc filesystem and pv block": {
|
||||||
isExpectedMatch: false,
|
isExpectedMatch: false,
|
||||||
vol: createTestVolOrderedIndex(createVolumeModeBlockTestVolume()),
|
vol: createTestVolOrderedIndex(createVolumeModeBlockTestVolume()),
|
||||||
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
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,
|
isExpectedMatch: false,
|
||||||
vol: createTestVolOrderedIndex(createVolumeModeFilesystemTestVolume()),
|
vol: createTestVolOrderedIndex(createVolumeModeFilesystemTestVolume()),
|
||||||
pvc: makeVolumeModePVC("8G", &blockMode, nil),
|
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,
|
isExpectedMatch: false,
|
||||||
vol: createTestVolOrderedIndex(createVolumeModeBlockTestVolume()),
|
vol: createTestVolOrderedIndex(createVolumeModeBlockTestVolume()),
|
||||||
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
||||||
enableBlock: true,
|
|
||||||
},
|
},
|
||||||
"1-5 feature enabled - pvc block and pv block": {
|
"pvc block and pv block": {
|
||||||
isExpectedMatch: true,
|
isExpectedMatch: true,
|
||||||
vol: createTestVolOrderedIndex(createVolumeModeBlockTestVolume()),
|
vol: createTestVolOrderedIndex(createVolumeModeBlockTestVolume()),
|
||||||
pvc: makeVolumeModePVC("8G", &blockMode, nil),
|
pvc: makeVolumeModePVC("8G", &blockMode, nil),
|
||||||
enableBlock: true,
|
|
||||||
},
|
},
|
||||||
"1-6 feature enabled - pvc filesystem and pv filesystem": {
|
"pvc filesystem and pv filesystem": {
|
||||||
isExpectedMatch: true,
|
isExpectedMatch: true,
|
||||||
vol: createTestVolOrderedIndex(createVolumeModeFilesystemTestVolume()),
|
vol: createTestVolOrderedIndex(createVolumeModeFilesystemTestVolume()),
|
||||||
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
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,
|
isExpectedMatch: true,
|
||||||
vol: createTestVolOrderedIndex(createVolumeModeFilesystemTestVolume()),
|
vol: createTestVolOrderedIndex(createVolumeModeFilesystemTestVolume()),
|
||||||
pvc: makeVolumeModePVC("8G", &filesystemMode, nil),
|
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 {
|
for name, scenario := range scenarios {
|
||||||
t.Run(name, func(t *testing.T) {
|
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)
|
pvmatch, err := scenario.vol.findBestMatchForClaim(scenario.pvc, false)
|
||||||
// expected to match but either got an error or no returned pvmatch
|
// expected to match but either got an error or no returned pvmatch
|
||||||
if pvmatch == nil && scenario.isExpectedMatch {
|
if pvmatch == nil && scenario.isExpectedMatch {
|
||||||
|
@ -30,11 +30,9 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apimachinery/pkg/util/diff"
|
"k8s.io/apimachinery/pkg/util/diff"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
core "k8s.io/client-go/testing"
|
core "k8s.io/client-go/testing"
|
||||||
"k8s.io/klog"
|
"k8s.io/klog"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrVersionConflict is the error returned when resource version of requested
|
// 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
|
// 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 = new(v1.PersistentVolumeMode)
|
||||||
*volume.Spec.VolumeMode = v1.PersistentVolumeFilesystem
|
*volume.Spec.VolumeMode = v1.PersistentVolumeFilesystem
|
||||||
}
|
}
|
||||||
|
@ -307,23 +307,6 @@ func FindMatchingVolume(
|
|||||||
// CheckVolumeModeMismatches is a convenience method that checks volumeMode for PersistentVolume
|
// CheckVolumeModeMismatches is a convenience method that checks volumeMode for PersistentVolume
|
||||||
// and PersistentVolumeClaims
|
// and PersistentVolumeClaims
|
||||||
func CheckVolumeModeMismatches(pvcSpec *v1.PersistentVolumeClaimSpec, pvSpec *v1.PersistentVolumeSpec) bool {
|
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.
|
// In HA upgrades, we cannot guarantee that the apiserver is on a version >= controller-manager.
|
||||||
// So we default a nil volumeMode to filesystem
|
// So we default a nil volumeMode to filesystem
|
||||||
requestedVolumeMode := v1.PersistentVolumeFilesystem
|
requestedVolumeMode := v1.PersistentVolumeFilesystem
|
||||||
|
@ -184,6 +184,7 @@ const (
|
|||||||
// owner: @screeley44
|
// owner: @screeley44
|
||||||
// alpha: v1.9
|
// alpha: v1.9
|
||||||
// beta: v1.13
|
// beta: v1.13
|
||||||
|
// ga: v1.18
|
||||||
//
|
//
|
||||||
// Enable Block volume support in containers.
|
// Enable Block volume support in containers.
|
||||||
BlockVolume featuregate.Feature = "BlockVolume"
|
BlockVolume featuregate.Feature = "BlockVolume"
|
||||||
@ -296,6 +297,7 @@ const (
|
|||||||
// owner: @vladimirvivien
|
// owner: @vladimirvivien
|
||||||
// alpha: v1.11
|
// alpha: v1.11
|
||||||
// beta: v1.14
|
// beta: v1.14
|
||||||
|
// ga: v1.18
|
||||||
//
|
//
|
||||||
// Enables CSI to use raw block storage volumes
|
// Enables CSI to use raw block storage volumes
|
||||||
CSIBlockVolume featuregate.Feature = "CSIBlockVolume"
|
CSIBlockVolume featuregate.Feature = "CSIBlockVolume"
|
||||||
@ -587,7 +589,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
|
|||||||
NodeDisruptionExclusion: {Default: false, PreRelease: featuregate.Alpha},
|
NodeDisruptionExclusion: {Default: false, PreRelease: featuregate.Alpha},
|
||||||
CSIDriverRegistry: {Default: true, PreRelease: featuregate.Beta},
|
CSIDriverRegistry: {Default: true, PreRelease: featuregate.Beta},
|
||||||
CSINodeInfo: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.19
|
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},
|
StorageObjectInUseProtection: {Default: true, PreRelease: featuregate.GA},
|
||||||
ResourceLimitsPriorityFunction: {Default: false, PreRelease: featuregate.Alpha},
|
ResourceLimitsPriorityFunction: {Default: false, PreRelease: featuregate.Alpha},
|
||||||
SupportIPVSProxyMode: {Default: true, PreRelease: featuregate.GA},
|
SupportIPVSProxyMode: {Default: true, PreRelease: featuregate.GA},
|
||||||
@ -614,7 +616,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
|
|||||||
VolumeSubpath: {Default: true, PreRelease: featuregate.GA},
|
VolumeSubpath: {Default: true, PreRelease: featuregate.GA},
|
||||||
BalanceAttachedNodeVolumes: {Default: false, PreRelease: featuregate.Alpha},
|
BalanceAttachedNodeVolumes: {Default: false, PreRelease: featuregate.Alpha},
|
||||||
VolumeSubpathEnvExpansion: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.19,
|
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},
|
CSIInlineVolume: {Default: true, PreRelease: featuregate.Beta},
|
||||||
RuntimeClass: {Default: true, PreRelease: featuregate.Beta},
|
RuntimeClass: {Default: true, PreRelease: featuregate.Beta},
|
||||||
NodeLease: {Default: true, PreRelease: featuregate.GA, LockToDefault: true},
|
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)
|
opts.PortMappings = kubecontainer.MakePortMappings(container)
|
||||||
|
|
||||||
// TODO: remove feature gate check after no longer needed
|
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
|
||||||
blkutil := volumepathhandler.NewBlockVolumePathHandler()
|
blkutil := volumepathhandler.NewBlockVolumePathHandler()
|
||||||
blkVolumes, err := kl.makeBlockVolumes(pod, container, volumes, blkutil)
|
blkVolumes, err := kl.makeBlockVolumes(pod, container, volumes, blkutil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
opts.Devices = append(opts.Devices, blkVolumes...)
|
opts.Devices = append(opts.Devices, blkVolumes...)
|
||||||
}
|
|
||||||
|
|
||||||
envs, err := kl.makeEnvironmentVariables(pod, container, podIP, podIPs)
|
envs, err := kl.makeEnvironmentVariables(pod, container, podIP, podIPs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -541,7 +541,6 @@ func (dswp *desiredStateOfWorldPopulator) createVolumeSpec(
|
|||||||
podVolume.Name,
|
podVolume.Name,
|
||||||
volumeMode)
|
volumeMode)
|
||||||
}
|
}
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
|
||||||
// Error if a container has volumeDevices but the volumeMode of PVC isn't Block
|
// Error if a container has volumeDevices but the volumeMode of PVC isn't Block
|
||||||
if devices.Has(podVolume.Name) && volumeMode != v1.PersistentVolumeBlock {
|
if devices.Has(podVolume.Name) && volumeMode != v1.PersistentVolumeBlock {
|
||||||
return nil, nil, "", fmt.Errorf(
|
return nil, nil, "", fmt.Errorf(
|
||||||
@ -549,7 +548,6 @@ func (dswp *desiredStateOfWorldPopulator) createVolumeSpec(
|
|||||||
podVolume.Name,
|
podVolume.Name,
|
||||||
volumeMode)
|
volumeMode)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return pvc, volumeSpec, volumeGidValue, nil
|
return pvc, volumeSpec, volumeGidValue, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -269,9 +269,6 @@ func TestFindAndRemoveDeletedPodsWithActualState(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestFindAndAddNewPods_FindAndRemoveDeletedPods_Valid_Block_VolumeDevices(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
|
// create dswp
|
||||||
mode := v1.PersistentVolumeBlock
|
mode := v1.PersistentVolumeBlock
|
||||||
pv := &v1.PersistentVolume{
|
pv := &v1.PersistentVolume{
|
||||||
@ -471,9 +468,6 @@ func TestCreateVolumeSpec_Valid_Nil_VolumeMounts(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateVolumeSpec_Valid_Block_VolumeDevices(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
|
// create dswp
|
||||||
mode := v1.PersistentVolumeBlock
|
mode := v1.PersistentVolumeBlock
|
||||||
pv := &v1.PersistentVolume{
|
pv := &v1.PersistentVolume{
|
||||||
@ -520,9 +514,6 @@ func TestCreateVolumeSpec_Valid_Block_VolumeDevices(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateVolumeSpec_Invalid_File_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
|
// create dswp
|
||||||
mode := v1.PersistentVolumeFilesystem
|
mode := v1.PersistentVolumeFilesystem
|
||||||
pv := &v1.PersistentVolume{
|
pv := &v1.PersistentVolume{
|
||||||
@ -569,9 +560,6 @@ func TestCreateVolumeSpec_Invalid_File_VolumeDevices(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateVolumeSpec_Invalid_Block_VolumeMounts(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
|
// create dswp
|
||||||
mode := v1.PersistentVolumeBlock
|
mode := v1.PersistentVolumeBlock
|
||||||
pv := &v1.PersistentVolume{
|
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) {
|
func TestCheckVolumeFSResize(t *testing.T) {
|
||||||
setCapacity := func(pv *v1.PersistentVolume, pvc *v1.PersistentVolumeClaim, capacity int) {
|
setCapacity := func(pv *v1.PersistentVolume, pvc *v1.PersistentVolumeClaim, capacity int) {
|
||||||
pv.Spec.Capacity = volumeCapacity(capacity)
|
pv.Spec.Capacity = volumeCapacity(capacity)
|
||||||
|
@ -487,8 +487,7 @@ func (rc *reconciler) reconstructVolume(volume podVolume) (*reconstructedVolume,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
// TODO: remove feature gate check after no longer needed
|
if volume.volumeMode == v1.PersistentVolumeBlock && mapperPlugin == nil {
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) && 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)
|
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
|
// Path to the mount or block device to check
|
||||||
var checkPath string
|
var checkPath string
|
||||||
|
|
||||||
// TODO: remove feature gate check after no longer needed
|
if volume.volumeMode == v1.PersistentVolumeBlock {
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) && volume.volumeMode == v1.PersistentVolumeBlock {
|
|
||||||
var newMapperErr error
|
var newMapperErr error
|
||||||
volumeMapper, newMapperErr = mapperPlugin.NewBlockVolumeMapper(
|
volumeMapper, newMapperErr = mapperPlugin.NewBlockVolumeMapper(
|
||||||
volumeSpec,
|
volumeSpec,
|
||||||
@ -697,12 +695,10 @@ func getVolumesFromPodDir(podDir string) ([]podVolume, error) {
|
|||||||
volumesDirs := map[v1.PersistentVolumeMode]string{
|
volumesDirs := map[v1.PersistentVolumeMode]string{
|
||||||
v1.PersistentVolumeFilesystem: path.Join(podDir, config.DefaultKubeletVolumesDirName),
|
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
|
// Find block volume information
|
||||||
// ex. block volume: /pods/{podUid}/volumeDevices/{escapeQualifiedPluginName}/{volumeName}
|
// ex. block volume: /pods/{podUid}/volumeDevices/{escapeQualifiedPluginName}/{volumeName}
|
||||||
volumesDirs[v1.PersistentVolumeBlock] = path.Join(podDir, config.DefaultKubeletVolumeDevicesDirName)
|
volumesDirs[v1.PersistentVolumeBlock] = path.Join(podDir, config.DefaultKubeletVolumeDevicesDirName)
|
||||||
}
|
|
||||||
for volumeMode, volumesDir := range volumesDirs {
|
for volumeMode, volumesDir := range volumesDirs {
|
||||||
var volumesDirInfo []os.FileInfo
|
var volumesDirInfo []os.FileInfo
|
||||||
if volumesDirInfo, err = ioutil.ReadDir(volumesDir); err != nil {
|
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
|
// Verifies there are attach/get map paths/setupDevice calls and
|
||||||
// no detach/teardownDevice calls.
|
// no detach/teardownDevice calls.
|
||||||
func Test_Run_Positive_VolumeAttachAndMap(t *testing.T) {
|
func Test_Run_Positive_VolumeAttachAndMap(t *testing.T) {
|
||||||
// Enable BlockVolume feature gate
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
|
|
||||||
|
|
||||||
pod := &v1.Pod{
|
pod := &v1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "pod1",
|
Name: "pod1",
|
||||||
@ -543,9 +540,6 @@ func Test_Run_Positive_VolumeAttachAndMap(t *testing.T) {
|
|||||||
// and no teardownDevice call.
|
// and no teardownDevice call.
|
||||||
// Verifies there are no attach/detach calls.
|
// Verifies there are no attach/detach calls.
|
||||||
func Test_Run_Positive_BlockVolumeMapControllerAttachEnabled(t *testing.T) {
|
func Test_Run_Positive_BlockVolumeMapControllerAttachEnabled(t *testing.T) {
|
||||||
// Enable BlockVolume feature gate
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
|
|
||||||
|
|
||||||
pod := &v1.Pod{
|
pod := &v1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "pod1",
|
Name: "pod1",
|
||||||
@ -647,9 +641,6 @@ func Test_Run_Positive_BlockVolumeMapControllerAttachEnabled(t *testing.T) {
|
|||||||
// Deletes volume/pod from desired state of world.
|
// Deletes volume/pod from desired state of world.
|
||||||
// Verifies one detach/teardownDevice calls are issued.
|
// Verifies one detach/teardownDevice calls are issued.
|
||||||
func Test_Run_Positive_BlockVolumeAttachMapUnmapDetach(t *testing.T) {
|
func Test_Run_Positive_BlockVolumeAttachMapUnmapDetach(t *testing.T) {
|
||||||
// Enable BlockVolume feature gate
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
|
|
||||||
|
|
||||||
pod := &v1.Pod{
|
pod := &v1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "pod1",
|
Name: "pod1",
|
||||||
@ -758,9 +749,6 @@ func Test_Run_Positive_BlockVolumeAttachMapUnmapDetach(t *testing.T) {
|
|||||||
// Verifies one teardownDevice call is made.
|
// Verifies one teardownDevice call is made.
|
||||||
// Verifies there are no attach/detach calls made.
|
// Verifies there are no attach/detach calls made.
|
||||||
func Test_Run_Positive_VolumeUnmapControllerAttachEnabled(t *testing.T) {
|
func Test_Run_Positive_VolumeUnmapControllerAttachEnabled(t *testing.T) {
|
||||||
// Enable BlockVolume feature gate
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.BlockVolume, true)()
|
|
||||||
|
|
||||||
pod := &v1.Pod{
|
pod := &v1.Pod{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "pod1",
|
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 {
|
for name, tc := range testCases {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
volumePluginMgr := &volume.VolumePluginMgr{}
|
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 {
|
for name, tc := range testCases {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
volumePluginMgr := &volume.VolumePluginMgr{}
|
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 {
|
for name, tc := range testCases {
|
||||||
t.Run(name, func(t *testing.T) {
|
t.Run(name, func(t *testing.T) {
|
||||||
volumePluginMgr := &volume.VolumePluginMgr{}
|
volumePluginMgr := &volume.VolumePluginMgr{}
|
||||||
|
@ -30,13 +30,10 @@ import (
|
|||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/apimachinery/pkg/util/wait"
|
"k8s.io/apimachinery/pkg/util/wait"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/client-go/kubernetes/fake"
|
"k8s.io/client-go/kubernetes/fake"
|
||||||
"k8s.io/client-go/tools/record"
|
"k8s.io/client-go/tools/record"
|
||||||
utiltesting "k8s.io/client-go/util/testing"
|
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/config"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/configmap"
|
"k8s.io/kubernetes/pkg/kubelet/configmap"
|
||||||
containertest "k8s.io/kubernetes/pkg/kubelet/container/testing"
|
containertest "k8s.io/kubernetes/pkg/kubelet/container/testing"
|
||||||
@ -60,7 +57,6 @@ func TestGetMountedVolumesForPodAndGetVolumesInUse(t *testing.T) {
|
|||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
pvMode, podMode v1.PersistentVolumeMode
|
pvMode, podMode v1.PersistentVolumeMode
|
||||||
disableBlockFeature bool
|
|
||||||
expectMount bool
|
expectMount bool
|
||||||
expectError bool
|
expectError bool
|
||||||
}{
|
}{
|
||||||
@ -78,14 +74,6 @@ func TestGetMountedVolumesForPodAndGetVolumesInUse(t *testing.T) {
|
|||||||
expectMount: true,
|
expectMount: true,
|
||||||
expectError: false,
|
expectError: false,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "block volume with block feature off",
|
|
||||||
pvMode: v1.PersistentVolumeBlock,
|
|
||||||
podMode: v1.PersistentVolumeBlock,
|
|
||||||
disableBlockFeature: true,
|
|
||||||
expectMount: false,
|
|
||||||
expectError: false,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "mismatched volume",
|
name: "mismatched volume",
|
||||||
pvMode: v1.PersistentVolumeBlock,
|
pvMode: v1.PersistentVolumeBlock,
|
||||||
@ -97,10 +85,6 @@ func TestGetMountedVolumesForPodAndGetVolumesInUse(t *testing.T) {
|
|||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
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")
|
tmpDir, err := utiltesting.MkTmpdir("volumeManagerTest")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("can't make a temp dir: %v", err)
|
t.Fatalf("can't make a temp dir: %v", err)
|
||||||
|
@ -35,8 +35,6 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"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"
|
||||||
"k8s.io/kubernetes/pkg/volume/util"
|
"k8s.io/kubernetes/pkg/volume/util"
|
||||||
"k8s.io/legacy-cloud-providers/aws"
|
"k8s.io/legacy-cloud-providers/aws"
|
||||||
@ -501,14 +499,11 @@ func (c *awsElasticBlockStoreProvisioner) Provision(selectedNode *v1.Node, allow
|
|||||||
fstype = "ext4"
|
fstype = "ext4"
|
||||||
}
|
}
|
||||||
|
|
||||||
var volumeMode *v1.PersistentVolumeMode
|
volumeMode := c.options.PVC.Spec.VolumeMode
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
|
||||||
volumeMode = c.options.PVC.Spec.VolumeMode
|
|
||||||
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
|
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
|
||||||
// Block volumes should not have any FSType
|
// Block volumes should not have any FSType
|
||||||
fstype = ""
|
fstype = ""
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pv := &v1.PersistentVolume{
|
pv := &v1.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
@ -29,9 +29,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
|
||||||
volumehelpers "k8s.io/cloud-provider/volume/helpers"
|
volumehelpers "k8s.io/cloud-provider/volume/helpers"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
"k8s.io/kubernetes/pkg/volume/util"
|
"k8s.io/kubernetes/pkg/volume/util"
|
||||||
"k8s.io/legacy-cloud-providers/azure"
|
"k8s.io/legacy-cloud-providers/azure"
|
||||||
@ -286,14 +284,11 @@ func (p *azureDiskProvisioner) Provision(selectedNode *v1.Node, allowedTopologie
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var volumeMode *v1.PersistentVolumeMode
|
volumeMode := p.options.PVC.Spec.VolumeMode
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
|
||||||
volumeMode = p.options.PVC.Spec.VolumeMode
|
|
||||||
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
|
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
|
||||||
// Block volumes should not have any FSType
|
// Block volumes should not have any FSType
|
||||||
fsType = ""
|
fsType = ""
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pv := &v1.PersistentVolume{
|
pv := &v1.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
@ -34,9 +34,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
|
||||||
cloudprovider "k8s.io/cloud-provider"
|
cloudprovider "k8s.io/cloud-provider"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
"k8s.io/kubernetes/pkg/volume/util"
|
"k8s.io/kubernetes/pkg/volume/util"
|
||||||
"k8s.io/legacy-cloud-providers/openstack"
|
"k8s.io/legacy-cloud-providers/openstack"
|
||||||
@ -572,14 +570,11 @@ func (c *cinderVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopolo
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var volumeMode *v1.PersistentVolumeMode
|
volumeMode := c.options.PVC.Spec.VolumeMode
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
|
||||||
volumeMode = c.options.PVC.Spec.VolumeMode
|
|
||||||
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
|
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
|
||||||
// Block volumes should not have any FSType
|
// Block volumes should not have any FSType
|
||||||
fstype = ""
|
fstype = ""
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pv := &v1.PersistentVolume{
|
pv := &v1.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
@ -28,8 +28,6 @@ import (
|
|||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"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"
|
||||||
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
||||||
)
|
)
|
||||||
@ -209,12 +207,12 @@ func volumeSpecToMounter(spec *volume.Spec, host volume.VolumeHost) (*fcDiskMoun
|
|||||||
wwids: wwids,
|
wwids: wwids,
|
||||||
io: &osIOHandler{},
|
io: &osIOHandler{},
|
||||||
}
|
}
|
||||||
// TODO: remove feature gate check after no longer needed
|
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
|
||||||
volumeMode, err := volumeutil.GetVolumeMode(spec)
|
volumeMode, err := volumeutil.GetVolumeMode(spec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
klog.V(5).Infof("fc: volumeSpecToMounter volumeMode %s", volumeMode)
|
klog.V(5).Infof("fc: volumeSpecToMounter volumeMode %s", volumeMode)
|
||||||
return &fcDiskMounter{
|
return &fcDiskMounter{
|
||||||
fcDisk: fcDisk,
|
fcDisk: fcDisk,
|
||||||
@ -225,15 +223,6 @@ func volumeSpecToMounter(spec *volume.Spec, host volume.VolumeHost) (*fcDiskMoun
|
|||||||
deviceUtil: volumeutil.NewDeviceHandler(volumeutil.NewIOHandler()),
|
deviceUtil: volumeutil.NewDeviceHandler(volumeutil.NewIOHandler()),
|
||||||
mountOptions: volumeutil.MountOptionFromSpec(spec),
|
mountOptions: volumeutil.MountOptionFromSpec(spec),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
|
||||||
return &fcDiskMounter{
|
|
||||||
fcDisk: fcDisk,
|
|
||||||
fsType: fc.FSType,
|
|
||||||
readOnly: readOnly,
|
|
||||||
mounter: volumeutil.NewSafeFormatAndMountFromHost(fcPluginName, host),
|
|
||||||
deviceUtil: volumeutil.NewDeviceHandler(volumeutil.NewIOHandler()),
|
|
||||||
mountOptions: volumeutil.MountOptionFromSpec(spec),
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func volumeSpecToUnmounter(mounter mount.Interface) *fcDiskUnmounter {
|
func volumeSpecToUnmounter(mounter mount.Interface) *fcDiskUnmounter {
|
||||||
|
@ -31,8 +31,6 @@ import (
|
|||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"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"
|
||||||
"k8s.io/kubernetes/pkg/volume/util"
|
"k8s.io/kubernetes/pkg/volume/util"
|
||||||
"k8s.io/kubernetes/pkg/volume/util/volumepathhandler"
|
"k8s.io/kubernetes/pkg/volume/util/volumepathhandler"
|
||||||
@ -134,12 +132,12 @@ func (plugin *fcPlugin) newMounterInternal(spec *volume.Spec, podUID types.UID,
|
|||||||
io: &osIOHandler{},
|
io: &osIOHandler{},
|
||||||
plugin: plugin,
|
plugin: plugin,
|
||||||
}
|
}
|
||||||
// TODO: remove feature gate check after no longer needed
|
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
|
||||||
volumeMode, err := util.GetVolumeMode(spec)
|
volumeMode, err := util.GetVolumeMode(spec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
klog.V(5).Infof("fc: newMounterInternal volumeMode %s", volumeMode)
|
klog.V(5).Infof("fc: newMounterInternal volumeMode %s", volumeMode)
|
||||||
return &fcDiskMounter{
|
return &fcDiskMounter{
|
||||||
fcDisk: fcDisk,
|
fcDisk: fcDisk,
|
||||||
@ -150,16 +148,6 @@ func (plugin *fcPlugin) newMounterInternal(spec *volume.Spec, podUID types.UID,
|
|||||||
deviceUtil: util.NewDeviceHandler(util.NewIOHandler()),
|
deviceUtil: util.NewDeviceHandler(util.NewIOHandler()),
|
||||||
mountOptions: util.MountOptionFromSpec(spec),
|
mountOptions: util.MountOptionFromSpec(spec),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
|
||||||
return &fcDiskMounter{
|
|
||||||
fcDisk: fcDisk,
|
|
||||||
fsType: fc.FSType,
|
|
||||||
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) {
|
func (plugin *fcPlugin) NewBlockVolumeMapper(spec *volume.Spec, pod *v1.Pod, _ volume.VolumeOptions) (volume.BlockVolumeMapper, error) {
|
||||||
|
@ -28,8 +28,6 @@ import (
|
|||||||
"k8s.io/utils/mount"
|
"k8s.io/utils/mount"
|
||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
|
||||||
"k8s.io/kubernetes/pkg/features"
|
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
||||||
)
|
)
|
||||||
@ -243,15 +241,13 @@ func (util *fcUtil) AttachDisk(b fcDiskMounter) (string, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
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.
|
// If the volumeMode is 'Block', plugin don't have to format the volume.
|
||||||
// The globalPDPath will be created by operationexecutor. Just return devicePath here.
|
// The globalPDPath will be created by operationexecutor. Just return devicePath here.
|
||||||
klog.V(5).Infof("fc: AttachDisk volumeMode: %s, devicePath: %s", b.volumeMode, devicePath)
|
klog.V(5).Infof("fc: AttachDisk volumeMode: %s, devicePath: %s", b.volumeMode, devicePath)
|
||||||
if b.volumeMode == v1.PersistentVolumeBlock {
|
if b.volumeMode == v1.PersistentVolumeBlock {
|
||||||
return devicePath, nil
|
return devicePath, nil
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// mount it
|
// mount it
|
||||||
globalPDPath := util.MakeGlobalPDName(*b.fcDisk)
|
globalPDPath := util.MakeGlobalPDName(*b.fcDisk)
|
||||||
|
@ -34,9 +34,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
|
||||||
volumehelpers "k8s.io/cloud-provider/volume/helpers"
|
volumehelpers "k8s.io/cloud-provider/volume/helpers"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
"k8s.io/kubernetes/pkg/volume/util"
|
"k8s.io/kubernetes/pkg/volume/util"
|
||||||
gcecloud "k8s.io/legacy-cloud-providers/gce"
|
gcecloud "k8s.io/legacy-cloud-providers/gce"
|
||||||
@ -500,14 +498,11 @@ func (c *gcePersistentDiskProvisioner) Provision(selectedNode *v1.Node, allowedT
|
|||||||
fstype = "ext4"
|
fstype = "ext4"
|
||||||
}
|
}
|
||||||
|
|
||||||
var volumeMode *v1.PersistentVolumeMode
|
volumeMode := c.options.PVC.Spec.VolumeMode
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
|
||||||
volumeMode = c.options.PVC.Spec.VolumeMode
|
|
||||||
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
|
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
|
||||||
// Block volumes should not have any FSType
|
// Block volumes should not have any FSType
|
||||||
fstype = ""
|
fstype = ""
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pv := &v1.PersistentVolume{
|
pv := &v1.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
@ -27,8 +27,6 @@ import (
|
|||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"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"
|
||||||
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
||||||
)
|
)
|
||||||
@ -209,12 +207,12 @@ func volumeSpecToMounter(spec *volume.Spec, host volume.VolumeHost, targetLocks
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
exec := host.GetExec(iscsiPluginName)
|
exec := host.GetExec(iscsiPluginName)
|
||||||
// TODO: remove feature gate check after no longer needed
|
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
|
||||||
volumeMode, err := volumeutil.GetVolumeMode(spec)
|
volumeMode, err := volumeutil.GetVolumeMode(spec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
klog.V(5).Infof("iscsi: VolumeSpecToMounter volumeMode %s", volumeMode)
|
klog.V(5).Infof("iscsi: VolumeSpecToMounter volumeMode %s", volumeMode)
|
||||||
return &iscsiDiskMounter{
|
return &iscsiDiskMounter{
|
||||||
iscsiDisk: iscsiDisk,
|
iscsiDisk: iscsiDisk,
|
||||||
@ -225,15 +223,6 @@ func volumeSpecToMounter(spec *volume.Spec, host volume.VolumeHost, targetLocks
|
|||||||
exec: exec,
|
exec: exec,
|
||||||
deviceUtil: volumeutil.NewDeviceHandler(volumeutil.NewIOHandler()),
|
deviceUtil: volumeutil.NewDeviceHandler(volumeutil.NewIOHandler()),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
|
||||||
return &iscsiDiskMounter{
|
|
||||||
iscsiDisk: iscsiDisk,
|
|
||||||
fsType: fsType,
|
|
||||||
readOnly: readOnly,
|
|
||||||
mounter: &mount.SafeFormatAndMount{Interface: host.GetMounter(iscsiPluginName), Exec: exec},
|
|
||||||
exec: exec,
|
|
||||||
deviceUtil: volumeutil.NewDeviceHandler(volumeutil.NewIOHandler()),
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func volumeSpecToUnmounter(mounter mount.Interface, host volume.VolumeHost, plugin *iscsiPlugin) *iscsiDiskUnmounter {
|
func volumeSpecToUnmounter(mounter mount.Interface, host volume.VolumeHost, plugin *iscsiPlugin) *iscsiDiskUnmounter {
|
||||||
|
@ -34,8 +34,6 @@ import (
|
|||||||
"k8s.io/utils/mount"
|
"k8s.io/utils/mount"
|
||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
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/kubelet/config"
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
||||||
@ -469,8 +467,6 @@ func (util *ISCSIUtil) AttachDisk(b iscsiDiskMounter) (string, error) {
|
|||||||
// If the volumeMode is 'Block', plugin creates a dir and persists iscsi configurations.
|
// 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.
|
// Since volume type is block, plugin doesn't need to format/mount the volume.
|
||||||
func globalPDPathOperation(b iscsiDiskMounter) func(iscsiDiskMounter, string, *ISCSIUtil) (string, error) {
|
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)
|
klog.V(5).Infof("iscsi: AttachDisk volumeMode: %s", b.volumeMode)
|
||||||
if b.volumeMode == v1.PersistentVolumeBlock {
|
if b.volumeMode == v1.PersistentVolumeBlock {
|
||||||
// If the volumeMode is 'Block', plugin don't need to format the volume.
|
// If the volumeMode is 'Block', plugin don't need to format the volume.
|
||||||
@ -487,7 +483,7 @@ func globalPDPathOperation(b iscsiDiskMounter) func(iscsiDiskMounter, string, *I
|
|||||||
return devicePath, nil
|
return devicePath, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// If the volumeMode is 'Filesystem', plugin needs to format the volume
|
// If the volumeMode is 'Filesystem', plugin needs to format the volume
|
||||||
// and mount it to globalPDPath.
|
// and mount it to globalPDPath.
|
||||||
return func(b iscsiDiskMounter, devicePath string, util *ISCSIUtil) (string, error) {
|
return func(b iscsiDiskMounter, devicePath string, util *ISCSIUtil) (string, error) {
|
||||||
|
@ -35,9 +35,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
"k8s.io/apimachinery/pkg/util/uuid"
|
"k8s.io/apimachinery/pkg/util/uuid"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
"k8s.io/kubernetes/pkg/volume/util"
|
"k8s.io/kubernetes/pkg/volume/util"
|
||||||
volutil "k8s.io/kubernetes/pkg/volume/util"
|
volutil "k8s.io/kubernetes/pkg/volume/util"
|
||||||
@ -718,14 +716,11 @@ func (r *rbdVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopologie
|
|||||||
rbd.Keyring = keyring
|
rbd.Keyring = keyring
|
||||||
}
|
}
|
||||||
|
|
||||||
var volumeMode *v1.PersistentVolumeMode
|
volumeMode := r.options.PVC.Spec.VolumeMode
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
|
||||||
volumeMode = r.options.PVC.Spec.VolumeMode
|
|
||||||
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
|
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
|
||||||
// Block volumes should not have any FSType
|
// Block volumes should not have any FSType
|
||||||
fstype = ""
|
fstype = ""
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
rbd.RadosUser = r.Id
|
rbd.RadosUser = r.Id
|
||||||
rbd.FSType = fstype
|
rbd.FSType = fstype
|
||||||
|
@ -39,12 +39,10 @@ import (
|
|||||||
apiruntime "k8s.io/apimachinery/pkg/runtime"
|
apiruntime "k8s.io/apimachinery/pkg/runtime"
|
||||||
utypes "k8s.io/apimachinery/pkg/types"
|
utypes "k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
|
||||||
clientset "k8s.io/client-go/kubernetes"
|
clientset "k8s.io/client-go/kubernetes"
|
||||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||||
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
podutil "k8s.io/kubernetes/pkg/api/v1/pod"
|
||||||
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
"k8s.io/kubernetes/pkg/volume/util/types"
|
"k8s.io/kubernetes/pkg/volume/util/types"
|
||||||
"k8s.io/kubernetes/pkg/volume/util/volumepathhandler"
|
"k8s.io/kubernetes/pkg/volume/util/volumepathhandler"
|
||||||
@ -436,7 +434,6 @@ func GetPersistentVolumeClaimQualifiedName(claim *v1.PersistentVolumeClaim) stri
|
|||||||
// CheckVolumeModeFilesystem checks VolumeMode.
|
// CheckVolumeModeFilesystem checks VolumeMode.
|
||||||
// If the mode is Filesystem, return true otherwise return false.
|
// If the mode is Filesystem, return true otherwise return false.
|
||||||
func CheckVolumeModeFilesystem(volumeSpec *volume.Spec) (bool, error) {
|
func CheckVolumeModeFilesystem(volumeSpec *volume.Spec) (bool, error) {
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
|
||||||
volumeMode, err := GetVolumeMode(volumeSpec)
|
volumeMode, err := GetVolumeMode(volumeSpec)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return true, err
|
return true, err
|
||||||
@ -444,14 +441,13 @@ func CheckVolumeModeFilesystem(volumeSpec *volume.Spec) (bool, error) {
|
|||||||
if volumeMode == v1.PersistentVolumeBlock {
|
if volumeMode == v1.PersistentVolumeBlock {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckPersistentVolumeClaimModeBlock checks VolumeMode.
|
// CheckPersistentVolumeClaimModeBlock checks VolumeMode.
|
||||||
// If the mode is Block, return true otherwise return false.
|
// If the mode is Block, return true otherwise return false.
|
||||||
func CheckPersistentVolumeClaimModeBlock(pvc *v1.PersistentVolumeClaim) bool {
|
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 \\
|
// 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)
|
mounts.Insert(mount.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: remove feature gate check after no longer needed
|
if container.VolumeDevices != nil {
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) &&
|
|
||||||
container.VolumeDevices != nil {
|
|
||||||
for _, device := range container.VolumeDevices {
|
for _, device := range container.VolumeDevices {
|
||||||
devices.Insert(device.Name)
|
devices.Insert(device.Name)
|
||||||
}
|
}
|
||||||
|
@ -33,9 +33,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
|
||||||
volumehelpers "k8s.io/cloud-provider/volume/helpers"
|
volumehelpers "k8s.io/cloud-provider/volume/helpers"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
"k8s.io/kubernetes/pkg/volume/util"
|
"k8s.io/kubernetes/pkg/volume/util"
|
||||||
)
|
)
|
||||||
@ -382,14 +380,11 @@ func (v *vsphereVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopol
|
|||||||
volSpec.Fstype = "ext4"
|
volSpec.Fstype = "ext4"
|
||||||
}
|
}
|
||||||
|
|
||||||
var volumeMode *v1.PersistentVolumeMode
|
volumeMode := v.options.PVC.Spec.VolumeMode
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.BlockVolume) {
|
|
||||||
volumeMode = v.options.PVC.Spec.VolumeMode
|
|
||||||
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
|
if volumeMode != nil && *volumeMode == v1.PersistentVolumeBlock {
|
||||||
klog.V(5).Infof("vSphere block volume should not have any FSType")
|
klog.V(5).Infof("vSphere block volume should not have any FSType")
|
||||||
volSpec.Fstype = ""
|
volSpec.Fstype = ""
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
pv := &v1.PersistentVolume{
|
pv := &v1.PersistentVolume{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
@ -331,7 +331,6 @@ type PersistentVolumeSpec struct {
|
|||||||
MountOptions []string `json:"mountOptions,omitempty" protobuf:"bytes,7,opt,name=mountOptions"`
|
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
|
// 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.
|
// or to remain in raw block state. Value of Filesystem is implied when not included in spec.
|
||||||
// This is a beta feature.
|
|
||||||
// +optional
|
// +optional
|
||||||
VolumeMode *PersistentVolumeMode `json:"volumeMode,omitempty" protobuf:"bytes,8,opt,name=volumeMode,casttype=PersistentVolumeMode"`
|
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.
|
// 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"`
|
StorageClassName *string `json:"storageClassName,omitempty" protobuf:"bytes,5,opt,name=storageClassName"`
|
||||||
// volumeMode defines what type of volume is required by the claim.
|
// volumeMode defines what type of volume is required by the claim.
|
||||||
// Value of Filesystem is implied when not included in claim spec.
|
// Value of Filesystem is implied when not included in claim spec.
|
||||||
// This is a beta feature.
|
|
||||||
// +optional
|
// +optional
|
||||||
VolumeMode *PersistentVolumeMode `json:"volumeMode,omitempty" protobuf:"bytes,6,opt,name=volumeMode,casttype=PersistentVolumeMode"`
|
VolumeMode *PersistentVolumeMode `json:"volumeMode,omitempty" protobuf:"bytes,6,opt,name=volumeMode,casttype=PersistentVolumeMode"`
|
||||||
// This field requires the VolumeSnapshotDataSource alpha feature gate to be
|
// This field requires the VolumeSnapshotDataSource alpha feature gate to be
|
||||||
@ -2181,7 +2179,6 @@ type Container struct {
|
|||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
VolumeMounts []VolumeMount `json:"volumeMounts,omitempty" patchStrategy:"merge" patchMergeKey:"mountPath" protobuf:"bytes,9,rep,name=volumeMounts"`
|
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.
|
// volumeDevices is the list of block devices to be used by the container.
|
||||||
// This is a beta feature.
|
|
||||||
// +patchMergeKey=devicePath
|
// +patchMergeKey=devicePath
|
||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +optional
|
// +optional
|
||||||
@ -3298,7 +3295,6 @@ type EphemeralContainerCommon struct {
|
|||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
VolumeMounts []VolumeMount `json:"volumeMounts,omitempty" patchStrategy:"merge" patchMergeKey:"mountPath" protobuf:"bytes,9,rep,name=volumeMounts"`
|
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.
|
// volumeDevices is the list of block devices to be used by the container.
|
||||||
// This is a beta feature.
|
|
||||||
// +patchMergeKey=devicePath
|
// +patchMergeKey=devicePath
|
||||||
// +patchStrategy=merge
|
// +patchStrategy=merge
|
||||||
// +optional
|
// +optional
|
||||||
|
Loading…
Reference in New Issue
Block a user