return an error instead of recording a test failure

Signed-off-by: carlory <baofa.fan@daocloud.io>
This commit is contained in:
carlory 2025-01-21 22:33:56 +08:00
parent aecf3238bf
commit c68fc01b77
6 changed files with 74 additions and 40 deletions

View File

@ -20,6 +20,7 @@ import (
"bytes" "bytes"
"context" "context"
"errors" "errors"
"fmt"
"io" "io"
"net/url" "net/url"
"strings" "strings"
@ -144,40 +145,40 @@ func ExecShellInPodWithFullOutput(ctx context.Context, f *framework.Framework, p
} }
// VerifyExecInPodSucceed verifies shell cmd in target pod succeed // VerifyExecInPodSucceed verifies shell cmd in target pod succeed
func VerifyExecInPodSucceed(ctx context.Context, f *framework.Framework, pod *v1.Pod, shExec string) { func VerifyExecInPodSucceed(ctx context.Context, f *framework.Framework, pod *v1.Pod, shExec string) error {
stdout, stderr, err := ExecShellInPodWithFullOutput(ctx, f, pod.Name, shExec) stdout, stderr, err := ExecShellInPodWithFullOutput(ctx, f, pod.Name, shExec)
if err != nil { if err != nil {
var exitError clientexec.CodeExitError var exitError clientexec.CodeExitError
if errors.As(err, &exitError) { if errors.As(err, &exitError) {
exitCode := exitError.ExitStatus() exitCode := exitError.ExitStatus()
framework.ExpectNoError(err, return fmt.Errorf("%q should succeed, but failed with exit code %d and error message %w\nstdout: %s\nstderr: %s",
"%q should succeed, but failed with exit code %d and error message %q\nstdout: %s\nstderr: %s",
shExec, exitCode, exitError, stdout, stderr) shExec, exitCode, exitError, stdout, stderr)
} else { } else {
framework.ExpectNoError(err, return fmt.Errorf("%q should succeed, but failed with error message %w\nstdout: %s\nstderr: %s",
"%q should succeed, but failed with error message %q\nstdout: %s\nstderr: %s",
shExec, err, stdout, stderr) shExec, err, stdout, stderr)
} }
} }
return nil
} }
// VerifyExecInPodFail verifies shell cmd in target pod fail with certain exit code // VerifyExecInPodFail verifies shell cmd in target pod fail with certain exit code
func VerifyExecInPodFail(ctx context.Context, f *framework.Framework, pod *v1.Pod, shExec string, exitCode int) { func VerifyExecInPodFail(ctx context.Context, f *framework.Framework, pod *v1.Pod, shExec string, exitCode int) error {
stdout, stderr, err := ExecShellInPodWithFullOutput(ctx, f, pod.Name, shExec) stdout, stderr, err := ExecShellInPodWithFullOutput(ctx, f, pod.Name, shExec)
if err != nil { if err != nil {
var exitError clientexec.CodeExitError var exitError clientexec.CodeExitError
if errors.As(err, &exitError) { if errors.As(err, &exitError) {
actualExitCode := exitError.ExitStatus() actualExitCode := exitError.ExitStatus()
gomega.Expect(actualExitCode).To(gomega.Equal(exitCode), if actualExitCode == exitCode {
"%q should fail with exit code %d, but failed with exit code %d and error message %q\nstdout: %s\nstderr: %s", return nil
}
return fmt.Errorf("%q should fail with exit code %d, but failed with exit code %d and error message %w\nstdout: %s\nstderr: %s",
shExec, exitCode, actualExitCode, exitError, stdout, stderr) shExec, exitCode, actualExitCode, exitError, stdout, stderr)
} else { } else {
framework.ExpectNoError(err, return fmt.Errorf("%q should fail with exit code %d, but failed with error message %w\nstdout: %s\nstderr: %s",
"%q should fail with exit code %d, but failed with error message %q\nstdout: %s\nstderr: %s",
shExec, exitCode, err, stdout, stderr) shExec, exitCode, err, stdout, stderr)
} }
} }
gomega.Expect(err).To(gomega.HaveOccurred(), "%q should fail with exit code %d, but exit without error", shExec, exitCode) return fmt.Errorf("%q should fail with exit code %d, but exit without error", shExec, exitCode)
} }
func execute(ctx context.Context, method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool) error { func execute(ctx context.Context, method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool) error {

View File

@ -510,7 +510,8 @@ func testVolumeContent(ctx context.Context, f *framework.Framework, pod *v1.Pod,
framework.ExpectNoError(err, "failed: finding the contents of the block device %s.", deviceName) framework.ExpectNoError(err, "failed: finding the contents of the block device %s.", deviceName)
// Check that it's a real block device // Check that it's a real block device
CheckVolumeModeOfPath(ctx, f, pod, test.Mode, deviceName) err = CheckVolumeModeOfPath(ctx, f, pod, test.Mode, deviceName)
framework.ExpectNoError(err, "failed: getting the right privileges in the block device %v", deviceName)
} else { } else {
// Filesystem: check content // Filesystem: check content
fileName := fmt.Sprintf("/opt/%d/%s", i, test.File) fileName := fmt.Sprintf("/opt/%d/%s", i, test.File)
@ -520,7 +521,8 @@ func testVolumeContent(ctx context.Context, f *framework.Framework, pod *v1.Pod,
// Check that a directory has been mounted // Check that a directory has been mounted
dirName := filepath.Dir(fileName) dirName := filepath.Dir(fileName)
CheckVolumeModeOfPath(ctx, f, pod, test.Mode, dirName) err = CheckVolumeModeOfPath(ctx, f, pod, test.Mode, dirName)
framework.ExpectNoError(err, "failed: getting the right privileges in the directory %v", dirName)
if !framework.NodeOSDistroIs("windows") { if !framework.NodeOSDistroIs("windows") {
// Filesystem: check fsgroup // Filesystem: check fsgroup
@ -663,18 +665,27 @@ func generateWriteFileCmd(content, fullPath string) []string {
} }
// CheckVolumeModeOfPath check mode of volume // CheckVolumeModeOfPath check mode of volume
func CheckVolumeModeOfPath(ctx context.Context, f *framework.Framework, pod *v1.Pod, volMode v1.PersistentVolumeMode, path string) { func CheckVolumeModeOfPath(ctx context.Context, f *framework.Framework, pod *v1.Pod, volMode v1.PersistentVolumeMode, path string) error {
if volMode == v1.PersistentVolumeBlock { if volMode == v1.PersistentVolumeBlock {
// Check if block exists // Check if block exists
e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("test -b %s", path)) if err := e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("test -b %s", path)); err != nil {
return err
}
// Double check that it's not directory // Double check that it's not directory
e2epod.VerifyExecInPodFail(ctx, f, pod, fmt.Sprintf("test -d %s", path), 1) if err := e2epod.VerifyExecInPodFail(ctx, f, pod, fmt.Sprintf("test -d %s", path), 1); err != nil {
return err
}
} else { } else {
// Check if directory exists // Check if directory exists
e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("test -d %s", path)) if err := e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("test -d %s", path)); err != nil {
return err
}
// Double check that it's not block // Double check that it's not block
e2epod.VerifyExecInPodFail(ctx, f, pod, fmt.Sprintf("test -b %s", path), 1) if err := e2epod.VerifyExecInPodFail(ctx, f, pod, fmt.Sprintf("test -b %s", path), 1); err != nil {
return err
}
} }
return nil
} }

View File

@ -194,7 +194,8 @@ func (p *ephemeralTestSuite) DefineTests(driver storageframework.TestDriver, pat
// attempt to create a dummy file and expect for it not to be created // attempt to create a dummy file and expect for it not to be created
command = "ls /mnt/test* && (touch /mnt/test-0/hello-world || true) && [ ! -f /mnt/test-0/hello-world ]" command = "ls /mnt/test* && (touch /mnt/test-0/hello-world || true) && [ ! -f /mnt/test-0/hello-world ]"
} }
e2epod.VerifyExecInPodSucceed(ctx, f, pod, command) err := e2epod.VerifyExecInPodSucceed(ctx, f, pod, command)
framework.ExpectNoError(err, "while checking read-only mount")
return nil return nil
} }
l.testCase.TestEphemeral(ctx) l.testCase.TestEphemeral(ctx)
@ -214,7 +215,8 @@ func (p *ephemeralTestSuite) DefineTests(driver storageframework.TestDriver, pat
if pattern.VolMode == v1.PersistentVolumeBlock { if pattern.VolMode == v1.PersistentVolumeBlock {
command = "if ! [ -b /mnt/test-0 ]; then echo /mnt/test-0 is not a block device; exit 1; fi" command = "if ! [ -b /mnt/test-0 ]; then echo /mnt/test-0 is not a block device; exit 1; fi"
} }
e2epod.VerifyExecInPodSucceed(ctx, f, pod, command) err := e2epod.VerifyExecInPodSucceed(ctx, f, pod, command)
framework.ExpectNoError(err, "while checking read/write mount")
return nil return nil
} }
l.testCase.TestEphemeral(ctx) l.testCase.TestEphemeral(ctx)
@ -308,8 +310,10 @@ func (p *ephemeralTestSuite) DefineTests(driver storageframework.TestDriver, pat
// visible in the other. // visible in the other.
if pattern.VolMode != v1.PersistentVolumeBlock && !readOnly && !shared { if pattern.VolMode != v1.PersistentVolumeBlock && !readOnly && !shared {
ginkgo.By("writing data in one pod and checking the second does not see it (it should get its own volume)") ginkgo.By("writing data in one pod and checking the second does not see it (it should get its own volume)")
e2epod.VerifyExecInPodSucceed(ctx, f, pod, "touch /mnt/test-0/hello-world") err := e2epod.VerifyExecInPodSucceed(ctx, f, pod, "touch /mnt/test-0/hello-world")
e2epod.VerifyExecInPodSucceed(ctx, f, pod2, "[ ! -f /mnt/test-0/hello-world ]") framework.ExpectNoError(err, "while writing data in first pod")
err = e2epod.VerifyExecInPodSucceed(ctx, f, pod2, "[ ! -f /mnt/test-0/hello-world ]")
framework.ExpectNoError(err, "while checking data in second pod")
} }
// TestEphemeral expects the pod to be fully deleted // TestEphemeral expects the pod to be fully deleted

View File

@ -499,7 +499,8 @@ func testAccessMultipleVolumes(ctx context.Context, f *framework.Framework, cs c
index := i + 1 index := i + 1
path := fmt.Sprintf("/mnt/volume%d", index) path := fmt.Sprintf("/mnt/volume%d", index)
ginkgo.By(fmt.Sprintf("Checking if the volume%d exists as expected volume mode (%s)", index, *pvc.Spec.VolumeMode)) ginkgo.By(fmt.Sprintf("Checking if the volume%d exists as expected volume mode (%s)", index, *pvc.Spec.VolumeMode))
e2evolume.CheckVolumeModeOfPath(ctx, f, pod, *pvc.Spec.VolumeMode, path) err = e2evolume.CheckVolumeModeOfPath(ctx, f, pod, *pvc.Spec.VolumeMode, path)
framework.ExpectNoError(err)
if readSeedBase > 0 { if readSeedBase > 0 {
ginkgo.By(fmt.Sprintf("Checking if read from the volume%d works properly", index)) ginkgo.By(fmt.Sprintf("Checking if read from the volume%d works properly", index))
@ -607,7 +608,8 @@ func TestConcurrentAccessToSingleVolume(ctx context.Context, f *framework.Framew
for i, pod := range pods { for i, pod := range pods {
index := i + 1 index := i + 1
ginkgo.By(fmt.Sprintf("Checking if the volume in pod%d exists as expected volume mode (%s)", index, *pvc.Spec.VolumeMode)) ginkgo.By(fmt.Sprintf("Checking if the volume in pod%d exists as expected volume mode (%s)", index, *pvc.Spec.VolumeMode))
e2evolume.CheckVolumeModeOfPath(ctx, f, pod, *pvc.Spec.VolumeMode, path) err := e2evolume.CheckVolumeModeOfPath(ctx, f, pod, *pvc.Spec.VolumeMode, path)
framework.ExpectNoError(err)
if readOnly { if readOnly {
ginkgo.By("Skipping volume content checks, volume is read-only") ginkgo.By("Skipping volume content checks, volume is read-only")
@ -643,7 +645,8 @@ func TestConcurrentAccessToSingleVolume(ctx context.Context, f *framework.Framew
index := i + 1 index := i + 1
// index of pod and index of pvc match, because pods are created above way // index of pod and index of pvc match, because pods are created above way
ginkgo.By(fmt.Sprintf("Rechecking if the volume in pod%d exists as expected volume mode (%s)", index, *pvc.Spec.VolumeMode)) ginkgo.By(fmt.Sprintf("Rechecking if the volume in pod%d exists as expected volume mode (%s)", index, *pvc.Spec.VolumeMode))
e2evolume.CheckVolumeModeOfPath(ctx, f, pod, *pvc.Spec.VolumeMode, "/mnt/volume1") err := e2evolume.CheckVolumeModeOfPath(ctx, f, pod, *pvc.Spec.VolumeMode, "/mnt/volume1")
framework.ExpectNoError(err)
if readOnly { if readOnly {
ginkgo.By("Skipping volume content checks, volume is read-only") ginkgo.By("Skipping volume content checks, volume is read-only")

View File

@ -449,25 +449,34 @@ func isSudoPresent(ctx context.Context, nodeIP string, provider string) bool {
func CheckReadWriteToPath(ctx context.Context, f *framework.Framework, pod *v1.Pod, volMode v1.PersistentVolumeMode, path string) { func CheckReadWriteToPath(ctx context.Context, f *framework.Framework, pod *v1.Pod, volMode v1.PersistentVolumeMode, path string) {
if volMode == v1.PersistentVolumeBlock { if volMode == v1.PersistentVolumeBlock {
// random -> file1 // random -> file1
e2epod.VerifyExecInPodSucceed(ctx, f, pod, "dd if=/dev/urandom of=/tmp/file1 bs=64 count=1") err := e2epod.VerifyExecInPodSucceed(ctx, f, pod, "dd if=/dev/urandom of=/tmp/file1 bs=64 count=1")
framework.ExpectNoError(err, "Failed to write to file1")
// file1 -> dev (write to dev) // file1 -> dev (write to dev)
e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("dd if=/tmp/file1 of=%s bs=64 count=1", path)) err = e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("dd if=/tmp/file1 of=%s bs=64 count=1", path))
framework.ExpectNoError(err, "Failed to write to block volume")
// dev -> file2 (read from dev) // dev -> file2 (read from dev)
e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("dd if=%s of=/tmp/file2 bs=64 count=1", path)) err = e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("dd if=%s of=/tmp/file2 bs=64 count=1", path))
framework.ExpectNoError(err, "Failed to read from block volume")
// file1 == file2 (check contents) // file1 == file2 (check contents)
e2epod.VerifyExecInPodSucceed(ctx, f, pod, "diff /tmp/file1 /tmp/file2") err = e2epod.VerifyExecInPodSucceed(ctx, f, pod, "diff /tmp/file1 /tmp/file2")
framework.ExpectNoError(err, "Failed to compare file1 and file2")
// Clean up temp files // Clean up temp files
e2epod.VerifyExecInPodSucceed(ctx, f, pod, "rm -f /tmp/file1 /tmp/file2") err = e2epod.VerifyExecInPodSucceed(ctx, f, pod, "rm -f /tmp/file1 /tmp/file2")
framework.ExpectNoError(err, "Failed to clean up temp files")
// Check that writing file to block volume fails // Check that writing file to block volume fails
e2epod.VerifyExecInPodFail(ctx, f, pod, fmt.Sprintf("echo 'Hello world.' > %s/file1.txt", path), 1) err = e2epod.VerifyExecInPodFail(ctx, f, pod, fmt.Sprintf("echo 'Hello world.' > %s/file1.txt", path), 1)
framework.ExpectNoError(err, "Expected write to block volume to fail")
} else { } else {
// text -> file1 (write to file) // text -> file1 (write to file)
e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("echo 'Hello world.' > %s/file1.txt", path)) err := e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("echo 'Hello world.' > %s/file1.txt", path))
framework.ExpectNoError(err, "Failed to write to file1")
// grep file1 (read from file and check contents) // grep file1 (read from file and check contents)
e2epod.VerifyExecInPodSucceed(ctx, f, pod, readFile("Hello word.", path)) err = e2epod.VerifyExecInPodSucceed(ctx, f, pod, readFile("Hello word.", path))
framework.ExpectNoError(err, "Failed to read from file1")
// Check that writing to directory as block volume fails // Check that writing to directory as block volume fails
e2epod.VerifyExecInPodFail(ctx, f, pod, fmt.Sprintf("dd if=/dev/urandom of=%s bs=64 count=1", path), 1) err = e2epod.VerifyExecInPodFail(ctx, f, pod, fmt.Sprintf("dd if=/dev/urandom of=%s bs=64 count=1", path), 1)
framework.ExpectNoError(err, "Expected write to directory to fail")
} }
} }
@ -513,8 +522,10 @@ func CheckReadFromPath(ctx context.Context, f *framework.Framework, pod *v1.Pod,
sum := sha256.Sum256(genBinDataFromSeed(len, seed)) sum := sha256.Sum256(genBinDataFromSeed(len, seed))
e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("dd if=%s %s bs=%d count=1 | sha256sum", pathForVolMode, iflag, len)) err := e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("dd if=%s %s bs=%d count=1 | sha256sum", pathForVolMode, iflag, len))
e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("dd if=%s %s bs=%d count=1 | sha256sum | grep -Fq %x", pathForVolMode, iflag, len, sum)) framework.ExpectNoError(err, "Failed to read from %s", pathForVolMode)
err = e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("dd if=%s %s bs=%d count=1 | sha256sum | grep -Fq %x", pathForVolMode, iflag, len, sum))
framework.ExpectNoError(err, "Failed to read from %s", pathForVolMode)
} }
// CheckWriteToPath that file can be properly written. // CheckWriteToPath that file can be properly written.
@ -538,8 +549,10 @@ func CheckWriteToPath(ctx context.Context, f *framework.Framework, pod *v1.Pod,
encoded := base64.StdEncoding.EncodeToString(genBinDataFromSeed(len, seed)) encoded := base64.StdEncoding.EncodeToString(genBinDataFromSeed(len, seed))
e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("echo %s | base64 -d | sha256sum", encoded)) err := e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("echo %s | base64 -d | sha256sum", encoded))
e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("echo %s | base64 -d | dd of=%s %s bs=%d count=1", encoded, pathForVolMode, oflag, len)) framework.ExpectNoError(err, "Failed to generate sha256sum of encoded data")
err = e2epod.VerifyExecInPodSucceed(ctx, f, pod, fmt.Sprintf("echo %s | base64 -d | dd of=%s %s bs=%d count=1", encoded, pathForVolMode, oflag, len))
framework.ExpectNoError(err, "Failed to write to %s", pathForVolMode)
} }
// GetSectorSize returns the sector size of the device. // GetSectorSize returns the sector size of the device.

