summaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'cmd')
-rw-r--r--cmd/podman/cliconfig/config.go4
-rw-r--r--cmd/podman/cp.go97
-rw-r--r--cmd/podman/exec.go7
-rw-r--r--cmd/podman/generate_kube.go19
-rw-r--r--cmd/podman/main.go3
-rw-r--r--cmd/podman/main_local.go2
-rw-r--r--cmd/podman/main_remote.go8
-rw-r--r--cmd/podman/restore.go18
-rw-r--r--cmd/podman/rm.go9
-rw-r--r--cmd/podman/varlink/io.podman.varlink10
10 files changed, 162 insertions, 15 deletions
diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go
index b8b1648b8..4a4c839cc 100644
--- a/cmd/podman/cliconfig/config.go
+++ b/cmd/podman/cliconfig/config.go
@@ -145,7 +145,8 @@ type ExportValues struct {
}
type GenerateKubeValues struct {
PodmanCommand
- Service bool
+ Service bool
+ Filename string
}
type GenerateSystemdValues struct {
@@ -438,6 +439,7 @@ type RmValues struct {
All bool
Force bool
Latest bool
+ Storage bool
Volumes bool
}
diff --git a/cmd/podman/cp.go b/cmd/podman/cp.go
index 7679ebcf1..a9418e6e0 100644
--- a/cmd/podman/cp.go
+++ b/cmd/podman/cp.go
@@ -145,7 +145,19 @@ func copyBetweenHostAndContainer(runtime *libpod.Runtime, src string, dest strin
var glob []string
if isFromHostToCtr {
- if filepath.IsAbs(destPath) {
+ if isVol, volDestName, volName := isVolumeDestName(destPath, ctr); isVol {
+ path, err := pathWithVolumeMount(ctr, runtime, volDestName, volName, destPath)
+ if err != nil {
+ return errors.Wrapf(err, "error getting destination path from volume %s", volDestName)
+ }
+ destPath = path
+ } else if isBindMount, mount := isBindMountDestName(destPath, ctr); isBindMount {
+ path, err := pathWithBindMountSource(mount, destPath)
+ if err != nil {
+ return errors.Wrapf(err, "error getting destination path from bind mount %s", mount.Destination)
+ }
+ destPath = path
+ } else if filepath.IsAbs(destPath) {
cleanedPath, err := securejoin.SecureJoin(mountPoint, destPath)
if err != nil {
return err
@@ -166,7 +178,19 @@ func copyBetweenHostAndContainer(runtime *libpod.Runtime, src string, dest strin
destPath = cleanedPath
}
} else {
- if filepath.IsAbs(srcPath) {
+ if isVol, volDestName, volName := isVolumeDestName(srcPath, ctr); isVol {
+ path, err := pathWithVolumeMount(ctr, runtime, volDestName, volName, srcPath)
+ if err != nil {
+ return errors.Wrapf(err, "error getting source path from volume %s", volDestName)
+ }
+ srcPath = path
+ } else if isBindMount, mount := isBindMountDestName(srcPath, ctr); isBindMount {
+ path, err := pathWithBindMountSource(mount, srcPath)
+ if err != nil {
+ return errors.Wrapf(err, "error getting source path from bind moutn %s", mount.Destination)
+ }
+ srcPath = path
+ } else if filepath.IsAbs(srcPath) {
cleanedPath, err := securejoin.SecureJoin(mountPoint, srcPath)
if err != nil {
return err
@@ -407,3 +431,72 @@ func streamFileToStdout(srcPath string, srcfi os.FileInfo) error {
}
return nil
}
+
+func isVolumeDestName(path string, ctr *libpod.Container) (bool, string, string) {
+ separator := string(os.PathSeparator)
+ if filepath.IsAbs(path) {
+ path = strings.TrimPrefix(path, separator)
+ }
+ if path == "" {
+ return false, "", ""
+ }
+ for _, vol := range ctr.Config().NamedVolumes {
+ volNamePath := strings.TrimPrefix(vol.Dest, separator)
+ if matchVolumePath(path, volNamePath) {
+ return true, vol.Dest, vol.Name
+ }
+ }
+ return false, "", ""
+}
+
+// if SRCPATH or DESTPATH is from volume mount's destination -v or --mount type=volume, generates the path with volume mount point
+func pathWithVolumeMount(ctr *libpod.Container, runtime *libpod.Runtime, volDestName, volName, path string) (string, error) {
+ destVolume, err := runtime.GetVolume(volName)
+ if err != nil {
+ return "", errors.Wrapf(err, "error getting volume destination %s", volName)
+ }
+ if !filepath.IsAbs(path) {
+ path = filepath.Join(string(os.PathSeparator), path)
+ }
+ path, err = securejoin.SecureJoin(destVolume.MountPoint(), strings.TrimPrefix(path, volDestName))
+ return path, err
+}
+
+func isBindMountDestName(path string, ctr *libpod.Container) (bool, specs.Mount) {
+ separator := string(os.PathSeparator)
+ if filepath.IsAbs(path) {
+ path = strings.TrimPrefix(path, string(os.PathSeparator))
+ }
+ if path == "" {
+ return false, specs.Mount{}
+ }
+ for _, m := range ctr.Config().Spec.Mounts {
+ if m.Type != "bind" {
+ continue
+ }
+ mDest := strings.TrimPrefix(m.Destination, separator)
+ if matchVolumePath(path, mDest) {
+ return true, m
+ }
+ }
+ return false, specs.Mount{}
+}
+
+func matchVolumePath(path, target string) bool {
+ pathStr := filepath.Clean(path)
+ target = filepath.Clean(target)
+ for len(pathStr) > len(target) && strings.Contains(pathStr, string(os.PathSeparator)) {
+ pathStr = pathStr[:strings.LastIndex(pathStr, string(os.PathSeparator))]
+ }
+ if pathStr == target {
+ return true
+ }
+ return false
+}
+
+func pathWithBindMountSource(m specs.Mount, path string) (string, error) {
+ if !filepath.IsAbs(path) {
+ path = filepath.Join(string(os.PathSeparator), path)
+ }
+ return securejoin.SecureJoin(m.Source, strings.TrimPrefix(path, m.Destination))
+}
diff --git a/cmd/podman/exec.go b/cmd/podman/exec.go
index deff44a92..0684da842 100644
--- a/cmd/podman/exec.go
+++ b/cmd/podman/exec.go
@@ -125,5 +125,10 @@ func execCmd(c *cliconfig.ExecValues) error {
streams.AttachError = true
streams.AttachInput = true
- return ctr.Exec(c.Tty, c.Privileged, envs, cmd, c.User, c.Workdir, streams, c.PreserveFDs)
+ err = ctr.Exec(c.Tty, c.Privileged, envs, cmd, c.User, c.Workdir, streams, c.PreserveFDs)
+ if errors.Cause(err) == libpod.ErrCtrStateInvalid {
+ exitCode = 126
+ }
+
+ return err
}
diff --git a/cmd/podman/generate_kube.go b/cmd/podman/generate_kube.go
index 318dd0771..3969e3132 100644
--- a/cmd/podman/generate_kube.go
+++ b/cmd/podman/generate_kube.go
@@ -2,6 +2,9 @@ package main
import (
"fmt"
+ "io/ioutil"
+ "os"
+
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/pkg/adapter"
podmanVersion "github.com/containers/libpod/version"
@@ -37,6 +40,7 @@ func init() {
containerKubeCommand.SetUsageTemplate(UsageTemplate())
flags := containerKubeCommand.Flags()
flags.BoolVarP(&containerKubeCommand.Service, "service", "s", false, "Generate YAML for kubernetes service object")
+ flags.StringVarP(&containerKubeCommand.Filename, "filename", "f", "", "Filename to output to")
}
func generateKubeYAMLCmd(c *cliconfig.GenerateKubeValues) error {
@@ -88,8 +92,19 @@ func generateKubeYAMLCmd(c *cliconfig.GenerateKubeValues) error {
output = append(output, []byte("---\n")...)
output = append(output, marshalledService...)
}
- // Output the v1.Pod with the v1.Container
- fmt.Println(string(output))
+
+ if c.Filename != "" {
+ if _, err := os.Stat(c.Filename); err == nil {
+ return errors.Errorf("cannot write to %q - file exists", c.Filename)
+ }
+
+ if err := ioutil.WriteFile(c.Filename, output, 0644); err != nil {
+ return err
+ }
+ } else {
+ // Output the v1.Pod with the v1.Container
+ fmt.Println(string(output))
+ }
return nil
}
diff --git a/cmd/podman/main.go b/cmd/podman/main.go
index a149a47f9..cbca32cc8 100644
--- a/cmd/podman/main.go
+++ b/cmd/podman/main.go
@@ -104,6 +104,9 @@ func before(cmd *cobra.Command, args []string) error {
logrus.Errorf(err.Error())
os.Exit(1)
}
+ if err := setSyslog(); err != nil {
+ return err
+ }
if err := setupRootless(cmd, args); err != nil {
return err
}
diff --git a/cmd/podman/main_local.go b/cmd/podman/main_local.go
index b4f21bd0c..132f35ab5 100644
--- a/cmd/podman/main_local.go
+++ b/cmd/podman/main_local.go
@@ -48,7 +48,7 @@ func init() {
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.Runtime, "runtime", "", "Path to the OCI-compatible binary used to run containers, default is /usr/bin/runc")
// -s is depracated due to conflict with -s on subcommands
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.StorageDriver, "storage-driver", "", "Select which storage driver is used to manage storage of images and containers (default is overlay)")
- rootCmd.PersistentFlags().StringSliceVar(&MainGlobalOpts.StorageOpts, "storage-opt", []string{}, "Used to pass an option to the storage driver")
+ rootCmd.PersistentFlags().StringArrayVar(&MainGlobalOpts.StorageOpts, "storage-opt", []string{}, "Used to pass an option to the storage driver")
rootCmd.PersistentFlags().BoolVar(&MainGlobalOpts.Syslog, "syslog", false, "Output logging information to syslog as well as the console")
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.TmpDir, "tmpdir", "", "Path to the tmp directory")
diff --git a/cmd/podman/main_remote.go b/cmd/podman/main_remote.go
index de6c2c760..1b9430e92 100644
--- a/cmd/podman/main_remote.go
+++ b/cmd/podman/main_remote.go
@@ -3,15 +3,21 @@
package main
import (
+ "os/user"
+
"github.com/spf13/cobra"
)
const remote = true
func init() {
+ var username string
+ if curruser, err := user.Current(); err == nil {
+ username = curruser.Username
+ }
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.ConnectionName, "connection", "", "remote connection name")
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.RemoteConfigFilePath, "remote-config-path", "", "alternate path for configuration file")
- rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.RemoteUserName, "username", "", "username on the remote host")
+ rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.RemoteUserName, "username", username, "username on the remote host")
rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.RemoteHost, "remote-host", "", "remote host")
// TODO maybe we allow the altering of this for bridge connections?
//rootCmd.PersistentFlags().StringVar(&MainGlobalOpts.VarlinkAddress, "varlink-address", adapter.DefaultAddress, "address of the varlink socket")
diff --git a/cmd/podman/restore.go b/cmd/podman/restore.go
index 9c77d4a5e..6e445e5df 100644
--- a/cmd/podman/restore.go
+++ b/cmd/podman/restore.go
@@ -76,8 +76,22 @@ func restoreCmd(c *cliconfig.RestoreValues, cmd *cobra.Command) error {
return errors.Errorf("--tcp-established cannot be used with --name")
}
- if (c.Import != "") && (c.All || c.Latest) {
- return errors.Errorf("Cannot use --import and --all or --latest at the same time")
+ argLen := len(c.InputArgs)
+ if c.Import != "" {
+ if c.All || c.Latest {
+ return errors.Errorf("Cannot use --import with --all or --latest")
+ }
+ if argLen > 0 {
+ return errors.Errorf("Cannot use --import with positional arguments")
+ }
}
+
+ if (c.All || c.Latest) && argLen > 0 {
+ return errors.Errorf("no arguments are needed with --all or --latest")
+ }
+ if argLen < 1 && !c.All && !c.Latest && c.Import == "" {
+ return errors.Errorf("you must provide at least one name or id")
+ }
+
return runtime.Restore(getContext(), c, options)
}
diff --git a/cmd/podman/rm.go b/cmd/podman/rm.go
index 1bf56b782..2710a8194 100644
--- a/cmd/podman/rm.go
+++ b/cmd/podman/rm.go
@@ -42,7 +42,9 @@ func init() {
flags.BoolVarP(&rmCommand.All, "all", "a", false, "Remove all containers")
flags.BoolVarP(&rmCommand.Force, "force", "f", false, "Force removal of a running container. The default is false")
flags.BoolVarP(&rmCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
+ flags.BoolVar(&rmCommand.Storage, "storage", false, "Remove container from storage library")
flags.BoolVarP(&rmCommand.Volumes, "volumes", "v", false, "Remove the volumes associated with the container")
+ markFlagHiddenForRemoteClient("storage", flags)
markFlagHiddenForRemoteClient("latest", flags)
}
@@ -54,6 +56,13 @@ func rmCmd(c *cliconfig.RmValues) error {
}
defer runtime.Shutdown(false)
+ // Storage conflicts with --all/--latest/--volumes
+ if c.Storage {
+ if c.All || c.Latest || c.Volumes {
+ return errors.Errorf("--storage conflicts with --volumes, --all, and --latest")
+ }
+ }
+
ok, failures, err := runtime.RemoveContainers(getContext(), c)
if err != nil {
if errors.Cause(err) == libpod.ErrNoSuchCtr {
diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink
index 5b3d5ae4c..9410b9459 100644
--- a/cmd/podman/varlink/io.podman.varlink
+++ b/cmd/podman/varlink/io.podman.varlink
@@ -207,7 +207,7 @@ type ContainerNameSpace (
ipc: string
)
-# InfoDistribution describes the the host's distribution
+# InfoDistribution describes the host's distribution
type InfoDistribution (
distribution: string,
version: string
@@ -671,7 +671,7 @@ method PauseContainer(name: string) -> (container: string)
# See also [PauseContainer](#PauseContainer).
method UnpauseContainer(name: string) -> (container: string)
-# Attach takes the name or ID of a container and sets up a the ability to remotely attach to its console. The start
+# Attach takes the name or ID of a container and sets up the ability to remotely attach to its console. The start
# bool is whether you wish to start the container in question first.
method Attach(name: string, detachKeys: string, start: bool) -> ()
@@ -744,7 +744,7 @@ method BuildImage(build: BuildInfo) -> (image: MoreResponse)
# This function is not implemented yet.
# method CreateImage() -> (notimplemented: NotImplemented)
-# InspectImage takes the name or ID of an image and returns a string respresentation of data associated with the
+# InspectImage takes the name or ID of an image and returns a string representation of data associated with the
#image. You must serialize the string into JSON to use it further. An [ImageNotFound](#ImageNotFound) error will
# be returned if the image cannot be found.
method InspectImage(name: string) -> (image: string)
@@ -810,7 +810,7 @@ method Commit(name: string, image_name: string, changes: []string, author: strin
method ImportImage(source: string, reference: string, message: string, changes: []string, delete: bool) -> (image: string)
# ExportImage takes the name or ID of an image and exports it to a destination like a tarball. There is also
-# a booleon option to force compression. It also takes in a string array of tags to be able to save multiple
+# a boolean option to force compression. It also takes in a string array of tags to be able to save multiple
# tags of the same image to a tarball (each tag should be of the form <image>:<tag>). Upon completion, the ID
# of the image is returned. If the image cannot be found in local storage, an [ImageNotFound](#ImageNotFound)
# error will be returned. See also [ImportImage](ImportImage).
@@ -915,7 +915,7 @@ method ListPods() -> (pods: []ListPodData)
# ~~~
method GetPod(name: string) -> (pod: ListPodData)
-# InspectPod takes the name or ID of an image and returns a string respresentation of data associated with the
+# InspectPod takes the name or ID of an image and returns a string representation of data associated with the
# pod. You must serialize the string into JSON to use it further. A [PodNotFound](#PodNotFound) error will
# be returned if the pod cannot be found.
method InspectPod(name: string) -> (pod: string)