mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 03:11:40 +00:00
Add unit tests for DesiredStateOfWorldPopulator
This commit is contained in:
parent
39f0d78714
commit
f9c7ce5b9c
@ -31,7 +31,9 @@ import (
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
core "k8s.io/client-go/testing"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
csitrans "k8s.io/csi-translation-lib"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/kubelet/configmap"
|
||||
containertest "k8s.io/kubernetes/pkg/kubelet/container/testing"
|
||||
kubepod "k8s.io/kubernetes/pkg/kubelet/pod"
|
||||
@ -1067,6 +1069,195 @@ func TestCheckVolumeFSResize(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckVolumeSELinux(t *testing.T) {
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.ReadWriteOncePod, true)()
|
||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMountReadWriteOncePod, true)()
|
||||
fullOpts := &v1.SELinuxOptions{
|
||||
User: "system_u",
|
||||
Role: "object_r",
|
||||
Type: "container_t",
|
||||
Level: "s0:c1,c2",
|
||||
}
|
||||
differentFullOpts := &v1.SELinuxOptions{
|
||||
User: "system_u",
|
||||
Role: "object_r",
|
||||
Type: "container_t",
|
||||
Level: "s0:c9998,c9999",
|
||||
}
|
||||
partialOpts := &v1.SELinuxOptions{
|
||||
Level: "s0:c3,c4",
|
||||
}
|
||||
|
||||
testcases := []struct {
|
||||
name string
|
||||
accessModes []v1.PersistentVolumeAccessMode
|
||||
existingContainerSELinuxOpts *v1.SELinuxOptions
|
||||
newContainerSELinuxOpts *v1.SELinuxOptions
|
||||
pluginSupportsSELinux bool
|
||||
expectError bool
|
||||
expectedContext string
|
||||
}{
|
||||
{
|
||||
name: "RWOP with plugin with SELinux with full context in pod",
|
||||
accessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod},
|
||||
newContainerSELinuxOpts: fullOpts,
|
||||
pluginSupportsSELinux: true,
|
||||
expectedContext: "system_u:object_r:container_file_t:s0:c1,c2",
|
||||
},
|
||||
{
|
||||
name: "RWOP with plugin with SELinux with partial context in pod",
|
||||
accessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod},
|
||||
newContainerSELinuxOpts: partialOpts,
|
||||
pluginSupportsSELinux: true,
|
||||
expectedContext: "system_u:object_r:container_file_t:s0:c3,c4",
|
||||
},
|
||||
{
|
||||
name: "RWX with plugin with SELinux with fill context in pod",
|
||||
accessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteMany},
|
||||
newContainerSELinuxOpts: fullOpts,
|
||||
pluginSupportsSELinux: true,
|
||||
expectedContext: "", // RWX volumes don't support SELinux
|
||||
},
|
||||
{
|
||||
name: "RWOP with plugin with no SELinux with fill context in pod",
|
||||
accessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod},
|
||||
newContainerSELinuxOpts: fullOpts,
|
||||
pluginSupportsSELinux: false,
|
||||
expectedContext: "", // plugin doesn't support SELinux
|
||||
},
|
||||
{
|
||||
name: "RWOP with plugin with SELinux with no context in pod",
|
||||
accessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod},
|
||||
newContainerSELinuxOpts: nil,
|
||||
pluginSupportsSELinux: true,
|
||||
expectedContext: "",
|
||||
},
|
||||
{
|
||||
name: "RWOP with plugin with SELinux with full context in pod with existing pod",
|
||||
accessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod},
|
||||
existingContainerSELinuxOpts: fullOpts,
|
||||
newContainerSELinuxOpts: fullOpts,
|
||||
pluginSupportsSELinux: true,
|
||||
expectedContext: "system_u:object_r:container_file_t:s0:c1,c2",
|
||||
},
|
||||
{
|
||||
name: "mismatched SELinux with RWX - success",
|
||||
accessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteMany},
|
||||
existingContainerSELinuxOpts: fullOpts,
|
||||
newContainerSELinuxOpts: differentFullOpts,
|
||||
pluginSupportsSELinux: true,
|
||||
expectedContext: "",
|
||||
},
|
||||
{
|
||||
name: "mismatched SELinux with RWOP - failure",
|
||||
accessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod},
|
||||
existingContainerSELinuxOpts: fullOpts,
|
||||
newContainerSELinuxOpts: differentFullOpts,
|
||||
pluginSupportsSELinux: true,
|
||||
expectError: true,
|
||||
// The original seLinuxOpts are kept in DSW
|
||||
expectedContext: "system_u:object_r:container_file_t:s0:c1,c2",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
pv := &v1.PersistentVolume{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "dswp-test-volume-name",
|
||||
},
|
||||
Spec: v1.PersistentVolumeSpec{
|
||||
PersistentVolumeSource: v1.PersistentVolumeSource{RBD: &v1.RBDPersistentVolumeSource{}},
|
||||
Capacity: volumeCapacity(1),
|
||||
ClaimRef: &v1.ObjectReference{Namespace: "ns", Name: "file-bound"},
|
||||
AccessModes: tc.accessModes,
|
||||
},
|
||||
}
|
||||
pvc := &v1.PersistentVolumeClaim{
|
||||
Spec: v1.PersistentVolumeClaimSpec{
|
||||
VolumeName: pv.Name,
|
||||
Resources: v1.ResourceRequirements{
|
||||
Requests: pv.Spec.Capacity,
|
||||
},
|
||||
AccessModes: tc.accessModes,
|
||||
},
|
||||
Status: v1.PersistentVolumeClaimStatus{
|
||||
Phase: v1.ClaimBound,
|
||||
Capacity: pv.Spec.Capacity,
|
||||
},
|
||||
}
|
||||
|
||||
container := v1.Container{
|
||||
SecurityContext: &v1.SecurityContext{
|
||||
SELinuxOptions: nil,
|
||||
},
|
||||
VolumeMounts: []v1.VolumeMount{
|
||||
{
|
||||
Name: pv.Name,
|
||||
MountPath: "/mnt",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
fakeVolumePluginMgr, plugin := volumetesting.GetTestKubeletVolumePluginMgr(t)
|
||||
plugin.SupportsSELinux = tc.pluginSupportsSELinux
|
||||
dswp, fakePodManager, fakeDSW, _, _ := createDswpWithVolumeWithCustomPluginMgr(t, pv, pvc, fakeVolumePluginMgr)
|
||||
|
||||
var existingPod *v1.Pod
|
||||
if tc.existingContainerSELinuxOpts != nil {
|
||||
// Add existing pod + volume
|
||||
existingContainer := container
|
||||
existingContainer.SecurityContext.SELinuxOptions = tc.existingContainerSELinuxOpts
|
||||
existingPod = createPodWithVolume("dswp-old-pod", "dswp-test-volume-name", "file-bound", []v1.Container{existingContainer})
|
||||
fakePodManager.AddPod(existingPod)
|
||||
dswp.findAndAddNewPods()
|
||||
}
|
||||
|
||||
newContainer := container
|
||||
newContainer.SecurityContext.SELinuxOptions = tc.newContainerSELinuxOpts
|
||||
newPod := createPodWithVolume("dswp-test-pod", "dswp-test-volume-name", "file-bound", []v1.Container{newContainer})
|
||||
|
||||
// Act - add the new Pod
|
||||
fakePodManager.AddPod(newPod)
|
||||
dswp.findAndAddNewPods()
|
||||
|
||||
// Assert
|
||||
|
||||
// Check the global volume state
|
||||
uniquePodName := types.UniquePodName(newPod.UID)
|
||||
uniqueVolumeName := v1.UniqueVolumeName("fake-plugin/" + newPod.Spec.Volumes[0].Name)
|
||||
volumeExists := fakeDSW.VolumeExists(uniqueVolumeName, tc.expectedContext)
|
||||
if !volumeExists {
|
||||
t.Errorf(
|
||||
"VolumeExists(%q) failed. Expected: <true> Actual: <%v>",
|
||||
uniqueVolumeName,
|
||||
volumeExists)
|
||||
}
|
||||
|
||||
// Check the Pod local volume state
|
||||
podExistsInVolume := fakeDSW.PodExistsInVolume(uniquePodName, uniqueVolumeName, tc.expectedContext)
|
||||
if !podExistsInVolume && !tc.expectError {
|
||||
t.Errorf(
|
||||
"DSW PodExistsInVolume returned incorrect value. Expected: <true> Actual: <%v>",
|
||||
podExistsInVolume)
|
||||
}
|
||||
if podExistsInVolume && tc.expectError {
|
||||
t.Errorf(
|
||||
"DSW PodExistsInVolume returned incorrect value. Expected: <false> Actual: <%v>",
|
||||
podExistsInVolume)
|
||||
}
|
||||
errors := fakeDSW.GetPodsWithErrors()
|
||||
if tc.expectError && len(errors) == 0 {
|
||||
t.Errorf("Expected Pod error, got none")
|
||||
}
|
||||
if !tc.expectError && len(errors) > 0 {
|
||||
t.Errorf("Unexpected Pod errors: %v", errors)
|
||||
}
|
||||
verifyVolumeExistsInVolumesToMount(t, uniqueVolumeName, false /* expectReportedInUse */, fakeDSW)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func createResizeRelatedVolumes(volumeMode *v1.PersistentVolumeMode) (pv *v1.PersistentVolume, pvc *v1.PersistentVolumeClaim) {
|
||||
pv = &v1.PersistentVolume{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@ -1175,7 +1366,7 @@ func createPodWithVolume(pod, pv, pvc string, containers []v1.Container) *v1.Pod
|
||||
return &v1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: pod,
|
||||
UID: "dswp-test-pod-uid",
|
||||
UID: kubetypes.UID(pod + "-uid"),
|
||||
Namespace: "dswp-test",
|
||||
},
|
||||
Spec: v1.PodSpec{
|
||||
|
@ -28,7 +28,10 @@ import (
|
||||
"k8s.io/apimachinery/pkg/api/resource"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
||||
_ "k8s.io/kubernetes/pkg/apis/core/install"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
"k8s.io/kubernetes/pkg/util/slice"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
utilptr "k8s.io/utils/pointer"
|
||||
|
Loading…
Reference in New Issue
Block a user