Add CSIDriverSpec.SELinuxMount

The new field tells Kubernetes if the CSI driver supports mounting of
volumes with -o context=XYZ or not.
This commit is contained in:
Jan Safranek 2022-03-16 16:20:44 +01:00
parent 34dc6b2587
commit 3efeeef346
9 changed files with 206 additions and 12 deletions

View File

@ -390,6 +390,27 @@ type CSIDriverSpec struct {
//
// +optional
RequiresRepublish *bool
// SELinuxMount specifies if the CSI driver supports "-o context"
// mount option.
//
// When "true", the CSI driver must ensure that all volumes provided by this CSI
// driver can be mounted separately with different `-o context` options. This is
// typical for storage backends that provide volumes as filesystems on block
// devices or as independent shared volumes.
// Kubernetes will call NodeStage / NodePublish with "-o context=xyz" mount
// option when mounting a ReadWriteOncePod volume used in Pod that has
// explicitly set SELinux context. In the future, it may be expanded to other
// volume AccessModes. In any case, Kubernetes will ensure that the volume is
// mounted only with a single SELinux context.
//
// When "false", Kubernetes won't pass any special SELinux mount options to the driver.
// This is typical for volumes that represent subdirectories of a bigger shared filesystem.
//
// Default is "false".
//
// +optional
SELinuxMount *bool
}
// FSGroupPolicy specifies if a CSI Driver supports modifying

View File

@ -64,4 +64,8 @@ func SetDefaults_CSIDriver(obj *storagev1.CSIDriver) {
obj.Spec.RequiresRepublish = new(bool)
*(obj.Spec.RequiresRepublish) = false
}
if obj.Spec.SELinuxMount == nil && utilfeature.DefaultFeatureGate.Enabled(features.SELinuxMountReadWriteOncePod) {
obj.Spec.SELinuxMount = new(bool)
*(obj.Spec.SELinuxMount) = false
}
}

View File

@ -122,3 +122,30 @@ func TestSetDefaultCSIDriver(t *testing.T) {
})
}
}
func TestSetDefaultSELinuxMountReadWriteOncePodEnabled(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, true)()
driver := &storagev1.CSIDriver{}
// field should be defaulted
defaultSELinuxMount := false
output := roundTrip(t, runtime.Object(driver)).(*storagev1.CSIDriver)
outSELinuxMount := output.Spec.SELinuxMount
if outSELinuxMount == nil {
t.Errorf("Expected SELinuxMount to be defaulted to: %+v, got: nil", defaultSELinuxMount)
} else if *outSELinuxMount != defaultSELinuxMount {
t.Errorf("Expected SELinuxMount to be defaulted to: %+v, got: %+v", defaultSELinuxMount, outSELinuxMount)
}
}
func TestSetDefaultSELinuxMountReadWriteOncePodDisabled(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, false)()
driver := &storagev1.CSIDriver{}
// field should not be defaulted
output := roundTrip(t, runtime.Object(driver)).(*storagev1.CSIDriver)
outSELinuxMount := output.Spec.SELinuxMount
if outSELinuxMount != nil {
t.Errorf("Expected SELinuxMount to remain nil, got: %+v", outSELinuxMount)
}
}

View File

@ -64,4 +64,8 @@ func SetDefaults_CSIDriver(obj *storagev1beta1.CSIDriver) {
obj.Spec.RequiresRepublish = new(bool)
*(obj.Spec.RequiresRepublish) = false
}
if obj.Spec.SELinuxMount == nil && utilfeature.DefaultFeatureGate.Enabled(features.SELinuxMountReadWriteOncePod) {
obj.Spec.SELinuxMount = new(bool)
*(obj.Spec.SELinuxMount) = false
}
}

View File

@ -165,3 +165,30 @@ func TestSetDefaultCSIDriver(t *testing.T) {
})
}
}
func TestSetDefaultSELinuxMountReadWriteOncePodEnabled(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, true)()
driver := &storagev1beta1.CSIDriver{}
// field should be defaulted
defaultSELinuxMount := false
output := roundTrip(t, runtime.Object(driver)).(*storagev1beta1.CSIDriver)
outSELinuxMount := output.Spec.SELinuxMount
if outSELinuxMount == nil {
t.Errorf("Expected SELinuxMount to be defaulted to: %+v, got: nil", defaultSELinuxMount)
} else if *outSELinuxMount != defaultSELinuxMount {
t.Errorf("Expected SELinuxMount to be defaulted to: %+v, got: %+v", defaultSELinuxMount, outSELinuxMount)
}
}
func TestSetDefaultSELinuxMountReadWriteOncePodDisabled(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, false)()
driver := &storagev1beta1.CSIDriver{}
// field should not be defaulted
output := roundTrip(t, runtime.Object(driver)).(*storagev1beta1.CSIDriver)
outSELinuxMount := output.Spec.SELinuxMount
if outSELinuxMount != nil {
t.Errorf("Expected SELinuxMount remain nil, got: %+v", outSELinuxMount)
}
}

