add podman container|image exists

Add an exists subcommand to podman container and podman image that allows
users to verify the existence of a container or image by ID or name.  The return
code can be 0 (success), 1 (failed to find), or 125 (failed to work with runtime).

Issue #1845

Signed-off-by: baude <bbaude@redhat.com>
This commit is contained in:
baude
2018-11-25 16:26:39 -06:00
parent e3ece3bb90
commit 9d883d2032
11 changed files with 285 additions and 2 deletions

View File

@ -9,6 +9,7 @@ var (
attachCommand,
checkpointCommand,
cleanupCommand,
containerExistsCommand,
commitCommand,
createCommand,
diffCommand,

83
cmd/podman/exists.go Normal file
View File

@ -0,0 +1,83 @@
package main
import (
"os"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/image"
"github.com/pkg/errors"
"github.com/urfave/cli"
)
var (
imageExistsDescription = `
podman image exists
Check if an image exists in local storage
`
imageExistsCommand = cli.Command{
Name: "exists",
Usage: "Check if an image exists in local storage",
Description: imageExistsDescription,
Action: imageExistsCmd,
ArgsUsage: "IMAGE-NAME",
OnUsageError: usageErrorHandler,
}
)
var (
containerExistsDescription = `
podman container exists
Check if a container exists in local storage
`
containerExistsCommand = cli.Command{
Name: "exists",
Usage: "Check if a container exists in local storage",
Description: containerExistsDescription,
Action: containerExistsCmd,
ArgsUsage: "CONTAINER-NAME",
OnUsageError: usageErrorHandler,
}
)
func imageExistsCmd(c *cli.Context) error {
args := c.Args()
if len(args) > 1 || len(args) < 1 {
return errors.New("you may only check for the existence of one image at a time")
}
runtime, err := libpodruntime.GetRuntime(c)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
defer runtime.Shutdown(false)
if _, err := runtime.ImageRuntime().NewFromLocal(args[0]); err != nil {
if errors.Cause(err) == image.ErrNoSuchImage {
os.Exit(1)
}
return err
}
return nil
}
func containerExistsCmd(c *cli.Context) error {
args := c.Args()
if len(args) > 1 || len(args) < 1 {
return errors.New("you may only check for the existence of one container at a time")
}
runtime, err := libpodruntime.GetRuntime(c)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
}
defer runtime.Shutdown(false)
if _, err := runtime.LookupContainer(args[0]); err != nil {
if errors.Cause(err) == libpod.ErrNoSuchCtr {
os.Exit(1)
}
return err
}
return nil
}

View File

