mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 11:50:44 +00:00
Merge pull request #105996 from marosset/host-process-volume-mount-e2e
Adding e2e tests to validate volume mounts in HostProcessContainers on Windows
This commit is contained in:
commit
662ea77c6a
@ -22,8 +22,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
|
|
||||||
|
|
||||||
"github.com/onsi/ginkgo"
|
"github.com/onsi/ginkgo"
|
||||||
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"
|
||||||
@ -31,10 +29,46 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/util/uuid"
|
"k8s.io/apimachinery/pkg/util/uuid"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
"k8s.io/kubernetes/pkg/features"
|
||||||
"k8s.io/kubernetes/test/e2e/framework"
|
"k8s.io/kubernetes/test/e2e/framework"
|
||||||
|
e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
|
||||||
e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
|
e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
|
||||||
imageutils "k8s.io/kubernetes/test/utils/image"
|
imageutils "k8s.io/kubernetes/test/utils/image"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
validation_script = `if (-not(Test-Path $env:CONTAINER_SANDBOX_MOUNT_POINT\etc\emptydir)) {
|
||||||
|
throw "Cannot find emptydir volume"
|
||||||
|
}
|
||||||
|
if (-not(Test-Path $env:CONTAINER_SANDBOX_MOUNT_POINT\etc\configmap\text.txt)) {
|
||||||
|
throw "Cannot find text.txt in configmap-volume"
|
||||||
|
}
|
||||||
|
$c = Get-Content -Path $env:CONTAINER_SANDBOX_MOUNT_POINT\etc\configmap\text.txt
|
||||||
|
if ($c -ne "Lorem ipsum dolor sit amet") {
|
||||||
|
throw "Contents of /etc/configmap/text.txt are not as expected"
|
||||||
|
}
|
||||||
|
if (-not(Test-Path $env:CONTAINER_SANDBOX_MOUNT_POINT\etc\hostpath)) {
|
||||||
|
throw "Cannot find hostpath volume"
|
||||||
|
}
|
||||||
|
if (-not(Test-Path $env:CONTAINER_SANDBOX_MOUNT_POINT\etc\downwardapi\podname)) {
|
||||||
|
throw "Cannot find podname file in downward-api volume"
|
||||||
|
}
|
||||||
|
$c = Get-Content -Path $env:CONTAINER_SANDBOX_MOUNT_POINT\etc\downwardapi\podname
|
||||||
|
if ($c -ne "host-process-volume-mounts") {
|
||||||
|
throw "Contents of /etc/downward-api/podname are not as expected"
|
||||||
|
}
|
||||||
|
if (-not(Test-Path $env:CONTAINER_SANDBOX_MOUNT_POINT\etc\secret\foo.txt)) {
|
||||||
|
throw "Cannot find file foo.txt in secret volume"
|
||||||
|
}
|
||||||
|
$c = Get-Content $env:CONTAINER_SANDBOX_MOUNT_POINT\etc\secret\foo.txt
|
||||||
|
if ($c -ne "bar") {
|
||||||
|
Write-Output $c
|
||||||
|
throw "Contents of /etc/secret/foo.txt are not as expected"
|
||||||
|
}
|
||||||
|
if ($env:NODE_NAME_TEST -ne $env:COMPUTERNAME) {
|
||||||
|
throw "NODE_NAME_TEST env var does not equal COMPUTERNAME"
|
||||||
|
}
|
||||||
|
Write-Output "SUCCESS"`
|
||||||
|
)
|
||||||
|
|
||||||
var _ = SIGDescribe("[Feature:WindowsHostProcessContainers] [Excluded:WindowsDocker] [MinimumKubeletVersion:1.22] HostProcess containers", func() {
|
var _ = SIGDescribe("[Feature:WindowsHostProcessContainers] [Excluded:WindowsDocker] [MinimumKubeletVersion:1.22] HostProcess containers", func() {
|
||||||
ginkgo.BeforeEach(func() {
|
ginkgo.BeforeEach(func() {
|
||||||
e2eskipper.SkipUnlessNodeOSDistroIs("windows")
|
e2eskipper.SkipUnlessNodeOSDistroIs("windows")
|
||||||
@ -383,8 +417,201 @@ var _ = SIGDescribe("[Feature:WindowsHostProcessContainers] [Excluded:WindowsDoc
|
|||||||
}
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
ginkgo.It("should support various volume mount types", func() {
|
||||||
|
ns := f.Namespace
|
||||||
|
|
||||||
|
ginkgo.By("Creating a configmap containing test data and a validation script")
|
||||||
|
configMap := &v1.ConfigMap{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
APIVersion: "v1",
|
||||||
|
Kind: "ConfigMap",
|
||||||
|
},
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "sample-config-map",
|
||||||
|
},
|
||||||
|
Data: map[string]string{
|
||||||
|
"text": "Lorem ipsum dolor sit amet",
|
||||||
|
"validation-script": validation_script,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err := f.ClientSet.CoreV1().ConfigMaps(ns.Name).Create(context.TODO(), configMap, metav1.CreateOptions{})
|
||||||
|
framework.ExpectNoError(err, "unable to create create configmap")
|
||||||
|
|
||||||
|
ginkgo.By("Creating a secret containing test data")
|
||||||
|
secret := &v1.Secret{
|
||||||
|
TypeMeta: metav1.TypeMeta{
|
||||||
|
APIVersion: "v1",
|
||||||
|
Kind: "Secret",
|
||||||
|
},
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "sample-secret",
|
||||||
|
},
|
||||||
|
Type: v1.SecretTypeOpaque,
|
||||||
|
Data: map[string][]byte{
|
||||||
|
"foo": []byte("bar"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err = f.ClientSet.CoreV1().Secrets(ns.Name).Create(context.TODO(), secret, metav1.CreateOptions{})
|
||||||
|
framework.ExpectNoError(err, "unable to create secret")
|
||||||
|
|
||||||
|
ginkgo.By("Creating a pod with a HostProcess container that uses various types of volume mounts")
|
||||||
|
|
||||||
|
podAndContainerName := "host-process-volume-mounts"
|
||||||
|
pod := makeTestPodWithVolumeMounts(podAndContainerName)
|
||||||
|
|
||||||
|
f.PodClient().Create(pod)
|
||||||
|
|
||||||
|
ginkgo.By("Waiting for pod to run")
|
||||||
|
f.PodClient().WaitForFinish(podAndContainerName, 3*time.Minute)
|
||||||
|
|
||||||
|
logs, err := e2epod.GetPodLogs(f.ClientSet, ns.Name, podAndContainerName, podAndContainerName)
|
||||||
|
framework.ExpectNoError(err, "Error getting pod logs")
|
||||||
|
framework.Logf("Container logs: %s", logs)
|
||||||
|
|
||||||
|
ginkgo.By("Then ensuring pod finished running successfully")
|
||||||
|
p, err := f.ClientSet.CoreV1().Pods(ns.Name).Get(
|
||||||
|
context.TODO(),
|
||||||
|
podAndContainerName,
|
||||||
|
metav1.GetOptions{})
|
||||||
|
|
||||||
|
framework.ExpectNoError(err, "Error retrieving pod")
|
||||||
|
framework.ExpectEqual(p.Status.Phase, v1.PodSucceeded)
|
||||||
|
})
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
func makeTestPodWithVolumeMounts(name string) *v1.Pod {
|
||||||
|
trueVar := true
|
||||||
|
username := "NT AUTHORITY\\SYSTEM"
|
||||||
|
hostPathDirectoryOrCreate := v1.HostPathDirectoryOrCreate
|
||||||
|
return &v1.Pod{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: name,
|
||||||
|
},
|
||||||
|
Spec: v1.PodSpec{
|
||||||
|
SecurityContext: &v1.PodSecurityContext{
|
||||||
|
WindowsOptions: &v1.WindowsSecurityContextOptions{
|
||||||
|
HostProcess: &trueVar,
|
||||||
|
RunAsUserName: &username,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
HostNetwork: true,
|
||||||
|
Containers: []v1.Container{
|
||||||
|
{
|
||||||
|
Image: imageutils.GetE2EImage(imageutils.BusyBox),
|
||||||
|
Name: name,
|
||||||
|
Command: []string{"powershell.exe", "./etc/configmap/validationscript.ps1"},
|
||||||
|
Env: []v1.EnvVar{
|
||||||
|
{
|
||||||
|
Name: "NODE_NAME_TEST",
|
||||||
|
ValueFrom: &v1.EnvVarSource{
|
||||||
|
FieldRef: &v1.ObjectFieldSelector{
|
||||||
|
FieldPath: "spec.nodeName",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
VolumeMounts: []v1.VolumeMount{
|
||||||
|
{
|
||||||
|
Name: "emptydir-volume",
|
||||||
|
MountPath: "/etc/emptydir",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "configmap-volume",
|
||||||
|
MountPath: "/etc/configmap",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "hostpath-volume",
|
||||||
|
MountPath: "/etc/hostpath",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "downwardapi-volume",
|
||||||
|
MountPath: "/etc/downwardapi",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "secret-volume",
|
||||||
|
MountPath: "/etc/secret",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
RestartPolicy: v1.RestartPolicyNever,
|
||||||
|
NodeSelector: map[string]string{
|
||||||
|
"kubernetes.io/os": "windows",
|
||||||
|
},
|
||||||
|
Volumes: []v1.Volume{
|
||||||
|
{
|
||||||
|
Name: "emptydir-volume",
|
||||||
|
VolumeSource: v1.VolumeSource{
|
||||||
|
EmptyDir: &v1.EmptyDirVolumeSource{
|
||||||
|
Medium: v1.StorageMediumDefault,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "configmap-volume",
|
||||||
|
VolumeSource: v1.VolumeSource{
|
||||||
|
ConfigMap: &v1.ConfigMapVolumeSource{
|
||||||
|
LocalObjectReference: v1.LocalObjectReference{
|
||||||
|
Name: "sample-config-map",
|
||||||
|
},
|
||||||
|
Items: []v1.KeyToPath{
|
||||||
|
{
|
||||||
|
Key: "text",
|
||||||
|
Path: "text.txt",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: "validation-script",
|
||||||
|
Path: "validationscript.ps1",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "hostpath-volume",
|
||||||
|
VolumeSource: v1.VolumeSource{
|
||||||
|
HostPath: &v1.HostPathVolumeSource{
|
||||||
|
Path: "/var/hostpath",
|
||||||
|
Type: &hostPathDirectoryOrCreate,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "downwardapi-volume",
|
||||||
|
VolumeSource: v1.VolumeSource{
|
||||||
|
DownwardAPI: &v1.DownwardAPIVolumeSource{
|
||||||
|
Items: []v1.DownwardAPIVolumeFile{
|
||||||
|
{
|
||||||
|
Path: "podname",
|
||||||
|
FieldRef: &v1.ObjectFieldSelector{
|
||||||
|
FieldPath: "metadata.name",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "secret-volume",
|
||||||
|
VolumeSource: v1.VolumeSource{
|
||||||
|
Secret: &v1.SecretVolumeSource{
|
||||||
|
SecretName: "sample-secret",
|
||||||
|
Items: []v1.KeyToPath{
|
||||||
|
{
|
||||||
|
Key: "foo",
|
||||||
|
Path: "foo.txt",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func SkipUnlessWindowsHostProcessContainersEnabled() {
|
func SkipUnlessWindowsHostProcessContainersEnabled() {
|
||||||
if !framework.TestContext.FeatureGates[string(features.WindowsHostProcessContainers)] {
|
if !framework.TestContext.FeatureGates[string(features.WindowsHostProcessContainers)] {
|
||||||
e2eskipper.Skipf("Skipping test because feature 'WindowsHostProcessContainers' is not enabled")
|
e2eskipper.Skipf("Skipping test because feature 'WindowsHostProcessContainers' is not enabled")
|
||||||
|
Loading…
Reference in New Issue
Block a user