View File

@ -50,6 +50,9 @@ func (csiDriverStrategy) PrepareForCreate(ctx context.Context, obj runtime.Objec
if !utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
csiDriver.Spec.VolumeLifecycleModes = nil
}
if !utilfeature.DefaultFeatureGate.Enabled(features.SELinuxMountReadWriteOncePod) {
csiDriver.Spec.SELinuxMount = nil
}
}
func (csiDriverStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
@ -87,6 +90,11 @@ func (csiDriverStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.
if !apiequality.Semantic.DeepEqual(oldCSIDriver.Spec.TokenRequests, newCSIDriver.Spec.TokenRequests) || !apiequality.Semantic.DeepEqual(oldCSIDriver.Spec.RequiresRepublish, newCSIDriver.Spec.RequiresRepublish) {
newCSIDriver.Generation = oldCSIDriver.Generation + 1
}
if oldCSIDriver.Spec.SELinuxMount == nil &&
!utilfeature.DefaultFeatureGate.Enabled(features.SELinuxMountReadWriteOncePod) {
newCSIDriver.Spec.SELinuxMount = nil
}
}
func (csiDriverStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {

View File

@ -211,18 +211,36 @@ func TestCSIDriverPrepareForUpdate(t *testing.T) {
RequiresRepublish: &enabled,
},
}
driverWithSELinuxMountEnabled := &storage.CSIDriver{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
},
Spec: storage.CSIDriverSpec{
SELinuxMount: &enabled,
},
}
driverWithSELinuxMountDisabled := &storage.CSIDriver{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
},
Spec: storage.CSIDriverSpec{
SELinuxMount: &disabled,
},
}
resultPersistent := []storage.VolumeLifecycleMode{storage.VolumeLifecyclePersistent}
tests := []struct {
name string
old, update *storage.CSIDriver
csiInlineVolumeEnabled bool
wantCapacity *bool
wantModes []storage.VolumeLifecycleMode
wantTokenRequests []storage.TokenRequest
wantRequiresRepublish *bool
wantGeneration int64
name string
old, update *storage.CSIDriver
csiInlineVolumeEnabled bool
seLinuxMountReadWriteOncePodEnabled bool
wantCapacity *bool
wantModes []storage.VolumeLifecycleMode
wantTokenRequests []storage.TokenRequest
wantRequiresRepublish *bool
wantGeneration int64
wantSELinuxMount *bool
}{
{
name: "capacity feature enabled, before: none, update: enabled",
@ -237,20 +255,20 @@ func TestCSIDriverPrepareForUpdate(t *testing.T) {
wantCapacity: &disabled,
},
{
name: "inline feature enabled, before: none, update: persitent",
name: "inline feature enabled, before: none, update: persistent",
csiInlineVolumeEnabled: true,
old: driverWithNothing,
update: driverWithPersistent,
wantModes: resultPersistent,
},
{
name: "inline feature disabled, before: none, update: persitent",
name: "inline feature disabled, before: none, update: persistent",
old: driverWithNothing,
update: driverWithPersistent,
wantModes: nil,
},
{
name: "inline feature disabled, before: ephemeral, update: persitent",
name: "inline feature disabled, before: ephemeral, update: persistent",
old: driverWithEphemeral,
update: driverWithPersistent,
wantModes: resultPersistent,
@ -263,11 +281,54 @@ func TestCSIDriverPrepareForUpdate(t *testing.T) {
wantRequiresRepublish: &enabled,
wantGeneration: 1,
},
{
name: "SELinux mount support feature enabled, before: nil, update: on",
seLinuxMountReadWriteOncePodEnabled: true,
old: driverWithNothing,
update: driverWithSELinuxMountEnabled,
wantSELinuxMount: &enabled,
},
{
name: "SELinux mount support feature enabled, before: off, update: on",
seLinuxMountReadWriteOncePodEnabled: true,
old: driverWithSELinuxMountDisabled,
update: driverWithSELinuxMountEnabled,
wantSELinuxMount: &enabled,
},
{
name: "SELinux mount support feature enabled, before: on, update: off",
seLinuxMountReadWriteOncePodEnabled: true,
old: driverWithSELinuxMountEnabled,
update: driverWithSELinuxMountDisabled,
wantSELinuxMount: &disabled,
},
{
name: "SELinux mount support feature disabled, before: nil, update: on",
seLinuxMountReadWriteOncePodEnabled: false,
old: driverWithNothing,
update: driverWithSELinuxMountEnabled,
wantSELinuxMount: nil,
},
{
name: "SELinux mount support feature disabled, before: off, update: on",
seLinuxMountReadWriteOncePodEnabled: false,
old: driverWithSELinuxMountDisabled,
update: driverWithSELinuxMountEnabled,
wantSELinuxMount: &enabled,
},
{
name: "SELinux mount support feature enabled, before: on, update: off",
seLinuxMountReadWriteOncePodEnabled: false,
old: driverWithSELinuxMountEnabled,
update: driverWithSELinuxMountDisabled,
wantSELinuxMount: &disabled,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, test.csiInlineVolumeEnabled)()
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, test.seLinuxMountReadWriteOncePodEnabled)()
csiDriver := test.update.DeepCopy()
Strategy.PrepareForUpdate(ctx, csiDriver, test.old)
@ -276,9 +337,9 @@ func TestCSIDriverPrepareForUpdate(t *testing.T) {
require.Equal(t, test.wantModes, csiDriver.Spec.VolumeLifecycleModes)
require.Equal(t, test.wantTokenRequests, csiDriver.Spec.TokenRequests)
require.Equal(t, test.wantRequiresRepublish, csiDriver.Spec.RequiresRepublish)
require.Equal(t, test.wantSELinuxMount, csiDriver.Spec.SELinuxMounted)
})
}
}
func TestCSIDriverValidation(t *testing.T) {

View File

@ -392,6 +392,27 @@ type CSIDriverSpec struct {
//
// +optional
RequiresRepublish *bool `json:"requiresRepublish,omitempty" protobuf:"varint,7,opt,name=requiresRepublish"`
// SELinuxMount specifies if the CSI driver supports "-o context"
// mount option.
//
// When "true", the CSI driver must ensure that all volumes provided by this CSI
// driver can be mounted separately with different `-o context` options. This is
// typical for storage backends that provide volumes as filesystems on block
// devices or as independent shared volumes.
// Kubernetes will call NodeStage / NodePublish with "-o context=xyz" mount
// option when mounting a ReadWriteOncePod volume used in Pod that has
// explicitly set SELinux context. In the future, it may be expanded to other
// volume AccessModes. In any case, Kubernetes will ensure that the volume is
// mounted only with a single SELinux context.
//
// When "false", Kubernetes won't pass any special SELinux mount options to the driver.
// This is typical for volumes that represent subdirectories of a bigger shared filesystem.
//
// Default is "false".
//
// +optional
SELinuxMount *bool `json:"seLinuxMount,omitempty" protobuf:"varint,8,opt,name=seLinuxMount"`
}
// FSGroupPolicy specifies if a CSI Driver supports modifying

View File

@ -410,6 +410,27 @@ type CSIDriverSpec struct {
//
// +optional
RequiresRepublish *bool `json:"requiresRepublish,omitempty" protobuf:"varint,7,opt,name=requiresRepublish"`
// SELinuxMount specifies if the CSI driver supports "-o context"
// mount option.
//
// When "true", the CSI driver must ensure that all volumes provided by this CSI
// driver can be mounted separately with different `-o context` options. This is
// typical for storage backends that provide volumes as filesystems on block
// devices or as independent shared volumes.
// Kubernetes will call NodeStage / NodePublish with "-o context=xyz" mount
// option when mounting a ReadWriteOncePod volume used in Pod that has
// explicitly set SELinux context. In the future, it may be expanded to other
// volume AccessModes. In any case, Kubernetes will ensure that the volume is
// mounted only with a single SELinux context.
//
// When "false", Kubernetes won't pass any special SELinux mount options to the driver.
// This is typical for volumes that represent subdirectories of a bigger shared filesystem.
//
// Default is "false".
//
// +optional
SELinuxMount *bool `json:"seLinuxMount,omitempty" protobuf:"varint,8,opt,name=seLinuxMount"`
}
// FSGroupPolicy specifies if a CSI Driver supports modifying