summaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'cmd')
-rw-r--r--cmd/podman/cliconfig/config.go14
-rw-r--r--cmd/podman/cliconfig/create.go4
-rw-r--r--cmd/podman/commands.go12
-rw-r--r--cmd/podman/commands_remoteclient.go10
-rw-r--r--cmd/podman/commit.go4
-rw-r--r--cmd/podman/common.go2
-rw-r--r--cmd/podman/cp.go257
-rw-r--r--cmd/podman/create.go4
-rw-r--r--cmd/podman/exists.go6
-rw-r--r--cmd/podman/info.go2
-rw-r--r--cmd/podman/inspect.go4
-rw-r--r--cmd/podman/libpodruntime/runtime.go2
-rw-r--r--cmd/podman/login.go27
-rw-r--r--cmd/podman/pod_inspect.go2
-rw-r--r--cmd/podman/pod_rm.go4
-rw-r--r--cmd/podman/pull.go71
-rw-r--r--cmd/podman/varlink/io.podman.varlink17
-rw-r--r--cmd/podman/volume.go10
-rw-r--r--cmd/podman/volume_prune.go29
19 files changed, 407 insertions, 74 deletions
diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go
index f38bcaa62..9c9be3618 100644
--- a/cmd/podman/cliconfig/config.go
+++ b/cmd/podman/cliconfig/config.go
@@ -177,12 +177,13 @@ type LoadValues struct {
type LoginValues struct {
PodmanCommand
- Password string
- Username string
- Authfile string
- CertDir string
- GetLogin bool
- TlsVerify bool
+ Password string
+ StdinPassword bool
+ Username string
+ Authfile string
+ CertDir string
+ GetLogin bool
+ TlsVerify bool
}
type LogoutValues struct {
@@ -339,6 +340,7 @@ type PsValues struct {
type PullValues struct {
PodmanCommand
+ AllTags bool
Authfile string
CertDir string
Creds string
diff --git a/cmd/podman/cliconfig/create.go b/cmd/podman/cliconfig/create.go
index 68ba4d857..b5ca1be9c 100644
--- a/cmd/podman/cliconfig/create.go
+++ b/cmd/podman/cliconfig/create.go
@@ -20,3 +20,7 @@ type BuildValues struct {
*buildahcli.NameSpaceResults
*buildahcli.LayerResults
}
+
+type CpValues struct {
+ PodmanCommand
+}
diff --git a/cmd/podman/commands.go b/cmd/podman/commands.go
index baa49d2af..fa3839a53 100644
--- a/cmd/podman/commands.go
+++ b/cmd/podman/commands.go
@@ -112,18 +112,6 @@ func getPodSubCommands() []*cobra.Command {
}
}
-// Commands that the local client implements
-func getVolumeSubCommands() []*cobra.Command {
- return []*cobra.Command{
- _volumeCreateCommand,
- _volumeLsCommand,
- _volumeRmCommand,
- _volumeInspectCommand,
- _volumePruneCommand,
- }
-}
-
-// Commands that the local client implements
func getGenerateSubCommands() []*cobra.Command {
return []*cobra.Command{
_containerKubeCommand,
diff --git a/cmd/podman/commands_remoteclient.go b/cmd/podman/commands_remoteclient.go
index 7bdba1c19..ba0a4d47e 100644
--- a/cmd/podman/commands_remoteclient.go
+++ b/cmd/podman/commands_remoteclient.go
@@ -32,16 +32,6 @@ func getPodSubCommands() []*cobra.Command {
}
// commands that only the remoteclient implements
-func getVolumeSubCommands() []*cobra.Command {
- return []*cobra.Command{
- _volumeCreateCommand,
- _volumeRmCommand,
- _volumeLsCommand,
- _volumeInspectCommand,
- }
-}
-
-// commands that only the remoteclient implements
func getGenerateSubCommands() []*cobra.Command {
return []*cobra.Command{}
}
diff --git a/cmd/podman/commit.go b/cmd/podman/commit.go
index dc53e68d1..d8ced0e36 100644
--- a/cmd/podman/commit.go
+++ b/cmd/podman/commit.go
@@ -33,7 +33,9 @@ var (
commitCommand.GlobalFlags = MainGlobalOpts
return commitCmd(&commitCommand)
},
- Example: "CONTAINER [REPOSITORY[:TAG]]",
+ Example: `podman commit -q --message "committing container to image" reverent_golick image-commited
+ podman commit -q --author "firstName lastName" reverent_golick image-commited
+ podman commit -q --pause=false containerID image-commited`,
}
)
diff --git a/cmd/podman/common.go b/cmd/podman/common.go
index 417e938b7..ec755c4a8 100644
--- a/cmd/podman/common.go
+++ b/cmd/podman/common.go
@@ -514,7 +514,7 @@ Aliases:
{{.NameAndAliases}}{{end}}{{if .HasExample}}
Examples:
-{{.Example}}{{end}}{{if .HasAvailableSubCommands}}
+ {{.Example}}{{end}}{{if .HasAvailableSubCommands}}
Available Commands:{{range .Commands}}{{if (or .IsAvailableCommand (eq .Name "help"))}}
{{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}
diff --git a/cmd/podman/cp.go b/cmd/podman/cp.go
new file mode 100644
index 000000000..89114fda1
--- /dev/null
+++ b/cmd/podman/cp.go
@@ -0,0 +1,257 @@
+package main
+
+import (
+ "os"
+ "path/filepath"
+ "strings"
+
+ "github.com/containers/buildah/util"
+ "github.com/containers/libpod/cmd/podman/cliconfig"
+ "github.com/containers/libpod/cmd/podman/libpodruntime"
+ "github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/pkg/chrootuser"
+ "github.com/containers/storage"
+ "github.com/containers/storage/pkg/archive"
+ "github.com/containers/storage/pkg/chrootarchive"
+ "github.com/containers/storage/pkg/idtools"
+ digest "github.com/opencontainers/go-digest"
+ specs "github.com/opencontainers/runtime-spec/specs-go"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+ "github.com/spf13/cobra"
+)
+
+var (
+ cpCommand cliconfig.CpValues
+
+ cpDescription = "Copy files/folders between a container and the local filesystem"
+ _cpCommand = &cobra.Command{
+ Use: "cp",
+ Short: "Copy files/folders between a container and the local filesystem",
+ Long: cpDescription,
+ RunE: func(cmd *cobra.Command, args []string) error {
+ cpCommand.InputArgs = args
+ cpCommand.GlobalFlags = MainGlobalOpts
+ return cpCmd(&cpCommand)
+ },
+ Example: "[CONTAINER:]SRC_PATH [CONTAINER:]DEST_PATH",
+ }
+)
+
+func init() {
+ cpCommand.Command = _cpCommand
+ rootCmd.AddCommand(cpCommand.Command)
+}
+
+func cpCmd(c *cliconfig.CpValues) error {
+ args := c.InputArgs
+ if len(args) != 2 {
+ return errors.Errorf("you must provide a source path and a destination path")
+ }
+
+ runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
+ if err != nil {
+ return errors.Wrapf(err, "could not get runtime")
+ }
+ defer runtime.Shutdown(false)
+
+ return copyBetweenHostAndContainer(runtime, args[0], args[1])
+}
+
+func copyBetweenHostAndContainer(runtime *libpod.Runtime, src string, dest string) error {
+
+ srcCtr, srcPath := parsePath(runtime, src)
+ destCtr, destPath := parsePath(runtime, dest)
+
+ if (srcCtr == nil && destCtr == nil) || (srcCtr != nil && destCtr != nil) {
+ return errors.Errorf("invalid arguments %s, %s you must use just one container", src, dest)
+ }
+
+ if len(srcPath) == 0 || len(destPath) == 0 {
+ return errors.Errorf("invalid arguments %s, %s you must specify paths", src, dest)
+ }
+ ctr := srcCtr
+ isFromHostToCtr := (ctr == nil)
+ if isFromHostToCtr {
+ ctr = destCtr
+ }
+
+ mountPoint, err := ctr.Mount()
+ if err != nil {
+ return err
+ }
+ defer ctr.Unmount(false)
+ user, err := getUser(mountPoint, ctr.User())
+ if err != nil {
+ return err
+ }
+ idMappingOpts, err := ctr.IDMappings()
+ if err != nil {
+ return errors.Wrapf(err, "error getting IDMappingOptions")
+ }
+ containerOwner := idtools.IDPair{UID: int(user.UID), GID: int(user.GID)}
+ hostUID, hostGID, err := util.GetHostIDs(convertIDMap(idMappingOpts.UIDMap), convertIDMap(idMappingOpts.GIDMap), user.UID, user.GID)
+ if err != nil {
+ return err
+ }
+
+ hostOwner := idtools.IDPair{UID: int(hostUID), GID: int(hostGID)}
+
+ var glob []string
+ if isFromHostToCtr {
+ if filepath.IsAbs(destPath) {
+ destPath = filepath.Join(mountPoint, destPath)
+
+ } else {
+ if err = idtools.MkdirAllAndChownNew(filepath.Join(mountPoint, ctr.WorkingDir()), 0755, hostOwner); err != nil {
+ return errors.Wrapf(err, "error creating directory %q", destPath)
+ }
+ destPath = filepath.Join(mountPoint, ctr.WorkingDir(), destPath)
+ }
+ } else {
+ if filepath.IsAbs(srcPath) {
+ srcPath = filepath.Join(mountPoint, srcPath)
+ } else {
+ srcPath = filepath.Join(mountPoint, ctr.WorkingDir(), srcPath)
+ }
+ }
+ glob, err = filepath.Glob(srcPath)
+ if err != nil {
+ return errors.Wrapf(err, "invalid glob %q", srcPath)
+ }
+ if len(glob) == 0 {
+ glob = append(glob, srcPath)
+ }
+ if !filepath.IsAbs(destPath) {
+ dir, err := os.Getwd()
+ if err != nil {
+ return errors.Wrapf(err, "err getting current working directory")
+ }
+ destPath = filepath.Join(dir, destPath)
+ }
+
+ var lastError error
+ for _, src := range glob {
+ err := copy(src, destPath, dest, idMappingOpts, &containerOwner)
+ if lastError != nil {
+ logrus.Error(lastError)
+ }
+ lastError = err
+ }
+ return lastError
+}
+
+func getUser(mountPoint string, userspec string) (specs.User, error) {
+ uid, gid, err := chrootuser.GetUser(mountPoint, userspec)
+ u := specs.User{
+ UID: uid,
+ GID: gid,
+ Username: userspec,
+ }
+ if !strings.Contains(userspec, ":") {
+ groups, err2 := chrootuser.GetAdditionalGroupsForUser(mountPoint, uint64(u.UID))
+ if err2 != nil {
+ if errors.Cause(err2) != chrootuser.ErrNoSuchUser && err == nil {
+ err = err2
+ }
+ } else {
+ u.AdditionalGids = groups
+ }
+
+ }
+ return u, err
+}
+
+func parsePath(runtime *libpod.Runtime, path string) (*libpod.Container, string) {
+ pathArr := strings.SplitN(path, ":", 2)
+ if len(pathArr) == 2 {
+ ctr, err := runtime.LookupContainer(pathArr[0])
+ if err == nil {
+ return ctr, pathArr[1]
+ }
+ }
+ return nil, path
+}
+
+func getPathInfo(path string) (string, os.FileInfo, error) {
+ path, err := filepath.EvalSymlinks(path)
+ if err != nil {
+ return "", nil, errors.Wrapf(err, "error evaluating symlinks %q", path)
+ }
+ srcfi, err := os.Stat(path)
+ if err != nil {
+ return "", nil, errors.Wrapf(err, "error reading path %q", path)
+ }
+ return path, srcfi, nil
+}
+
+func copy(src, destPath, dest string, idMappingOpts storage.IDMappingOptions, chownOpts *idtools.IDPair) error {
+ srcPath, err := filepath.EvalSymlinks(src)
+ if err != nil {
+ return errors.Wrapf(err, "error evaluating symlinks %q", srcPath)
+ }
+
+ srcPath, srcfi, err := getPathInfo(srcPath)
+ if err != nil {
+ return err
+ }
+ destdir := destPath
+ if !srcfi.IsDir() && !strings.HasSuffix(dest, string(os.PathSeparator)) {
+ destdir = filepath.Dir(destPath)
+ }
+ if err = os.MkdirAll(destdir, 0755); err != nil {
+ return errors.Wrapf(err, "error creating directory %q", destdir)
+ }
+
+ // return functions for copying items
+ copyFileWithTar := chrootarchive.CopyFileWithTarAndChown(chownOpts, digest.Canonical.Digester().Hash(), idMappingOpts.UIDMap, idMappingOpts.GIDMap)
+ copyWithTar := chrootarchive.CopyWithTarAndChown(chownOpts, digest.Canonical.Digester().Hash(), idMappingOpts.UIDMap, idMappingOpts.GIDMap)
+ untarPath := chrootarchive.UntarPathAndChown(chownOpts, digest.Canonical.Digester().Hash(), idMappingOpts.UIDMap, idMappingOpts.GIDMap)
+
+ if srcfi.IsDir() {
+
+ logrus.Debugf("copying %q to %q", srcPath+string(os.PathSeparator)+"*", dest+string(os.PathSeparator)+"*")
+ if err = copyWithTar(srcPath, destPath); err != nil {
+ return errors.Wrapf(err, "error copying %q to %q", srcPath, dest)
+ }
+ return nil
+ }
+ if !archive.IsArchivePath(srcPath) {
+ // This srcPath is a file, and either it's not an
+ // archive, or we don't care whether or not it's an
+ // archive.
+ destfi, err := os.Stat(destPath)
+ if err != nil {
+ if !os.IsNotExist(err) {
+ return errors.Wrapf(err, "failed to get stat of dest path %s", destPath)
+ }
+ }
+ if destfi != nil && destfi.IsDir() {
+ destPath = filepath.Join(destPath, filepath.Base(srcPath))
+ }
+ // Copy the file, preserving attributes.
+ logrus.Debugf("copying %q to %q", srcPath, destPath)
+ if err = copyFileWithTar(srcPath, destPath); err != nil {
+ return errors.Wrapf(err, "error copying %q to %q", srcPath, destPath)
+ }
+ return nil
+ }
+ // We're extracting an archive into the destination directory.
+ logrus.Debugf("extracting contents of %q into %q", srcPath, destPath)
+ if err = untarPath(srcPath, destPath); err != nil {
+ return errors.Wrapf(err, "error extracting %q into %q", srcPath, destPath)
+ }
+ return nil
+}
+
+func convertIDMap(idMaps []idtools.IDMap) (convertedIDMap []specs.LinuxIDMapping) {
+ for _, idmap := range idMaps {
+ tempIDMap := specs.LinuxIDMapping{
+ ContainerID: uint32(idmap.ContainerID),
+ HostID: uint32(idmap.HostID),
+ Size: uint32(idmap.Size),
+ }
+ convertedIDMap = append(convertedIDMap, tempIDMap)
+ }
+ return convertedIDMap
+}
diff --git a/cmd/podman/create.go b/cmd/podman/create.go
index adfae25c1..e7efe7502 100644
--- a/cmd/podman/create.go
+++ b/cmd/podman/create.go
@@ -49,7 +49,9 @@ var (
createCommand.GlobalFlags = MainGlobalOpts
return createCmd(&createCommand)
},
- Example: "IMAGE [COMMAND [ARG...]]",
+ Example: `podman create alpine ls
+ podman create --annotation HELLO=WORLD alpine ls
+ podman create -t -i --name myctr alpine ls`,
}
defaultEnvVariables = map[string]string{
diff --git a/cmd/podman/exists.go b/cmd/podman/exists.go
index 15ddaec06..7645bb716 100644
--- a/cmd/podman/exists.go
+++ b/cmd/podman/exists.go
@@ -41,7 +41,7 @@ var (
imageExistsCommand.GlobalFlags = MainGlobalOpts
return imageExistsCmd(&imageExistsCommand)
},
- Example: "IMAGE-NAME",
+ Example: `podman image exists imageID`,
}
_containerExistsCommand = &cobra.Command{
@@ -54,7 +54,7 @@ var (
return containerExistsCmd(&containerExistsCommand)
},
- Example: "CONTAINER-NAME",
+ Example: `podman container exists containerID`,
}
_podExistsCommand = &cobra.Command{
@@ -66,7 +66,7 @@ var (
podExistsCommand.GlobalFlags = MainGlobalOpts
return podExistsCmd(&podExistsCommand)
},
- Example: "POD-NAME",
+ Example: `podman pod exists podID`,
}
)
diff --git a/cmd/podman/info.go b/cmd/podman/info.go
index d60b8f84f..06dbbd748 100644
--- a/cmd/podman/info.go
+++ b/cmd/podman/info.go
@@ -26,7 +26,7 @@ var (
infoCommand.GlobalFlags = MainGlobalOpts
return infoCmd(&infoCommand)
},
- Example: "",
+ Example: `podman info`,
}
)
diff --git a/cmd/podman/inspect.go b/cmd/podman/inspect.go
index a29eb790e..a1f3ef81f 100644
--- a/cmd/podman/inspect.go
+++ b/cmd/podman/inspect.go
@@ -34,7 +34,9 @@ var (
inspectCommand.GlobalFlags = MainGlobalOpts
return inspectCmd(&inspectCommand)
},
- Example: "CONTAINER-OR-IMAGE [CONTAINER-OR-IMAGE]...",
+ Example: `podman inspect alpine
+ podman inspect --format "imageId: {{.Id}} size: {{.Size}}" alpine
+ podman inspect --format "image: {{.ImageName}} driver: {{.Driver}}" myctr`,
}
)
diff --git a/cmd/podman/libpodruntime/runtime.go b/cmd/podman/libpodruntime/runtime.go
index 60acd1f5b..0b9568b8d 100644
--- a/cmd/podman/libpodruntime/runtime.go
+++ b/cmd/podman/libpodruntime/runtime.go
@@ -48,7 +48,7 @@ func GetRuntime(c *cliconfig.PodmanCommand) (*libpod.Runtime, error) {
if c.Flags().Changed("storage-driver") {
storageOpts.GraphDriverName = c.GlobalFlags.StorageDriver
}
- if c.Flags().Changed("storage-opt") {
+ if len(c.GlobalFlags.StorageOpts) > 0 {
storageOpts.GraphDriverOptions = c.GlobalFlags.StorageOpts
}
diff --git a/cmd/podman/login.go b/cmd/podman/login.go
index 0bd58ff78..3eacab54a 100644
--- a/cmd/podman/login.go
+++ b/cmd/podman/login.go
@@ -29,7 +29,9 @@ var (
loginCommand.GlobalFlags = MainGlobalOpts
return loginCmd(&loginCommand)
},
- Example: "REGISTRY",
+ Example: `podman login -u testuser -p testpassword localhost:5000
+ podman login --authfile authdir/myauths.json quay.io
+ podman login -u testuser -p testpassword localhost:5000`,
}
)
@@ -44,6 +46,7 @@ func init() {
flags.StringVarP(&loginCommand.Password, "password", "p", "", "Password for registry")
flags.BoolVar(&loginCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries (default: true)")
flags.StringVarP(&loginCommand.Username, "username", "u", "", "Username for registry")
+ flags.BoolVar(&loginCommand.StdinPassword, "password-stdin", false, "Take the password from stdin")
}
@@ -90,8 +93,26 @@ func loginCmd(c *cliconfig.LoginValues) error {
}
ctx := getContext()
+
+ password := c.Password
+
+ if c.Flag("password-stdin").Changed {
+ var stdinPasswordStrBuilder strings.Builder
+ if c.Password != "" {
+ return errors.Errorf("Can't specify both --password-stdin and --password")
+ }
+ if c.Username == "" {
+ return errors.Errorf("Must provide --username with --password-stdin")
+ }
+ scanner := bufio.NewScanner(os.Stdin)
+ for scanner.Scan() {
+ fmt.Fprint(&stdinPasswordStrBuilder, scanner.Text())
+ }
+ password = stdinPasswordStrBuilder.String()
+ }
+
// If no username and no password is specified, try to use existing ones.
- if c.Username == "" && c.Password == "" {
+ if c.Username == "" && password == "" {
fmt.Println("Authenticating with existing credentials...")
if err := docker.CheckAuth(ctx, sc, userFromAuthFile, passFromAuthFile, server); err == nil {
fmt.Println("Existing credentials are valid. Already logged in to", server)
@@ -100,7 +121,7 @@ func loginCmd(c *cliconfig.LoginValues) error {
fmt.Println("Existing credentials are invalid, please enter valid username and password")
}
- username, password, err := getUserAndPass(c.Username, c.Password, userFromAuthFile)
+ username, password, err := getUserAndPass(c.Username, password, userFromAuthFile)
if err != nil {
return errors.Wrapf(err, "error getting username and password")
}
diff --git a/cmd/podman/pod_inspect.go b/cmd/podman/pod_inspect.go
index a0b691642..58b15328e 100644
--- a/cmd/podman/pod_inspect.go
+++ b/cmd/podman/pod_inspect.go
@@ -23,7 +23,7 @@ var (
podInspectCommand.GlobalFlags = MainGlobalOpts
return podInspectCmd(&podInspectCommand)
},
- Example: "[POD_NAME_OR_ID]",
+ Example: `podman pod inspect podID`,
}
)
diff --git a/cmd/podman/pod_rm.go b/cmd/podman/pod_rm.go
index 389f44a20..54cee2a50 100644
--- a/cmd/podman/pod_rm.go
+++ b/cmd/podman/pod_rm.go
@@ -26,7 +26,9 @@ If --force is specified, all containers will be stopped, then removed.
podRmCommand.GlobalFlags = MainGlobalOpts
return podRmCmd(&podRmCommand)
},
- Example: "[POD ...]",
+ Example: `podman pod rm mywebserverpod
+ podman pod rm -f 860a4b23
+ podman pod rm -f -a`,
}
)
diff --git a/cmd/podman/pull.go b/cmd/podman/pull.go
index 6d9d1a278..6e060d6f5 100644
--- a/cmd/podman/pull.go
+++ b/cmd/podman/pull.go
@@ -6,11 +6,13 @@ import (
"os"
"strings"
+ "github.com/containers/image/docker"
dockerarchive "github.com/containers/image/docker/archive"
"github.com/containers/image/transports/alltransports"
"github.com/containers/image/types"
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/libpod/adapter"
+ "github.com/containers/libpod/libpod/common"
image2 "github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/util"
"github.com/pkg/errors"
@@ -42,6 +44,7 @@ func init() {
pullCommand.Command = _pullCommand
pullCommand.SetUsageTemplate(UsageTemplate())
flags := pullCommand.Flags()
+ flags.BoolVar(&pullCommand.AllTags, "all-tags", false, "All tagged images inthe repository will be pulled")
flags.StringVar(&pullCommand.Authfile, "authfile", "", "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override")
flags.StringVar(&pullCommand.CertDir, "cert-dir", "", "`Pathname` of a directory containing TLS certificates and keys")
flags.StringVar(&pullCommand.Creds, "creds", "", "`Credentials` (USERNAME:PASSWORD) to use for authenticating to a registry")
@@ -69,6 +72,15 @@ func pullCmd(c *cliconfig.PullValues) error {
logrus.Errorf("too many arguments. Requires exactly 1")
return nil
}
+
+ arr := strings.SplitN(args[0], ":", 2)
+ if len(arr) == 2 {
+ if c.Bool("all-tags") {
+ logrus.Errorf("tag can't be used with --all-tags")
+ return nil
+ }
+ }
+ ctx := getContext()
image := args[0]
var registryCreds *types.DockerAuthConfig
@@ -83,7 +95,6 @@ func pullCmd(c *cliconfig.PullValues) error {
var (
writer io.Writer
- imgID string
)
if !c.Quiet {
writer = os.Stderr
@@ -107,18 +118,58 @@ func pullCmd(c *cliconfig.PullValues) error {
if err != nil {
return errors.Wrapf(err, "error pulling image from %q", image)
}
- imgID = newImage[0].ID()
+ fmt.Println(newImage[0].ID())
} else {
- authfile := getAuthFile(c.Authfile)
- newImage, err := runtime.New(getContext(), image, c.SignaturePolicy, authfile, writer, &dockerRegistryOptions, image2.SigningOptions{}, true, nil)
+ authfile := getAuthFile(c.String("authfile"))
+ spec := image
+ systemContext := common.GetSystemContext("", authfile, false)
+ srcRef, err := alltransports.ParseImageName(spec)
if err != nil {
+ dockerTransport := "docker://"
+ logrus.Debugf("error parsing image name %q, trying with transport %q: %v", spec, dockerTransport, err)
+ spec = dockerTransport + spec
+ srcRef2, err2 := alltransports.ParseImageName(spec)
+ if err2 != nil {
+ return errors.Wrapf(err2, "error parsing image name %q", image)
+ }
+ srcRef = srcRef2
+ }
+ var names []string
+ if c.Bool("all-tags") {
+ if srcRef.DockerReference() == nil {
+ return errors.New("Non-docker transport is currently not supported")
+ }
+ tags, err := docker.GetRepositoryTags(ctx, systemContext, srcRef)
+ if err != nil {
+ return errors.Wrapf(err, "error getting repository tags")
+ }
+ for _, tag := range tags {
+ name := spec + ":" + tag
+ names = append(names, name)
+ }
+ } else {
+ names = append(names, spec)
+ }
+ var foundIDs []string
+ foundImage := true
+ for _, name := range names {
+ newImage, err := runtime.New(getContext(), name, c.String("signature-policy"), authfile, writer, &dockerRegistryOptions, image2.SigningOptions{}, true, nil)
+ if err != nil {
+ println(errors.Wrapf(err, "error pulling image %q", name))
+ foundImage = false
+ continue
+ }
+ foundIDs = append(foundIDs, newImage.ID())
+ }
+ if len(names) == 1 && !foundImage {
return errors.Wrapf(err, "error pulling image %q", image)
}
- imgID = newImage.ID()
- }
-
- // Intentionally choosing to ignore if there is an error because
- // outputting the image ID is a NTH and not integral to the pull
- fmt.Println(imgID)
+ if len(names) > 1 {
+ fmt.Println("Pulled Images:")
+ }
+ for _, id := range foundIDs {
+ fmt.Println(id)
+ }
+ } // end else if strings.HasPrefix(image, dockerarchive.Transport.Name()+":")
return nil
}
diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink
index 3b7a11fc3..697d9ed90 100644
--- a/cmd/podman/varlink/io.podman.varlink
+++ b/cmd/podman/varlink/io.podman.varlink
@@ -412,7 +412,7 @@ type Runlabel(
name: string,
pull: bool,
signaturePolicyPath: string,
- tlsVerify: bool,
+ tlsVerify: ?bool,
label: string,
extraArgs: []string,
opts: [string]string
@@ -658,7 +658,7 @@ method HistoryImage(name: string) -> (history: []ImageHistory)
# and a boolean as to whether tls-verify should be used (with false disabling TLS, not affecting the default behavior).
# It will return an [ImageNotFound](#ImageNotFound) error if
# the image cannot be found in local storage; otherwise it will return a [MoreResponse](#MoreResponse)
-method PushImage(name: string, tag: string, tlsverify: bool, signaturePolicy: string, creds: string, certDir: string, compress: bool, format: string, removeSignatures: bool, signBy: string) -> (reply: MoreResponse)
+method PushImage(name: string, tag: string, tlsverify: ?bool, signaturePolicy: string, creds: string, certDir: string, compress: bool, format: string, removeSignatures: bool, signBy: string) -> (reply: MoreResponse)
# TagImage takes the name or ID of an image in local storage as well as the desired tag name. If the image cannot
# be found, an [ImageNotFound](#ImageNotFound) error will be returned; otherwise, the ID of the image is returned on success.
@@ -679,7 +679,7 @@ method RemoveImage(name: string, force: bool) -> (image: string)
# SearchImages searches available registries for images that contain the
# contents of "query" in their name. If "limit" is given, limits the amount of
# search results per registry.
-method SearchImages(query: string, limit: ?int) -> (results: []ImageSearchResult)
+method SearchImages(query: string, limit: ?int, tlsVerify: ?bool) -> (results: []ImageSearchResult)
# DeleteUnusedImages deletes any images not associated with a container. The IDs of the deleted images are returned
# in a string array.
@@ -726,7 +726,7 @@ method ExportImage(name: string, destination: string, compress: bool, tags: []st
# "id": "426866d6fa419873f97e5cbd320eeb22778244c1dfffa01c944db3114f55772e"
# }
# ~~~
-method PullImage(name: string, certDir: string, creds: string, signaturePolicy: string, tlsVerify: bool) -> (id: string)
+method PullImage(name: string, certDir: string, creds: string, signaturePolicy: string, tlsVerify: ?bool) -> (id: string)
# CreatePod creates a new empty pod. It uses a [PodCreate](#PodCreate) type for input.
# On success, the ID of the newly created pod will be returned.
@@ -1070,15 +1070,24 @@ method ContainerInspectData(name: string) -> (config: string)
# development of Podman only and generally should not be used.
method ContainerStateData(name: string) -> (config: string)
+# Sendfile allows a remote client to send a file to the host
method SendFile(type: string, length: int) -> (file_handle: string)
+
+# ReceiveFile allows the host to send a remote client a file
method ReceiveFile(path: string, delete: bool) -> (len: int)
+# VolumeCreate creates a volume on a remote host
method VolumeCreate(options: VolumeCreateOpts) -> (volumeName: string)
+# VolumeRemove removes a volume on a remote host
method VolumeRemove(options: VolumeRemoveOpts) -> (volumeNames: []string)
+# GetVolumes gets slice of the volumes on a remote host
method GetVolumes(args: []string, all: bool) -> (volumes: []Volume)
+# VolumesPrune removes unused volumes on the host
+method VolumesPrune() -> (prunedNames: []string, prunedErrors: []string)
+
# ImageNotFound means the image could not be found by the provided name or ID in local storage.
error ImageNotFound (id: string)
diff --git a/cmd/podman/volume.go b/cmd/podman/volume.go
index 36798a19e..8a8664151 100644
--- a/cmd/podman/volume.go
+++ b/cmd/podman/volume.go
@@ -16,8 +16,16 @@ var volumeCommand = cliconfig.PodmanCommand{
Long: volumeDescription,
},
}
+var volumeSubcommands = []*cobra.Command{
+ _volumeCreateCommand,
+ _volumeLsCommand,
+ _volumeRmCommand,
+ _volumeInspectCommand,
+ _volumePruneCommand,
+}
func init() {
- volumeCommand.AddCommand(getVolumeSubCommands()...)
volumeCommand.SetUsageTemplate(UsageTemplate())
+ volumeCommand.AddCommand(volumeSubcommands...)
+ rootCmd.AddCommand(volumeCommand.Command)
}
diff --git a/cmd/podman/volume_prune.go b/cmd/podman/volume_prune.go
index 74228fa5b..a2205140f 100644
--- a/cmd/podman/volume_prune.go
+++ b/cmd/podman/volume_prune.go
@@ -8,7 +8,6 @@ import (
"strings"
"github.com/containers/libpod/cmd/podman/cliconfig"
- "github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/adapter"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
@@ -44,23 +43,20 @@ func init() {
}
func volumePrune(runtime *adapter.LocalRuntime, ctx context.Context) error {
- var lastError error
-
- volumes, err := runtime.GetAllVolumes()
- if err != nil {
- return err
+ prunedNames, prunedErrors := runtime.PruneVolumes(ctx)
+ for _, name := range prunedNames {
+ fmt.Println(name)
+ }
+ if len(prunedErrors) == 0 {
+ return nil
}
+ // Grab the last error
+ lastError := prunedErrors[len(prunedErrors)-1]
+ // Remove the last error from the error slice
+ prunedErrors = prunedErrors[:len(prunedErrors)-1]
- for _, vol := range volumes {
- err = runtime.RemoveVolume(ctx, vol, false, true)
- if err == nil {
- fmt.Println(vol.Name())
- } else if err != libpod.ErrVolumeBeingUsed {
- if lastError != nil {
- logrus.Errorf("%q", lastError)
- }
- lastError = errors.Wrapf(err, "failed to remove volume %q", vol.Name())
- }
+ for _, err := range prunedErrors {
+ logrus.Errorf("%q", err)
}
return lastError
}
@@ -85,6 +81,5 @@ func volumePruneCmd(c *cliconfig.VolumePruneValues) error {
return nil
}
}
-
return volumePrune(runtime, getContext())
}