View File

@ -105,7 +105,8 @@ func (t *VolumeModeDowngradeTest) Setup(ctx context.Context, f *framework.Framew
framework.ExpectNoError(err) framework.ExpectNoError(err)
ginkgo.By("Checking if PV exists as expected volume mode") ginkgo.By("Checking if PV exists as expected volume mode")
e2evolume.CheckVolumeModeOfPath(ctx, f, t.pod, block, devicePath) err = e2evolume.CheckVolumeModeOfPath(ctx, f, t.pod, block, devicePath)
framework.ExpectNoError(err)
ginkgo.By("Checking if read/write to PV works properly") ginkgo.By("Checking if read/write to PV works properly")
storageutils.CheckReadWriteToPath(ctx, f, t.pod, block, devicePath) storageutils.CheckReadWriteToPath(ctx, f, t.pod, block, devicePath)
@ -118,7 +119,8 @@ func (t *VolumeModeDowngradeTest) Test(ctx context.Context, f *framework.Framewo
<-done <-done
ginkgo.By("Verifying that nothing exists at the device path in the pod") ginkgo.By("Verifying that nothing exists at the device path in the pod")
e2epod.VerifyExecInPodFail(ctx, f, t.pod, fmt.Sprintf("test -e %s", devicePath), 1) err := e2epod.VerifyExecInPodFail(ctx, f, t.pod, fmt.Sprintf("test -e %s", devicePath), 1)
framework.ExpectNoError(err)
} }
// Teardown cleans up any remaining resources. // Teardown cleans up any remaining resources.