mirror of
https://github.com/containers/podman.git
synced 2025-10-20 12:43:58 +08:00
Merge pull request #25340 from giuseppe/fix-crun-error-messages
tests: adapt e2e tests new crun error messages
This commit is contained in:
@ -46,6 +46,7 @@ func ExitCode(err error) int {
|
|||||||
e := strings.ToLower(err.Error())
|
e := strings.ToLower(err.Error())
|
||||||
logrus.Debugf("ExitCode msg: %q", e)
|
logrus.Debugf("ExitCode msg: %q", e)
|
||||||
if strings.Contains(e, "not found") ||
|
if strings.Contains(e, "not found") ||
|
||||||
|
strings.Contains(e, "executable path is empty") ||
|
||||||
strings.Contains(e, "no such file") {
|
strings.Contains(e, "no such file") {
|
||||||
return ExecErrorCodeNotFound
|
return ExecErrorCodeNotFound
|
||||||
}
|
}
|
||||||
|
@ -421,19 +421,20 @@ var _ = Describe("Podman exec", func() {
|
|||||||
session := podmanTest.Podman([]string{"exec", "test1", "/etc"})
|
session := podmanTest.Podman([]string{"exec", "test1", "/etc"})
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
|
|
||||||
// crun (and, we hope, any other future runtimes)
|
|
||||||
expectedStatus := 126
|
|
||||||
expectedMessage := "open executable: Operation not permitted: OCI permission denied"
|
|
||||||
|
|
||||||
// ...but it's much more complicated under runc (#19552)
|
// ...but it's much more complicated under runc (#19552)
|
||||||
if podmanTest.OCIRuntime == "runc" {
|
if podmanTest.OCIRuntime == "runc" {
|
||||||
expectedMessage = `exec failed: unable to start container process: exec: "/etc": is a directory`
|
expectedMessage := `exec failed: unable to start container process: exec: "/etc": is a directory`
|
||||||
expectedStatus = 255
|
expectedStatus := 255
|
||||||
if IsRemote() {
|
if IsRemote() {
|
||||||
expectedStatus = 125
|
expectedStatus = 125
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Expect(session).Should(ExitWithError(expectedStatus, expectedMessage))
|
Expect(session).Should(ExitWithError(expectedStatus, expectedMessage))
|
||||||
|
} else {
|
||||||
|
// crun (and, we hope, any other future runtimes)
|
||||||
|
expectedStatus := 126
|
||||||
|
expectedMessage := ".*(open executable|the path `/etc` is not a regular file): Operation not permitted: OCI permission denied.*"
|
||||||
|
Expect(session).Should(ExitWithErrorRegex(expectedStatus, expectedMessage))
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman exec command not found", func() {
|
It("podman exec command not found", func() {
|
||||||
|
@ -18,7 +18,7 @@ CMD []
|
|||||||
podmanTest.BuildImage(dockerfile, "foobar.com/entrypoint:latest", "false")
|
podmanTest.BuildImage(dockerfile, "foobar.com/entrypoint:latest", "false")
|
||||||
session := podmanTest.Podman([]string{"run", "foobar.com/entrypoint:latest"})
|
session := podmanTest.Podman([]string{"run", "foobar.com/entrypoint:latest"})
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
Expect(session).Should(ExitWithError(126, "open executable: Operation not permitted: OCI permission denied"))
|
Expect(session).Should(ExitWithErrorRegex(126, ".*(open executable|executable path is empty): Operation not permitted: OCI permission denied.*"))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman run entrypoint == [\"\"]", func() {
|
It("podman run entrypoint == [\"\"]", func() {
|
||||||
|
@ -22,7 +22,7 @@ var _ = Describe("Podman run exit", func() {
|
|||||||
It("podman run exit ExecErrorCodeCannotInvoke", func() {
|
It("podman run exit ExecErrorCodeCannotInvoke", func() {
|
||||||
result := podmanTest.Podman([]string{"run", ALPINE, "/etc"})
|
result := podmanTest.Podman([]string{"run", ALPINE, "/etc"})
|
||||||
result.WaitWithDefaultTimeout()
|
result.WaitWithDefaultTimeout()
|
||||||
Expect(result).Should(ExitWithError(define.ExecErrorCodeCannotInvoke, "open executable: Operation not permitted: OCI permission denied"))
|
Expect(result).Should(ExitWithErrorRegex(define.ExecErrorCodeCannotInvoke, ".*(open executable|the path `/etc` is not a regular file): Operation not permitted: OCI permission denied.*"))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman run exit ExecErrorCodeNotFound", func() {
|
It("podman run exit ExecErrorCodeNotFound", func() {
|
||||||
|
@ -1135,12 +1135,6 @@ echo -n madeit-$teststring >$tmpfile
|
|||||||
Expect(session).Should(ExitWithError(125, `invalid stream "asdfasdf" for --attach - must be one of stdin, stdout, or stderr: invalid argument`))
|
Expect(session).Should(ExitWithError(125, `invalid stream "asdfasdf" for --attach - must be one of stdin, stdout, or stderr: invalid argument`))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman run exit code on failure to exec", func() {
|
|
||||||
session := podmanTest.Podman([]string{"run", ALPINE, "/etc"})
|
|
||||||
session.WaitWithDefaultTimeout()
|
|
||||||
Expect(session).Should(ExitWithError(126, "open executable: Operation not permitted: OCI permission denied"))
|
|
||||||
})
|
|
||||||
|
|
||||||
It("podman run error on exec", func() {
|
It("podman run error on exec", func() {
|
||||||
session := podmanTest.Podman([]string{"run", ALPINE, "sh", "-c", "exit 100"})
|
session := podmanTest.Podman([]string{"run", ALPINE, "sh", "-c", "exit 100"})
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
|
@ -10,7 +10,7 @@ load helpers.network
|
|||||||
err_no_such_cmd="Error:.*/no/such/command.*[Nn]o such file or directory"
|
err_no_such_cmd="Error:.*/no/such/command.*[Nn]o such file or directory"
|
||||||
# runc: RHEL8 on 2023-07-17: "is a directory".
|
# runc: RHEL8 on 2023-07-17: "is a directory".
|
||||||
# Everything else (crun; runc on debian): "permission denied"
|
# Everything else (crun; runc on debian): "permission denied"
|
||||||
err_no_exec_dir="Error:.*exec.*\\\(permission denied\\\|is a directory\\\)"
|
err_no_exec_dir="Error:.*\\\(exec.*\\\(permission denied\\\|is a directory\\\)\\\|is not a regular file\\\)"
|
||||||
|
|
||||||
tests="
|
tests="
|
||||||
true | 0 |
|
true | 0 |
|
||||||
@ -1657,14 +1657,14 @@ search | $IMAGE |
|
|||||||
# runc and crun emit different diagnostics
|
# runc and crun emit different diagnostics
|
||||||
runtime=$(podman_runtime)
|
runtime=$(podman_runtime)
|
||||||
case "$runtime" in
|
case "$runtime" in
|
||||||
crun) expect='crun: executable file `` not found in $PATH: No such file or directory: OCI runtime attempted to invoke a command that was not found' ;;
|
crun) expect='\(executable file `` not found in $PATH: No such file or directory: OCI runtime attempted to invoke a command that was not found\|executable path is empty\)' ;;
|
||||||
runc) expect='runc: runc create failed: unable to start container process: exec: "": executable file not found in $PATH: OCI runtime attempted to invoke a command that was not found' ;;
|
runc) expect='runc: runc create failed: unable to start container process: exec: "": executable file not found in $PATH: OCI runtime attempted to invoke a command that was not found' ;;
|
||||||
*) skip "Unknown runtime '$runtime'" ;;
|
*) skip "Unknown runtime '$runtime'" ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# The '.*' in the error below is for dealing with podman-remote, which
|
# The '.*' in the error below is for dealing with podman-remote, which
|
||||||
# includes "error preparing container <sha> for attach" in output.
|
# includes "error preparing container <sha> for attach" in output.
|
||||||
is "$output" "Error.*: $expect" "podman emits useful diagnostic when no entrypoint is set"
|
is "$output" "Error.* $expect" "podman emits useful diagnostic when no entrypoint is set"
|
||||||
}
|
}
|
||||||
|
|
||||||
# bats test_tags=ci:parallel
|
# bats test_tags=ci:parallel
|
||||||
|
@ -3,6 +3,7 @@ package utils
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/onsi/gomega/format"
|
"github.com/onsi/gomega/format"
|
||||||
@ -20,6 +21,7 @@ type ExitMatcher struct {
|
|||||||
ExpectedExitCode int
|
ExpectedExitCode int
|
||||||
ExitCode int
|
ExitCode int
|
||||||
ExpectedStderr string
|
ExpectedStderr string
|
||||||
|
ExpectedStderrRegex string
|
||||||
msg string
|
msg string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,6 +31,12 @@ func ExitWithError(expectExitCode int, expectStderr string) *ExitMatcher {
|
|||||||
return &ExitMatcher{ExpectedExitCode: expectExitCode, ExpectedStderr: expectStderr}
|
return &ExitMatcher{ExpectedExitCode: expectExitCode, ExpectedStderr: expectStderr}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ExitWithErrorRegex checks both exit code and the stderr regex, fails if either does not match
|
||||||
|
// Modeled after the gomega Exit() matcher and also operates on sessions.
|
||||||
|
func ExitWithErrorRegex(expectExitCode int, expectStderrRegex string) *ExitMatcher {
|
||||||
|
return &ExitMatcher{ExpectedExitCode: expectExitCode, ExpectedStderrRegex: expectStderrRegex}
|
||||||
|
}
|
||||||
|
|
||||||
// Match follows gexec.Matcher interface.
|
// Match follows gexec.Matcher interface.
|
||||||
func (matcher *ExitMatcher) Match(actual interface{}) (success bool, err error) {
|
func (matcher *ExitMatcher) Match(actual interface{}) (success bool, err error) {
|
||||||
session, ok := actual.(podmanSession)
|
session, ok := actual.(podmanSession)
|
||||||
@ -49,12 +57,23 @@ func (matcher *ExitMatcher) Match(actual interface{}) (success bool, err error)
|
|||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if matcher.ExpectedStderr != "" {
|
switch {
|
||||||
|
case matcher.ExpectedStderrRegex != "":
|
||||||
|
matched, err := regexp.MatchString(matcher.ExpectedStderrRegex, session.ErrorToString())
|
||||||
|
if err != nil {
|
||||||
|
matcher.msg = fmt.Sprintf("Invalid regex pattern: %s", err)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if !matched {
|
||||||
|
matcher.msg = fmt.Sprintf("Command exited %d as expected, but stderr did not match regex '%s'", matcher.ExitCode, matcher.ExpectedStderrRegex)
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
case matcher.ExpectedStderr != "":
|
||||||
if !strings.Contains(session.ErrorToString(), matcher.ExpectedStderr) {
|
if !strings.Contains(session.ErrorToString(), matcher.ExpectedStderr) {
|
||||||
matcher.msg = fmt.Sprintf("Command exited %d as expected, but did not emit '%s'", matcher.ExitCode, matcher.ExpectedStderr)
|
matcher.msg = fmt.Sprintf("Command exited %d as expected, but did not emit '%s'", matcher.ExitCode, matcher.ExpectedStderr)
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
} else {
|
default:
|
||||||
if session.ErrorToString() != "" {
|
if session.ErrorToString() != "" {
|
||||||
matcher.msg = "Command exited with expected exit status, but emitted unwanted stderr"
|
matcher.msg = "Command exited with expected exit status, but emitted unwanted stderr"
|
||||||
return false, nil
|
return false, nil
|
||||||
|
Reference in New Issue
Block a user