@ -9,6 +9,7 @@ var (
buildCommand,
historyCommand,
importCommand,
imageExistsCommand,
inspectCommand,
loadCommand,
lsImagesCommand,

View File

@ -2178,6 +2178,22 @@ _podman_container_runlabel() {
esac
}
_podman_container_exists() {
local options_with_args="
"
local boolean_options="
"
}
_podman_image_exists() {
local options_with_args="
"
local boolean_options="
"
}
_podman_pod_create() {
local options_with_args="
--cgroup-parent

View File

@ -0,0 +1,40 @@
% PODMAN(1) Podman Man Pages
% Brent Baude
% November 2018
# NAME
podman-container-exists- Check if a container exists in local storage
# SYNOPSIS
**podman container exists**
[**-h**|**--help**]
CONTAINER
# DESCRIPTION
**podman container exists** checks if a container exists in local storage. The **ID** or **Name**
of the container may be used as input. Podman will return an exit code
of `0` when the container is found. A `1` will be returned otherwise. An exit code of `125` indicates there
was an issue accessing the local storage.
## Examples ##
Check if an container called `webclient` exists in local storage (the container does actually exist).
```
$ sudo podman container exists webclient
$ echo $?
0
$
```
Check if an container called `webbackend` exists in local storage (the container does not actually exist).
```
$ sudo podman container exists webbackend
$ echo $?
1
$
```
## SEE ALSO
podman(1)
# HISTORY
November 2018, Originally compiled by Brent Baude (bbaude at redhat dot com)

View File

@ -20,6 +20,7 @@ The container command allows you to manage containers
| create | [podman-create(1)](podman-create.1.md) | Create a new container. |
| diff | [podman-diff(1)](podman-diff.1.md) | Inspect changes on a container or image's filesystem. |
| exec | [podman-exec(1)](podman-exec.1.md) | Execute a command in a running container. |
| exists | [podman-exists(1)](podman-container-exists.1.md) | Check if a container exists in local storage |
| export | [podman-export(1)](podman-export.1.md) | Export a container's filesystem contents as a tar archive. |
| inspect | [podman-inspect(1)](podman-inspect.1.md) | Display a container or image's configuration. |
| kill | [podman-kill(1)](podman-kill.1.md) | Kill the main process in one or more containers. |

View File

@ -0,0 +1,40 @@
% PODMAN(1) Podman Man Pages
% Brent Baude
% November 2018
# NAME
podman-image-exists- Check if an image exists in local storage
# SYNOPSIS
**podman image exists**
[**-h**|**--help**]
IMAGE
# DESCRIPTION
**podman image exists** checks if an image exists in local storage. The **ID** or **Name**
of the image may be used as input. Podman will return an exit code
of `0` when the image is found. A `1` will be returned otherwise. An exit code of `125` indicates there
was an issue accessing the local storage.
## Examples ##
Check if an image called `webclient` exists in local storage (the image does actually exist).
```
$ sudo podman image exists webclient
$ echo $?
0
$
```
Check if an image called `webbackend` exists in local storage (the image does not actually exist).
```
$ sudo podman image exists webbackend
$ echo $?
1
$
```
## SEE ALSO
podman(1)
# HISTORY
November 2018, Originally compiled by Brent Baude (bbaude at redhat dot com)

View File

@ -14,6 +14,7 @@ The image command allows you to manage images
| Command | Man Page | Description |
| -------- | ----------------------------------------- | ------------------------------------------------------------------------------ |
| build | [podman-build(1)](podman-build.1.md) | Build a container using a Dockerfile. |
| exists | [podman-exists(1)](podman-image-exists.1.md) | Check if a image exists in local storage |
| history | [podman-history(1)](podman-history.1.md) | Show the history of an image. |
| import | [podman-import(1)](podman-import.1.md) | Import a tarball and save it as a filesystem image. |
| inspect | [podman-inspect(1)](podman-inspect.1.md) | Display a image or image's configuration. |

15
libpod/image/errors.go Normal file
View File

@ -0,0 +1,15 @@
package image
import (
"errors"
)
// Copied directly from libpod errors to avoid circular imports
var (
// ErrNoSuchCtr indicates the requested container does not exist
ErrNoSuchCtr = errors.New("no such container")
// ErrNoSuchPod indicates the requested pod does not exist
ErrNoSuchPod = errors.New("no such pod")
// ErrNoSuchImage indicates the requested image does not exist
ErrNoSuchImage = errors.New("no such image")
)

View File

@ -252,7 +252,7 @@ func (i *Image) getLocalImage() (*storage.Image, error) {
// The image has a registry name in it and we made sure we looked for it locally
// with a tag. It cannot be local.
if decomposedImage.hasRegistry {
return nil, errors.Errorf("%s", imageError)
return nil, errors.Wrapf(ErrNoSuchImage, imageError)
}
@ -275,7 +275,7 @@ func (i *Image) getLocalImage() (*storage.Image, error) {
return repoImage, nil
}
return nil, errors.Wrapf(err, imageError)
return nil, errors.Wrapf(ErrNoSuchImage, err.Error())
}
// ID returns the image ID as a string

85
test/e2e/exists_test.go Normal file
View File

@ -0,0 +1,85 @@
package integration
import (
"fmt"
"os"
. "github.com/containers/libpod/test/utils"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)
var _ = Describe("Podman image|container exists", func() {
var (
tempdir string
err error
podmanTest *PodmanTestIntegration
)
BeforeEach(func() {
tempdir, err = CreateTempDirInTempDir()
if err != nil {
os.Exit(1)
}
podmanTest = PodmanTestCreate(tempdir)
podmanTest.RestoreAllArtifacts()
})
AfterEach(func() {
podmanTest.Cleanup()
f := CurrentGinkgoTestDescription()
timedResult := fmt.Sprintf("Test: %s completed in %f seconds", f.TestText, f.Duration.Seconds())
GinkgoWriter.Write([]byte(timedResult))
})
It("podman image exists in local storage by fq name", func() {
session := podmanTest.Podman([]string{"image", "exists", ALPINE})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
})
It("podman image exists in local storage by short name", func() {
session := podmanTest.Podman([]string{"image", "exists", "alpine"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
})
It("podman image does not exist in local storage", func() {
session := podmanTest.Podman([]string{"image", "exists", "alpine9999"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(1))
})
It("podman container exists in local storage by name", func() {
setup := podmanTest.RunTopContainer("foobar")
setup.WaitWithDefaultTimeout()
Expect(setup.ExitCode()).To(Equal(0))
session := podmanTest.Podman([]string{"container", "exists", "foobar"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
})
It("podman container exists in local storage by container ID", func() {
setup := podmanTest.RunTopContainer("")
setup.WaitWithDefaultTimeout()
Expect(setup.ExitCode()).To(Equal(0))
cid := setup.OutputToString()
session := podmanTest.Podman([]string{"container", "exists", cid})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
})
It("podman container exists in local storage by short container ID", func() {
setup := podmanTest.RunTopContainer("")
setup.WaitWithDefaultTimeout()
Expect(setup.ExitCode()).To(Equal(0))
cid := setup.OutputToString()[0:12]
session := podmanTest.Podman([]string{"container", "exists", cid})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(0))
})
It("podman container does not exist in local storage", func() {
session := podmanTest.Podman([]string{"container", "exists", "foobar"})
session.WaitWithDefaultTimeout()
Expect(session.ExitCode()).To(Equal(1))
})
})