mirror of
https://github.com/containers/podman.git
synced 2025-06-20 00:51:16 +08:00
Add new exit codes to rm & rmi for running containers & dependencies
This enables programs and scripts wrapping the podman command to handle 'podman rm' and 'podman rmi' failures caused by paused or running containers or due to images having other child images or dependent containers. These errors are common enough that it makes sense to have a more machine readable way of detecting them than parsing the standard error output. Signed-off-by: Ondrej Zoder <ozoder@redhat.com> Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
This commit is contained in:
@ -8,6 +8,8 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/containers/libpod/libpod/define"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -24,3 +26,14 @@ func outputError(err error) {
|
|||||||
fmt.Fprintln(os.Stderr, "Error:", err.Error())
|
fmt.Fprintln(os.Stderr, "Error:", err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setExitCode(err error) int {
|
||||||
|
cause := errors.Cause(err)
|
||||||
|
switch cause {
|
||||||
|
case define.ErrNoSuchCtr:
|
||||||
|
return 1
|
||||||
|
case define.ErrCtrStateInvalid:
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
return exitCode
|
||||||
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/containers/libpod/cmd/podman/varlink"
|
"github.com/containers/libpod/cmd/podman/varlink"
|
||||||
|
"github.com/containers/libpod/libpod/define"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
@ -43,3 +44,22 @@ func outputError(err error) {
|
|||||||
fmt.Fprintln(os.Stderr, "Error:", ne.Error())
|
fmt.Fprintln(os.Stderr, "Error:", ne.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setExitCode(err error) int {
|
||||||
|
cause := errors.Cause(err)
|
||||||
|
switch e := cause.(type) {
|
||||||
|
// For some reason golang wont let me list them with commas so listing them all.
|
||||||
|
case *iopodman.ContainerNotFound:
|
||||||
|
return 1
|
||||||
|
case *iopodman.InvalidState:
|
||||||
|
return 2
|
||||||
|
default:
|
||||||
|
switch e {
|
||||||
|
case define.ErrNoSuchCtr:
|
||||||
|
return 1
|
||||||
|
case define.ErrCtrStateInvalid:
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return exitCode
|
||||||
|
}
|
||||||
|
@ -4,7 +4,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/containers/libpod/cmd/podman/cliconfig"
|
"github.com/containers/libpod/cmd/podman/cliconfig"
|
||||||
"github.com/containers/libpod/libpod/define"
|
|
||||||
"github.com/containers/libpod/pkg/adapter"
|
"github.com/containers/libpod/pkg/adapter"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@ -65,18 +64,16 @@ func rmCmd(c *cliconfig.RmValues) error {
|
|||||||
|
|
||||||
ok, failures, err := runtime.RemoveContainers(getContext(), c)
|
ok, failures, err := runtime.RemoveContainers(getContext(), c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Cause(err) == define.ErrNoSuchCtr {
|
if len(c.InputArgs) < 2 {
|
||||||
if len(c.InputArgs) > 1 {
|
exitCode = setExitCode(err)
|
||||||
exitCode = 125
|
|
||||||
} else {
|
|
||||||
exitCode = 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(failures) > 0 {
|
if len(failures) > 0 {
|
||||||
exitCode = 125
|
for _, err := range failures {
|
||||||
|
exitCode = setExitCode(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return printCmdResults(ok, failures)
|
return printCmdResults(ok, failures)
|
||||||
|
@ -74,6 +74,7 @@ func rmiCmd(c *cliconfig.RmiValues) error {
|
|||||||
fmt.Printf("A container associated with containers/storage, i.e. via Buildah, CRI-O, etc., may be associated with this image: %-12.12s\n", img.ID())
|
fmt.Printf("A container associated with containers/storage, i.e. via Buildah, CRI-O, etc., may be associated with this image: %-12.12s\n", img.ID())
|
||||||
}
|
}
|
||||||
if !adapter.IsImageNotFound(err) {
|
if !adapter.IsImageNotFound(err) {
|
||||||
|
exitCode = 2
|
||||||
failureCnt++
|
failureCnt++
|
||||||
}
|
}
|
||||||
if lastError != nil {
|
if lastError != nil {
|
||||||
|
@ -69,7 +69,8 @@ podman rm -f --latest
|
|||||||
## Exit Status
|
## Exit Status
|
||||||
**_0_** if all specified containers removed
|
**_0_** if all specified containers removed
|
||||||
**_1_** if one of the specified containers did not exist, and no other failures
|
**_1_** if one of the specified containers did not exist, and no other failures
|
||||||
**_125_** if command fails for a reason other then an container did not exist
|
**_2_** if one of the specified containers is paused or running
|
||||||
|
**_125_** if the command fails for a reason other than container did not exist or is paused/running
|
||||||
|
|
||||||
## SEE ALSO
|
## SEE ALSO
|
||||||
podman(1), podman-image-rm(1)
|
podman(1), podman-image-rm(1)
|
||||||
|
@ -43,7 +43,8 @@ podman rmi -a -f
|
|||||||
## Exit Status
|
## Exit Status
|
||||||
**_0_** if all specified images removed
|
**_0_** if all specified images removed
|
||||||
**_1_** if one of the specified images did not exist, and no other failures
|
**_1_** if one of the specified images did not exist, and no other failures
|
||||||
**_125_** if command fails for a reason other then an image did not exist
|
**_2_** if one of the specified images has child images or is being used by a container
|
||||||
|
**_125_** if the command fails for a reason other than an image did not exist or is in use
|
||||||
|
|
||||||
## SEE ALSO
|
## SEE ALSO
|
||||||
podman(1)
|
podman(1)
|
||||||
|
@ -488,6 +488,12 @@ func (i *LibpodAPI) RemoveContainer(call iopodman.VarlinkCall, name string, forc
|
|||||||
return call.ReplyContainerNotFound(name, err.Error())
|
return call.ReplyContainerNotFound(name, err.Error())
|
||||||
}
|
}
|
||||||
if err := i.Runtime.RemoveContainer(ctx, ctr, force, removeVolumes); err != nil {
|
if err := i.Runtime.RemoveContainer(ctx, ctr, force, removeVolumes); err != nil {
|
||||||
|
if errors.Cause(err) == define.ErrNoSuchCtr {
|
||||||
|
return call.ReplyContainerExists(1)
|
||||||
|
}
|
||||||
|
if errors.Cause(err) == define.ErrCtrStateInvalid {
|
||||||
|
return call.ReplyInvalidState(ctr.ID(), err.Error())
|
||||||
|
}
|
||||||
return call.ReplyErrorOccurred(err.Error())
|
return call.ReplyErrorOccurred(err.Error())
|
||||||
}
|
}
|
||||||
return call.ReplyRemoveContainer(ctr.ID())
|
return call.ReplyRemoveContainer(ctr.ID())
|
||||||
|
@ -147,7 +147,7 @@ var _ = Describe("Podman checkpoint", func() {
|
|||||||
|
|
||||||
result = podmanTest.Podman([]string{"rm", cid})
|
result = podmanTest.Podman([]string{"rm", cid})
|
||||||
result.WaitWithDefaultTimeout()
|
result.WaitWithDefaultTimeout()
|
||||||
Expect(result.ExitCode()).To(Equal(125))
|
Expect(result.ExitCode()).To(Equal(2))
|
||||||
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
|
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
|
||||||
|
|
||||||
result = podmanTest.Podman([]string{"rm", "-f", cid})
|
result = podmanTest.Podman([]string{"rm", "-f", cid})
|
||||||
|
@ -126,7 +126,7 @@ var _ = Describe("Podman pause", func() {
|
|||||||
result = podmanTest.Podman([]string{"rm", cid})
|
result = podmanTest.Podman([]string{"rm", cid})
|
||||||
result.WaitWithDefaultTimeout()
|
result.WaitWithDefaultTimeout()
|
||||||
|
|
||||||
Expect(result.ExitCode()).To(Equal(125))
|
Expect(result.ExitCode()).To(Equal(2))
|
||||||
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
|
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
|
||||||
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring(pausedState))
|
Expect(podmanTest.GetContainerStatus()).To(ContainSubstring(pausedState))
|
||||||
|
|
||||||
@ -179,7 +179,7 @@ var _ = Describe("Podman pause", func() {
|
|||||||
|
|
||||||
result = podmanTest.Podman([]string{"rm", cid})
|
result = podmanTest.Podman([]string{"rm", cid})
|
||||||
result.WaitWithDefaultTimeout()
|
result.WaitWithDefaultTimeout()
|
||||||
Expect(result.ExitCode()).To(Equal(125))
|
Expect(result.ExitCode()).To(Equal(2))
|
||||||
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
|
Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
|
||||||
|
|
||||||
result = podmanTest.Podman([]string{"rm", "-f", cid})
|
result = podmanTest.Podman([]string{"rm", "-f", cid})
|
||||||
|
@ -49,7 +49,7 @@ var _ = Describe("Podman rm", func() {
|
|||||||
|
|
||||||
result := podmanTest.Podman([]string{"rm", cid})
|
result := podmanTest.Podman([]string{"rm", cid})
|
||||||
result.WaitWithDefaultTimeout()
|
result.WaitWithDefaultTimeout()
|
||||||
Expect(result.ExitCode()).To(Equal(125))
|
Expect(result.ExitCode()).To(Equal(2))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman rm created container", func() {
|
It("podman rm created container", func() {
|
||||||
|
@ -145,7 +145,7 @@ var _ = Describe("Podman rmi", func() {
|
|||||||
|
|
||||||
session = podmanTest.PodmanNoCache([]string{"rmi", "-f", untaggedImg})
|
session = podmanTest.PodmanNoCache([]string{"rmi", "-f", untaggedImg})
|
||||||
session.WaitWithDefaultTimeout()
|
session.WaitWithDefaultTimeout()
|
||||||
Expect(session.ExitCode()).To(Not(Equal(0)))
|
Expect(session.ExitCode()).To(Equal(2))
|
||||||
})
|
})
|
||||||
|
|
||||||
It("podman rmi image that is created from another named imaged", func() {
|
It("podman rmi image that is created from another named imaged", func() {
|
||||||
|
Reference in New Issue
Block a user