summaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'cmd')
-rw-r--r--cmd/podman/attach.go5
-rw-r--r--cmd/podman/build.go114
-rw-r--r--cmd/podman/checkpoint.go1
-rw-r--r--cmd/podman/cleanup.go23
-rw-r--r--cmd/podman/cliconfig/config.go19
-rw-r--r--cmd/podman/cliconfig/create.go4
-rw-r--r--cmd/podman/commands.go68
-rw-r--r--cmd/podman/commands_remoteclient.go22
-rw-r--r--cmd/podman/commit.go6
-rw-r--r--cmd/podman/common.go24
-rw-r--r--cmd/podman/common_test.go26
-rw-r--r--cmd/podman/container.go7
-rw-r--r--cmd/podman/containers_prune.go14
-rw-r--r--cmd/podman/cp.go257
-rw-r--r--cmd/podman/create.go9
-rw-r--r--cmd/podman/diff.go4
-rw-r--r--cmd/podman/exec.go2
-rw-r--r--cmd/podman/exists.go9
-rw-r--r--cmd/podman/export.go2
-rw-r--r--cmd/podman/generate.go2
-rw-r--r--cmd/podman/generate_kube.go1
-rw-r--r--cmd/podman/history.go4
-rw-r--r--cmd/podman/image.go7
-rw-r--r--cmd/podman/images.go9
-rw-r--r--cmd/podman/images_prune.go1
-rw-r--r--cmd/podman/import.go2
-rw-r--r--cmd/podman/info.go4
-rw-r--r--cmd/podman/inspect.go6
-rw-r--r--cmd/podman/kill.go2
-rw-r--r--cmd/podman/load.go2
-rw-r--r--cmd/podman/login.go29
-rw-r--r--cmd/podman/logout.go2
-rw-r--r--cmd/podman/logs.go2
-rw-r--r--cmd/podman/main.go26
-rw-r--r--cmd/podman/mount.go2
-rw-r--r--cmd/podman/pause.go2
-rw-r--r--cmd/podman/play.go15
-rw-r--r--cmd/podman/play_kube.go1
-rw-r--r--cmd/podman/pod.go2
-rw-r--r--cmd/podman/pod_create.go5
-rw-r--r--cmd/podman/pod_inspect.go3
-rw-r--r--cmd/podman/pod_kill.go1
-rw-r--r--cmd/podman/pod_pause.go1
-rw-r--r--cmd/podman/pod_ps.go1
-rw-r--r--cmd/podman/pod_restart.go1
-rw-r--r--cmd/podman/pod_rm.go5
-rw-r--r--cmd/podman/pod_start.go1
-rw-r--r--cmd/podman/pod_stats.go131
-rw-r--r--cmd/podman/pod_stop.go1
-rw-r--r--cmd/podman/pod_top.go1
-rw-r--r--cmd/podman/pod_unpause.go1
-rw-r--r--cmd/podman/port.go9
-rw-r--r--cmd/podman/ps.go4
-rw-r--r--cmd/podman/pull.go2
-rw-r--r--cmd/podman/push.go17
-rw-r--r--cmd/podman/refresh.go2
-rw-r--r--cmd/podman/restart.go2
-rw-r--r--cmd/podman/restore.go2
-rw-r--r--cmd/podman/rm.go18
-rw-r--r--cmd/podman/rmi.go3
-rw-r--r--cmd/podman/run.go47
-rw-r--r--cmd/podman/runlabel.go1
-rw-r--r--cmd/podman/save.go3
-rw-r--r--cmd/podman/search.go3
-rw-r--r--cmd/podman/shared/container.go7
-rw-r--r--cmd/podman/sign.go3
-rw-r--r--cmd/podman/start.go12
-rw-r--r--cmd/podman/stats.go3
-rw-r--r--cmd/podman/stop.go3
-rw-r--r--cmd/podman/system.go7
-rw-r--r--cmd/podman/system_prune.go4
-rw-r--r--cmd/podman/tag.go3
-rw-r--r--cmd/podman/top.go3
-rw-r--r--cmd/podman/trust.go1
-rw-r--r--cmd/podman/trust_set_show.go3
-rw-r--r--cmd/podman/umount.go3
-rw-r--r--cmd/podman/unpause.go3
-rw-r--r--cmd/podman/varlink.go7
-rw-r--r--cmd/podman/varlink/io.podman.varlink233
-rw-r--r--cmd/podman/varlink_dummy.go10
-rw-r--r--cmd/podman/version.go2
-rw-r--r--cmd/podman/volume.go10
-rw-r--r--cmd/podman/volume_create.go37
-rw-r--r--cmd/podman/volume_inspect.go23
-rw-r--r--cmd/podman/volume_ls.go43
-rw-r--r--cmd/podman/volume_prune.go30
-rw-r--r--cmd/podman/volume_rm.go37
-rw-r--r--cmd/podman/wait.go3
88 files changed, 994 insertions, 498 deletions
diff --git a/cmd/podman/attach.go b/cmd/podman/attach.go
index 8b0fd7ffd..ed175bdf4 100644
--- a/cmd/podman/attach.go
+++ b/cmd/podman/attach.go
@@ -28,14 +28,13 @@ var (
func init() {
attachCommand.Command = _attachCommand
+ attachCommand.SetUsageTemplate(UsageTemplate())
flags := attachCommand.Flags()
flags.StringVar(&attachCommand.DetachKeys, "detach-keys", "", "Override the key sequence for detaching a container. Format is a single character [a-Z] or ctrl-<value> where <value> is one of: a-z, @, ^, [, , or _")
flags.BoolVar(&attachCommand.NoStdin, "no-stdin", false, "Do not attach STDIN. The default is false")
flags.BoolVar(&attachCommand.SigProxy, "sig-proxy", true, "Proxy received signals to the process (default true)")
flags.BoolVarP(&attachCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
-
- rootCmd.AddCommand(attachCommand.Command)
}
func attachCmd(c *cliconfig.AttachValues) error {
@@ -75,7 +74,7 @@ func attachCmd(c *cliconfig.AttachValues) error {
inputStream = nil
}
- if err := startAttachCtr(ctr, os.Stdout, os.Stderr, inputStream, c.DetachKeys, c.SigProxy, false); err != nil {
+ if err := startAttachCtr(ctr, os.Stdout, os.Stderr, inputStream, c.DetachKeys, c.SigProxy, false); err != nil && errors.Cause(err) != libpod.ErrDetach {
return errors.Wrapf(err, "error attaching to container %s", ctr.ID())
}
diff --git a/cmd/podman/build.go b/cmd/podman/build.go
index 20f621e84..30a734377 100644
--- a/cmd/podman/build.go
+++ b/cmd/podman/build.go
@@ -1,7 +1,6 @@
package main
import (
- "io/ioutil"
"os"
"path/filepath"
"strings"
@@ -9,10 +8,9 @@ import (
"github.com/containers/buildah"
"github.com/containers/buildah/imagebuildah"
buildahcli "github.com/containers/buildah/pkg/cli"
- "github.com/containers/buildah/pkg/parse"
"github.com/containers/libpod/cmd/podman/cliconfig"
- "github.com/containers/libpod/cmd/podman/libpodruntime"
- "github.com/containers/libpod/pkg/rootless"
+ "github.com/containers/libpod/libpod/adapter"
+ "github.com/docker/go-units"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
@@ -48,6 +46,7 @@ var (
func init() {
buildCommand.Command = _buildCommand
+ buildCommand.SetUsageTemplate(UsageTemplate())
flags := buildCommand.Flags()
flags.SetInterspersed(false)
@@ -58,8 +57,6 @@ func init() {
flags.AddFlagSet(&budFlags)
flags.AddFlagSet(&fromAndBugFlags)
-
- rootCmd.AddCommand(buildCommand.Command)
}
func getDockerfiles(files []string) []string {
@@ -77,7 +74,6 @@ func getDockerfiles(files []string) []string {
func buildCmd(c *cliconfig.BuildValues) error {
// The following was taken directly from containers/buildah/cmd/bud.go
// TODO Find a away to vendor more of this in rather than copy from bud
-
output := ""
tags := []string{}
if c.Flag("tag").Changed {
@@ -87,6 +83,7 @@ func buildCmd(c *cliconfig.BuildValues) error {
tags = tags[1:]
}
}
+
pullPolicy := imagebuildah.PullNever
if c.Pull {
pullPolicy = imagebuildah.PullIfMissing
@@ -174,16 +171,17 @@ func buildCmd(c *cliconfig.BuildValues) error {
dockerfiles = append(dockerfiles, filepath.Join(contextDir, "Dockerfile"))
}
+ runtime, err := adapter.GetRuntime(&c.PodmanCommand)
+ if err != nil {
+ return errors.Wrapf(err, "could not get runtime")
+ }
+
runtimeFlags := []string{}
for _, arg := range c.RuntimeOpts {
runtimeFlags = append(runtimeFlags, "--"+arg)
}
// end from buildah
- runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
- if err != nil {
- return errors.Wrapf(err, "could not get runtime")
- }
defer runtime.Shutdown(false)
var stdout, stderr, reporter *os.File
@@ -202,72 +200,64 @@ func buildCmd(c *cliconfig.BuildValues) error {
reporter = f
}
- systemContext, err := parse.SystemContextFromOptions(c.PodmanCommand.Command)
- if err != nil {
- return errors.Wrapf(err, "error building system context")
- }
- systemContext.AuthFilePath = getAuthFile(c.Authfile)
- commonOpts, err := parse.CommonBuildOptions(c.PodmanCommand.Command)
- if err != nil {
- return err
+ var memoryLimit, memorySwap int64
+ if c.Flags().Changed("memory") {
+ memoryLimit, err = units.RAMInBytes(c.Memory)
+ if err != nil {
+ return err
+ }
}
- namespaceOptions, networkPolicy, err := parse.NamespaceOptions(c.PodmanCommand.Command)
- if err != nil {
- return errors.Wrapf(err, "error parsing namespace-related options")
- }
- usernsOption, idmappingOptions, err := parse.IDMappingOptions(c.PodmanCommand.Command)
- if err != nil {
- return errors.Wrapf(err, "error parsing ID mapping options")
+ if c.Flags().Changed("memory-swap") {
+ memorySwap, err = units.RAMInBytes(c.MemorySwap)
+ if err != nil {
+ return err
+ }
}
- namespaceOptions.AddOrReplace(usernsOption...)
- ociruntime := runtime.GetOCIRuntimePath()
- if c.Flag("runtime").Changed {
- ociruntime = c.Runtime
+ buildOpts := buildah.CommonBuildOptions{
+ AddHost: c.AddHost,
+ CgroupParent: c.CgroupParent,
+ CPUPeriod: c.CPUPeriod,
+ CPUQuota: c.CPUQuota,
+ CPUShares: c.CPUShares,
+ CPUSetCPUs: c.CPUSetCPUs,
+ CPUSetMems: c.CPUSetMems,
+ Memory: memoryLimit,
+ MemorySwap: memorySwap,
+ ShmSize: c.ShmSize,
+ Ulimit: c.Ulimit,
+ Volumes: c.Volume,
}
+
options := imagebuildah.BuildOptions{
- ContextDirectory: contextDir,
- PullPolicy: pullPolicy,
- Compression: imagebuildah.Gzip,
- Quiet: c.Quiet,
- SignaturePolicyPath: c.SignaturePolicy,
- Args: args,
- Output: output,
+ CommonBuildOpts: &buildOpts,
AdditionalTags: tags,
- Out: stdout,
- Err: stderr,
- ReportWriter: reporter,
- Runtime: ociruntime,
- RuntimeArgs: runtimeFlags,
- OutputFormat: format,
- SystemContext: systemContext,
- NamespaceOptions: namespaceOptions,
- ConfigureNetwork: networkPolicy,
- CNIPluginPath: c.CNIPlugInPath,
+ Annotations: c.Annotation,
+ Args: args,
CNIConfigDir: c.CNIConfigDir,
- IDMappingOptions: idmappingOptions,
- CommonBuildOpts: commonOpts,
+ CNIPluginPath: c.CNIPlugInPath,
+ Compression: imagebuildah.Gzip,
+ ContextDirectory: contextDir,
DefaultMountsFilePath: c.GlobalFlags.DefaultMountsFile,
+ Err: stderr,
+ ForceRmIntermediateCtrs: c.ForceRm,
IIDFile: c.Iidfile,
- Squash: c.Squash,
Labels: c.Label,
- Annotations: c.Annotation,
Layers: layers,
NoCache: c.NoCache,
+ Out: stdout,
+ Output: output,
+ OutputFormat: format,
+ PullPolicy: pullPolicy,
+ Quiet: c.Quiet,
RemoveIntermediateCtrs: c.Rm,
- ForceRmIntermediateCtrs: c.ForceRm,
- }
-
- if c.Quiet {
- options.ReportWriter = ioutil.Discard
- }
-
- if rootless.IsRootless() {
- options.Isolation = buildah.IsolationOCIRootless
+ ReportWriter: reporter,
+ RuntimeArgs: runtimeFlags,
+ SignaturePolicyPath: c.SignaturePolicy,
+ Squash: c.Squash,
}
-
- return runtime.Build(getContext(), options, dockerfiles...)
+ return runtime.Build(getContext(), c, options, dockerfiles)
}
// Tail returns a string slice after the first element unless there are
diff --git a/cmd/podman/checkpoint.go b/cmd/podman/checkpoint.go
index 2a978bea8..aa4034ccd 100644
--- a/cmd/podman/checkpoint.go
+++ b/cmd/podman/checkpoint.go
@@ -35,6 +35,7 @@ var (
func init() {
checkpointCommand.Command = _checkpointCommand
+ checkpointCommand.SetUsageTemplate(UsageTemplate())
flags := checkpointCommand.Flags()
flags.BoolVarP(&checkpointCommand.Keep, "keep", "k", false, "Keep all temporary checkpoint files")
diff --git a/cmd/podman/cleanup.go b/cmd/podman/cleanup.go
index 1a7617d5c..e465a30e6 100644
--- a/cmd/podman/cleanup.go
+++ b/cmd/podman/cleanup.go
@@ -32,10 +32,12 @@ var (
func init() {
cleanupCommand.Command = _cleanupCommand
+ cleanupCommand.SetUsageTemplate(UsageTemplate())
flags := cleanupCommand.Flags()
flags.BoolVarP(&cleanupCommand.All, "all", "a", false, "Cleans up all containers")
flags.BoolVarP(&cleanupCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
+ flags.BoolVar(&cleanupCommand.Remove, "rm", false, "After cleanup, remove the container entirely")
}
func cleanupCmd(c *cliconfig.CleanupValues) error {
@@ -54,12 +56,25 @@ func cleanupCmd(c *cliconfig.CleanupValues) error {
ctx := getContext()
for _, ctr := range cleanupContainers {
- if err = ctr.Cleanup(ctx); err != nil {
- if lastError != nil {
- fmt.Fprintln(os.Stderr, lastError)
+ hadError := false
+ if c.Remove {
+ if err := runtime.RemoveContainer(ctx, ctr, false, false); err != nil {
+ if lastError != nil {
+ fmt.Fprintln(os.Stderr, lastError)
+ }
+ lastError = errors.Wrapf(err, "failed to cleanup and remove container %v", ctr.ID())
+ hadError = true
}
- lastError = errors.Wrapf(err, "failed to cleanup container %v", ctr.ID())
} else {
+ if err := ctr.Cleanup(ctx); err != nil {
+ if lastError != nil {
+ fmt.Fprintln(os.Stderr, lastError)
+ }
+ lastError = errors.Wrapf(err, "failed to cleanup container %v", ctr.ID())
+ hadError = true
+ }
+ }
+ if !hadError {
fmt.Println(ctr.ID())
}
}
diff --git a/cmd/podman/cliconfig/config.go b/cmd/podman/cliconfig/config.go
index a4c1bf0c0..9c9be3618 100644
--- a/cmd/podman/cliconfig/config.go
+++ b/cmd/podman/cliconfig/config.go
@@ -135,6 +135,11 @@ type PruneImagesValues struct {
All bool
}
+type PruneContainersValues struct {
+ PodmanCommand
+ Force bool
+}
+
type ImportValues struct {
PodmanCommand
Change []string
@@ -172,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 {
@@ -532,6 +538,7 @@ type CleanupValues struct {
PodmanCommand
All bool
Latest bool
+ Remove bool
}
type SystemPruneValues struct {
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 e1eba1f31..fa3839a53 100644
--- a/cmd/podman/commands.go
+++ b/cmd/podman/commands.go
@@ -6,24 +6,65 @@ import (
"github.com/spf13/cobra"
)
+// Commands that the local client implements
+func getMainCommands() []*cobra.Command {
+ rootCommands := []*cobra.Command{
+ _attachCommand,
+ _commitCommand,
+ _createCommand,
+ _diffCommand,
+ _execCommand,
+ _killCommand,
+ generateCommand.Command,
+ podCommand.Command,
+ _containerKubeCommand,
+ _psCommand,
+ _loadCommand,
+ _loginCommand,
+ _logoutCommand,
+ _logsCommand,
+ _mountCommand,
+ _pauseCommand,
+ _portCommand,
+ _refreshCommand,
+ _restartCommand,
+ _restoreCommand,
+ _rmCommand,
+ _runCommand,
+ _saveCommand,
+ _searchCommand,
+ _signCommand,
+ _startCommand,
+ _statsCommand,
+ _stopCommand,
+ _topCommand,
+ _umountCommand,
+ _unpauseCommand,
+ volumeCommand.Command,
+ _waitCommand,
+ }
+
+ if len(_varlinkCommand.Use) > 0 {
+ rootCommands = append(rootCommands, _varlinkCommand)
+ }
+ return rootCommands
+}
+
+// Commands that the local client implements
func getImageSubCommands() []*cobra.Command {
return []*cobra.Command{
- _buildCommand,
- _importCommand,
_loadCommand,
- _pullCommand,
- _rmiCommand,
_saveCommand,
_signCommand,
}
}
+// Commands that the local client implements
func getContainerSubCommands() []*cobra.Command {
return []*cobra.Command{
_attachCommand,
_checkpointCommand,
_cleanupCommand,
- _containerExistsCommand,
_commitCommand,
_createCommand,
_diffCommand,
@@ -40,7 +81,7 @@ func getContainerSubCommands() []*cobra.Command {
_restartCommand,
_restoreCommand,
_rmCommand,
- _runCommmand,
+ _runCommand,
_runlabelCommand,
_startCommand,
_statsCommand,
@@ -52,6 +93,7 @@ func getContainerSubCommands() []*cobra.Command {
}
}
+// Commands that the local client implements
func getPodSubCommands() []*cobra.Command {
return []*cobra.Command{
_podCreateCommand,
@@ -70,28 +112,20 @@ func getPodSubCommands() []*cobra.Command {
}
}
-func getVolumeSubCommands() []*cobra.Command {
- return []*cobra.Command{
- _volumeCreateCommand,
- _volumeLsCommand,
- _volumeRmCommand,
- _volumeInspectCommand,
- _volumePruneCommand,
- }
-}
-
func getGenerateSubCommands() []*cobra.Command {
return []*cobra.Command{
_containerKubeCommand,
}
}
+// Commands that the local client implements
func getPlaySubCommands() []*cobra.Command {
return []*cobra.Command{
_playKubeCommand,
}
}
+// Commands that the local client implements
func getTrustSubCommands() []*cobra.Command {
return []*cobra.Command{
_setTrustCommand,
@@ -99,9 +133,9 @@ func getTrustSubCommands() []*cobra.Command {
}
}
+// Commands that the local client implements
func getSystemSubCommands() []*cobra.Command {
return []*cobra.Command{
- _infoCommand,
_pruneSystemCommand,
}
}
diff --git a/cmd/podman/commands_remoteclient.go b/cmd/podman/commands_remoteclient.go
index 80083eab9..ba0a4d47e 100644
--- a/cmd/podman/commands_remoteclient.go
+++ b/cmd/podman/commands_remoteclient.go
@@ -6,43 +6,47 @@ import (
"github.com/spf13/cobra"
)
-//import "github.com/urfave/cli"
-//
+// commands that only the remoteclient implements
+func getMainCommands() []*cobra.Command {
+ return []*cobra.Command{}
+}
+
+// commands that only the remoteclient implements
func getAppCommands() []*cobra.Command {
return []*cobra.Command{}
}
+// commands that only the remoteclient implements
func getImageSubCommands() []*cobra.Command {
return []*cobra.Command{}
}
+// commands that only the remoteclient implements
func getContainerSubCommands() []*cobra.Command {
return []*cobra.Command{}
}
+// commands that only the remoteclient implements
func getPodSubCommands() []*cobra.Command {
return []*cobra.Command{}
}
-func getVolumeSubCommands() []*cobra.Command {
- return []*cobra.Command{}
-}
-
+// commands that only the remoteclient implements
func getGenerateSubCommands() []*cobra.Command {
return []*cobra.Command{}
}
+// commands that only the remoteclient implements
func getPlaySubCommands() []*cobra.Command {
return []*cobra.Command{}
}
+// commands that only the remoteclient implements
func getTrustSubCommands() []*cobra.Command {
return []*cobra.Command{}
}
-//func getMainAppFlags() []cli.Flag {
-// return []cli.Flag{}
-//}
+// commands that only the remoteclient implements
func getSystemSubCommands() []*cobra.Command {
return []*cobra.Command{}
}
diff --git a/cmd/podman/commit.go b/cmd/podman/commit.go
index 6fd6b9761..d8ced0e36 100644
--- a/cmd/podman/commit.go
+++ b/cmd/podman/commit.go
@@ -33,12 +33,15 @@ 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`,
}
)
func init() {
commitCommand.Command = _commitCommand
+ commitCommand.SetUsageTemplate(UsageTemplate())
flags := commitCommand.Flags()
flags.StringSliceVarP(&commitCommand.Change, "change", "c", []string{}, fmt.Sprintf("Apply the following possible instructions to the created image (default []): %s", strings.Join(libpod.ChangeCmds, " | ")))
flags.StringVarP(&commitCommand.Format, "format", "f", "oci", "`Format` of the image manifest and metadata")
@@ -47,7 +50,6 @@ func init() {
flags.BoolVarP(&commitCommand.Pause, "pause", "p", false, "Pause container during commit")
flags.BoolVarP(&commitCommand.Quiet, "quiet", "q", false, "Suppress output")
- rootCmd.AddCommand(commitCommand.Command)
}
func commitCmd(c *cliconfig.CommitValues) error {
diff --git a/cmd/podman/common.go b/cmd/podman/common.go
index 5fbdfce50..ec755c4a8 100644
--- a/cmd/podman/common.go
+++ b/cmd/podman/common.go
@@ -500,3 +500,27 @@ func scrubServer(server string) string {
server = strings.TrimPrefix(server, "https://")
return strings.TrimPrefix(server, "http://")
}
+
+// UsageTemplate returns the usage template for podman commands
+// This blocks the desplaying of the global options. The main podman
+// command should not use this.
+func UsageTemplate() string {
+ return `Usage:{{if .Runnable}}
+ {{.UseLine}}{{end}}{{if .HasAvailableSubCommands}}
+
+ {{.CommandPath}} [command]{{end}}{{if gt (len .Aliases) 0}}
+
+Aliases:
+ {{.NameAndAliases}}{{end}}{{if .HasExample}}
+
+Examples:
+ {{.Example}}{{end}}{{if .HasAvailableSubCommands}}
+
+Available Commands:{{range .Commands}}{{if (or .IsAvailableCommand (eq .Name "help"))}}
+ {{rpad .Name .NamePadding }} {{.Short}}{{end}}{{end}}{{end}}{{if .HasAvailableLocalFlags}}
+
+Flags:
+{{.LocalFlags.FlagUsages | trimTrailingWhitespaces}}{{end}}{{if .HasAvailableInheritedFlags}}
+{{end}}
+`
+}
diff --git a/cmd/podman/common_test.go b/cmd/podman/common_test.go
index 042568d7e..a24173003 100644
--- a/cmd/podman/common_test.go
+++ b/cmd/podman/common_test.go
@@ -3,34 +3,8 @@ package main
import (
"os/user"
"testing"
-
- "flag"
-
- "github.com/urfave/cli"
)
-func TestGetStore(t *testing.T) {
- t.Skip("FIX THIS!")
-
- //cmd/podman/common_test.go:27: cannot use c (type *cli.Context) as type *libkpod.Config in argument to getStore
-
- // Make sure the tests are running as root
- skipTestIfNotRoot(t)
-
- set := flag.NewFlagSet("test", 0)
- globalSet := flag.NewFlagSet("test", 0)
- globalSet.String("root", "", "path to the root directory in which data, including images, is stored")
- globalCtx := cli.NewContext(nil, globalSet, nil)
- command := cli.Command{Name: "imagesCommand"}
- c := cli.NewContext(nil, set, globalCtx)
- c.Command = command
-
- //_, err := getStore(c)
- //if err != nil {
- //t.Error(err)
- //}
-}
-
func skipTestIfNotRoot(t *testing.T) {
u, err := user.Current()
if err != nil {
diff --git a/cmd/podman/container.go b/cmd/podman/container.go
index 969cb2dc8..d2450fdd3 100644
--- a/cmd/podman/container.go
+++ b/cmd/podman/container.go
@@ -15,7 +15,14 @@ var containerCommand = cliconfig.PodmanCommand{
},
}
+// Commands that are universally implemented.
+var containerCommands = []*cobra.Command{
+ _containerExistsCommand,
+}
+
func init() {
+ containerCommand.AddCommand(containerCommands...)
containerCommand.AddCommand(getContainerSubCommands()...)
+ containerCommand.SetUsageTemplate(UsageTemplate())
rootCmd.AddCommand(containerCommand.Command)
}
diff --git a/cmd/podman/containers_prune.go b/cmd/podman/containers_prune.go
index 3f9b46035..bae578e1d 100644
--- a/cmd/podman/containers_prune.go
+++ b/cmd/podman/containers_prune.go
@@ -13,13 +13,12 @@ import (
)
var (
- pruneContainersCommand cliconfig.ContainersPrune
+ pruneContainersCommand cliconfig.PruneContainersValues
pruneContainersDescription = `
podman container prune
Removes all exited containers
`
-
_pruneContainersCommand = &cobra.Command{
Use: "prune",
Short: "Remove all stopped containers",
@@ -34,9 +33,12 @@ var (
func init() {
pruneContainersCommand.Command = _pruneContainersCommand
+ pruneContainersCommand.SetUsageTemplate(UsageTemplate())
+ flags := pruneContainersCommand.Flags()
+ flags.BoolVarP(&pruneContainersCommand.Force, "force", "f", false, "Force removal of a running container. The default is false")
}
-func pruneContainers(runtime *adapter.LocalRuntime, ctx context.Context, maxWorkers int, force bool) error {
+func pruneContainers(runtime *adapter.LocalRuntime, ctx context.Context, maxWorkers int, force, volumes bool) error {
var deleteFuncs []shared.ParallelWorkerInput
filter := func(c *libpod.Container) bool {
@@ -56,7 +58,7 @@ func pruneContainers(runtime *adapter.LocalRuntime, ctx context.Context, maxWork
for _, container := range delContainers {
con := container
f := func() error {
- return runtime.RemoveContainer(ctx, con, force)
+ return runtime.RemoveContainer(ctx, con, force, volumes)
}
deleteFuncs = append(deleteFuncs, shared.ParallelWorkerInput{
@@ -69,7 +71,7 @@ func pruneContainers(runtime *adapter.LocalRuntime, ctx context.Context, maxWork
return printParallelOutput(deleteErrors, errCount)
}
-func pruneContainersCmd(c *cliconfig.ContainersPrune) error {
+func pruneContainersCmd(c *cliconfig.PruneContainersValues) error {
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not get runtime")
@@ -82,5 +84,5 @@ func pruneContainersCmd(c *cliconfig.ContainersPrune) error {
}
logrus.Debugf("Setting maximum workers to %d", maxWorkers)
- return pruneContainers(runtime, getContext(), maxWorkers, c.Bool("force"))
+ return pruneContainers(runtime, getContext(), maxWorkers, c.Bool("force"), c.Bool("volumes"))
}
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 2f8742052..7bfb070c7 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{
@@ -60,12 +62,12 @@ var (
func init() {
createCommand.PodmanCommand.Command = _createCommand
+ createCommand.SetUsageTemplate(UsageTemplate())
getCreateFlags(&createCommand.PodmanCommand)
flags := createCommand.Flags()
flags.SetInterspersed(true)
- rootCmd.AddCommand(createCommand.Command)
}
func createCmd(c *cliconfig.CreateValues) error {
@@ -646,9 +648,10 @@ func parseCreateOpts(ctx context.Context, c *cliconfig.PodmanCommand, runtime *l
}
var ImageVolumes map[string]struct{}
- if data != nil {
+ if data != nil && c.String("image-volume") != "ignore" {
ImageVolumes = data.Config.Volumes
}
+
var imageVolType = map[string]string{
"bind": "",
"tmpfs": "",
diff --git a/cmd/podman/diff.go b/cmd/podman/diff.go
index 04a659ab6..7d4cc1b58 100644
--- a/cmd/podman/diff.go
+++ b/cmd/podman/diff.go
@@ -52,6 +52,7 @@ var (
func init() {
diffCommand.Command = _diffCommand
+ diffCommand.SetUsageTemplate(UsageTemplate())
flags := diffCommand.Flags()
flags.BoolVar(&diffCommand.Archive, "archive", true, "Save the diff as a tar archive")
@@ -59,9 +60,8 @@ func init() {
flags.MarkHidden("archive")
- rootCmd.AddCommand(diffCommand.Command)
-
}
+
func formatJSON(output []diffOutputParams) (diffJSONOutput, error) {
jsonStruct := diffJSONOutput{}
for _, output := range output {
diff --git a/cmd/podman/exec.go b/cmd/podman/exec.go
index b4f66bc03..74808768e 100644
--- a/cmd/podman/exec.go
+++ b/cmd/podman/exec.go
@@ -35,6 +35,7 @@ var (
func init() {
execCommand.Command = _execCommand
+ execCommand.SetUsageTemplate(UsageTemplate())
flags := execCommand.Flags()
flags.SetInterspersed(false)
flags.StringSliceVarP(&execCommand.Env, "env", "e", []string{}, "Set environment variables")
@@ -46,7 +47,6 @@ func init() {
flags.StringVarP(&execCommand.Workdir, "workdir", "w", "", "Working directory inside the container")
- rootCmd.AddCommand(execCommand.Command)
}
func execCmd(c *cliconfig.ExecValues) error {
diff --git a/cmd/podman/exists.go b/cmd/podman/exists.go
index a21e8fcf8..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,14 +66,17 @@ var (
podExistsCommand.GlobalFlags = MainGlobalOpts
return podExistsCmd(&podExistsCommand)
},
- Example: "POD-NAME",
+ Example: `podman pod exists podID`,
}
)
func init() {
imageExistsCommand.Command = _imageExistsCommand
+ imageExistsCommand.SetUsageTemplate(UsageTemplate())
containerExistsCommand.Command = _containerExistsCommand
+ containerExistsCommand.SetUsageTemplate(UsageTemplate())
podExistsCommand.Command = _podExistsCommand
+ podExistsCommand.SetUsageTemplate(UsageTemplate())
}
func imageExistsCmd(c *cliconfig.ImageExistsValues) error {
diff --git a/cmd/podman/export.go b/cmd/podman/export.go
index bd9e38b0c..2ce8186a1 100644
--- a/cmd/podman/export.go
+++ b/cmd/podman/export.go
@@ -31,9 +31,9 @@ var (
func init() {
exportCommand.Command = _exportCommand
+ exportCommand.SetUsageTemplate(UsageTemplate())
flags := exportCommand.Flags()
flags.StringVarP(&exportCommand.Output, "output", "o", "/dev/stdout", "Write to a file, default is STDOUT")
- rootCmd.AddCommand(exportCommand.Command)
}
// exportCmd saves a container to a tarball on disk
diff --git a/cmd/podman/generate.go b/cmd/podman/generate.go
index a5e15fdd6..66cb7a465 100644
--- a/cmd/podman/generate.go
+++ b/cmd/podman/generate.go
@@ -17,5 +17,5 @@ var generateCommand = cliconfig.PodmanCommand{
func init() {
generateCommand.AddCommand(getGenerateSubCommands()...)
- rootCmd.AddCommand(generateCommand.Command)
+ generateCommand.SetUsageTemplate(UsageTemplate())
}
diff --git a/cmd/podman/generate_kube.go b/cmd/podman/generate_kube.go
index 8e3432d12..ddb2daa34 100644
--- a/cmd/podman/generate_kube.go
+++ b/cmd/podman/generate_kube.go
@@ -31,6 +31,7 @@ var (
func init() {
containerKubeCommand.Command = _containerKubeCommand
+ containerKubeCommand.SetUsageTemplate(UsageTemplate())
flags := containerKubeCommand.Flags()
flags.BoolVarP(&containerKubeCommand.Service, "service", "s", false, "Generate YAML for kubernetes service object")
}
diff --git a/cmd/podman/history.go b/cmd/podman/history.go
index 97e501947..6791257d9 100644
--- a/cmd/podman/history.go
+++ b/cmd/podman/history.go
@@ -53,6 +53,7 @@ var (
func init() {
historyCommand.Command = _historyCommand
+ historyCommand.SetUsageTemplate(UsageTemplate())
flags := historyCommand.Flags()
flags.StringVar(&historyCommand.Format, "format", "", "Change the output to JSON or a Go template")
flags.BoolVarP(&historyCommand.Human, "human", "H", true, "Display sizes and dates in human readable format")
@@ -60,9 +61,8 @@ func init() {
flags.BoolVar(&historyCommand.NoTrunc, "no-trunc", false, "Do not truncate the output")
flags.BoolVarP(&historyCommand.Quiet, "quiet", "q", false, "Display the numeric IDs only")
- rootCmd.AddCommand(historyCommand.Command)
-
}
+
func historyCmd(c *cliconfig.HistoryValues) error {
runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
diff --git a/cmd/podman/image.go b/cmd/podman/image.go
index ac7ff4944..4f9c7cd6a 100644
--- a/cmd/podman/image.go
+++ b/cmd/podman/image.go
@@ -18,18 +18,21 @@ var (
//imageSubCommands are implemented both in local and remote clients
var imageSubCommands = []*cobra.Command{
+ _buildCommand,
_historyCommand,
_imageExistsCommand,
- _inspectCommand,
_imagesCommand,
+ _importCommand,
+ _inspectCommand,
_pruneImagesCommand,
+ _pullCommand,
_pushCommand,
_rmiCommand,
_tagCommand,
}
func init() {
+ imageCommand.SetUsageTemplate(UsageTemplate())
imageCommand.AddCommand(imageSubCommands...)
imageCommand.AddCommand(getImageSubCommands()...)
- rootCmd.AddCommand(imageCommand.Command)
}
diff --git a/cmd/podman/images.go b/cmd/podman/images.go
index 6f5a3e9f1..b269f6440 100644
--- a/cmd/podman/images.go
+++ b/cmd/podman/images.go
@@ -102,6 +102,7 @@ var (
func init() {
imagesCommand.Command = _imagesCommand
+ imagesCommand.SetUsageTemplate(UsageTemplate())
flags := imagesCommand.Flags()
flags.BoolVarP(&imagesCommand.All, "all", "a", false, "Show all images (default hides intermediate images)")
flags.BoolVar(&imagesCommand.Digests, "digests", false, "Show digests")
@@ -114,8 +115,6 @@ func init() {
flags.BoolVarP(&imagesCommand.Quiet, "quiet", "q", false, "Display only image IDs")
flags.StringVar(&imagesCommand.Sort, "sort", "created", "Sort by created, id, repository, size, or tag")
- rootCmd.AddCommand(imagesCommand.Command)
-
}
func imagesCmd(c *cliconfig.ImagesValues) error {
@@ -248,8 +247,12 @@ func getImagesTemplateOutput(ctx context.Context, images []*adapter.ContainerIma
}
// get all specified repo:tag pairs and print them separately
+ repopairs, err := image.ReposToMap(img.Names())
+ if err != nil {
+ logrus.Errorf("error finding tag/digest for %s", img.ID())
+ }
outer:
- for repo, tags := range image.ReposToMap(img.Names()) {
+ for repo, tags := range repopairs {
for _, tag := range tags {
size, err := img.Size(ctx)
var sizeStr string
diff --git a/cmd/podman/images_prune.go b/cmd/podman/images_prune.go
index ba99c5bde..cc0dcb99a 100644
--- a/cmd/podman/images_prune.go
+++ b/cmd/podman/images_prune.go
@@ -30,6 +30,7 @@ var (
func init() {
pruneImagesCommand.Command = _pruneImagesCommand
+ pruneImagesCommand.SetUsageTemplate(UsageTemplate())
flags := pruneImagesCommand.Flags()
flags.BoolVarP(&pruneImagesCommand.All, "all", "a", false, "Remove all unused images, not just dangling ones")
}
diff --git a/cmd/podman/import.go b/cmd/podman/import.go
index 52d144eb3..32f79757b 100644
--- a/cmd/podman/import.go
+++ b/cmd/podman/import.go
@@ -31,12 +31,12 @@ var (
func init() {
importCommand.Command = _importCommand
+ importCommand.SetUsageTemplate(UsageTemplate())
flags := importCommand.Flags()
flags.StringSliceVarP(&importCommand.Change, "change", "c", []string{}, "Apply the following possible instructions to the created image (default []): CMD | ENTRYPOINT | ENV | EXPOSE | LABEL | STOPSIGNAL | USER | VOLUME | WORKDIR")
flags.StringVarP(&importCommand.Message, "message", "m", "", "Set commit message for imported image")
flags.BoolVarP(&importCommand.Quiet, "quiet", "q", false, "Suppress output")
- rootCmd.AddCommand(importCommand.Command)
}
func importCmd(c *cliconfig.ImportValues) error {
diff --git a/cmd/podman/info.go b/cmd/podman/info.go
index 0896e16a4..06dbbd748 100644
--- a/cmd/podman/info.go
+++ b/cmd/podman/info.go
@@ -26,18 +26,18 @@ var (
infoCommand.GlobalFlags = MainGlobalOpts
return infoCmd(&infoCommand)
},
- Example: "",
+ Example: `podman info`,
}
)
func init() {
infoCommand.Command = _infoCommand
+ infoCommand.SetUsageTemplate(UsageTemplate())
flags := infoCommand.Flags()
flags.BoolVarP(&infoCommand.Debug, "debug", "D", false, "Display additional debug information")
flags.StringVarP(&infoCommand.Format, "format", "f", "", "Change the output format to JSON or a Go template")
- rootCmd.AddCommand(infoCommand.Command)
}
func infoCmd(c *cliconfig.InfoValues) error {
diff --git a/cmd/podman/inspect.go b/cmd/podman/inspect.go
index b2979c6ae..a1f3ef81f 100644
--- a/cmd/podman/inspect.go
+++ b/cmd/podman/inspect.go
@@ -34,19 +34,21 @@ 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`,
}
)
func init() {
inspectCommand.Command = _inspectCommand
+ inspectCommand.SetUsageTemplate(UsageTemplate())
flags := inspectCommand.Flags()
flags.StringVarP(&inspectCommand.TypeObject, "type", "t", inspectAll, "Return JSON for specified type, (e.g image, container or task)")
flags.StringVarP(&inspectCommand.Format, "format", "f", "", "Change the output format to a Go template")
flags.BoolVarP(&inspectCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of if the type is a container")
flags.BoolVarP(&inspectCommand.Size, "size", "s", false, "Display total file size if the type is container")
- rootCmd.AddCommand(inspectCommand.Command)
}
func inspectCmd(c *cliconfig.InspectValues) error {
diff --git a/cmd/podman/kill.go b/cmd/podman/kill.go
index 04c0fd531..d922cf721 100644
--- a/cmd/podman/kill.go
+++ b/cmd/podman/kill.go
@@ -34,13 +34,13 @@ var (
func init() {
killCommand.Command = _killCommand
+ killCommand.SetUsageTemplate(UsageTemplate())
flags := killCommand.Flags()
flags.BoolVarP(&killCommand.All, "all", "a", false, "Signal all running containers")
flags.StringVarP(&killCommand.Signal, "signal", "s", "KILL", "Signal to send to the container")
flags.BoolVarP(&killCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
- rootCmd.AddCommand(killCommand.Command)
}
// killCmd kills one or more containers with a signal
diff --git a/cmd/podman/load.go b/cmd/podman/load.go
index 90268ca8f..34a51cd0d 100644
--- a/cmd/podman/load.go
+++ b/cmd/podman/load.go
@@ -34,12 +34,12 @@ var (
func init() {
loadCommand.Command = _loadCommand
+ loadCommand.SetUsageTemplate(UsageTemplate())
flags := loadCommand.Flags()
flags.StringVarP(&loadCommand.Input, "input", "i", "/dev/stdin", "Read from archive file, default is STDIN")
flags.BoolVarP(&loadCommand.Quiet, "quiet", "q", false, "Suppress the output")
flags.StringVar(&loadCommand.SignaturePolicy, "signature-policy", "", "Pathname of signature policy file (not usually used)")
- rootCmd.AddCommand(loadCommand.Command)
}
// loadCmd gets the image/file to be loaded from the command line
diff --git a/cmd/podman/login.go b/cmd/podman/login.go
index 5ab0713e5..3eacab54a 100644
--- a/cmd/podman/login.go
+++ b/cmd/podman/login.go
@@ -29,12 +29,15 @@ 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`,
}
)
func init() {
loginCommand.Command = _loginCommand
+ loginCommand.SetUsageTemplate(UsageTemplate())
flags := loginCommand.Flags()
flags.StringVar(&loginCommand.Authfile, "authfile", "", "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override")
@@ -43,8 +46,8 @@ 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")
- rootCmd.AddCommand(loginCommand.Command)
}
// loginCmd uses the authentication package to store a user's authenticated credentials
@@ -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/logout.go b/cmd/podman/logout.go
index 02bde7857..5fecf814e 100644
--- a/cmd/podman/logout.go
+++ b/cmd/podman/logout.go
@@ -28,11 +28,11 @@ var (
func init() {
logoutCommand.Command = _logoutCommand
+ logoutCommand.SetUsageTemplate(UsageTemplate())
flags := logoutCommand.Flags()
flags.BoolVarP(&logoutCommand.All, "all", "a", false, "Remove the cached credentials for all registries in the auth file")
flags.StringVar(&logoutCommand.Authfile, "authfile", "", "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override")
- rootCmd.AddCommand(logoutCommand.Command)
}
// logoutCmd uses the authentication package to remove the authenticated of a registry
diff --git a/cmd/podman/logs.go b/cmd/podman/logs.go
index 83f900e63..6962a1f6d 100644
--- a/cmd/podman/logs.go
+++ b/cmd/podman/logs.go
@@ -32,6 +32,7 @@ var (
func init() {
logsCommand.Command = _logsCommand
+ logsCommand.SetUsageTemplate(UsageTemplate())
flags := logsCommand.Flags()
flags.BoolVar(&logsCommand.Details, "details", false, "Show extra details provided to the logs")
flags.BoolVarP(&logsCommand.Follow, "follow", "f", false, "Follow log output. The default is false")
@@ -43,7 +44,6 @@ func init() {
flags.SetInterspersed(false)
- rootCmd.AddCommand(logsCommand.Command)
}
func logsCmd(c *cliconfig.LogsValues) error {
diff --git a/cmd/podman/main.go b/cmd/podman/main.go
index 32ecaede7..f9820c075 100644
--- a/cmd/podman/main.go
+++ b/cmd/podman/main.go
@@ -27,6 +27,26 @@ var (
exitCode = 125
)
+// Commands that the remote and local client have
+// implemented.
+var mainCommands = []*cobra.Command{
+ _buildCommand,
+ _exportCommand,
+ _historyCommand,
+ _imagesCommand,
+ _importCommand,
+ _infoCommand,
+ _inspectCommand,
+ _killCommand,
+ _pullCommand,
+ _pushCommand,
+ _rmiCommand,
+ _tagCommand,
+ _versionCommand,
+ imageCommand.Command,
+ systemCommand.Command,
+}
+
var cmdsNotRequiringRootless = map[*cobra.Command]bool{
_versionCommand: true,
_createCommand: true,
@@ -40,7 +60,7 @@ var cmdsNotRequiringRootless = map[*cobra.Command]bool{
_killCommand: true,
_pauseCommand: true,
_restartCommand: true,
- _runCommmand: true,
+ _runCommand: true,
_unpauseCommand: true,
_searchCommand: true,
_statsCommand: true,
@@ -92,6 +112,8 @@ func init() {
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")
+ rootCmd.AddCommand(mainCommands...)
+ rootCmd.AddCommand(getMainCommands()...)
}
func initConfig() {
@@ -185,7 +207,7 @@ func main() {
exitCode = status.ExitStatus()
}
}
- fmt.Fprintln(os.Stderr, err.Error())
+ fmt.Fprintln(os.Stderr, "Error:", err.Error())
}
} else {
// The exitCode modified from 125, indicates an application
diff --git a/cmd/podman/mount.go b/cmd/podman/mount.go
index 36ca8bcfb..ce7c22d60 100644
--- a/cmd/podman/mount.go
+++ b/cmd/podman/mount.go
@@ -39,13 +39,13 @@ var (
func init() {
mountCommand.Command = _mountCommand
+ mountCommand.SetUsageTemplate(UsageTemplate())
flags := mountCommand.Flags()
flags.BoolVarP(&mountCommand.All, "all", "a", false, "Mount all containers")
flags.StringVar(&mountCommand.Format, "format", "", "Change the output format to Go template")
flags.BoolVarP(&mountCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
flags.BoolVar(&mountCommand.NoTrunc, "notruncate", false, "Do not truncate output")
- rootCmd.AddCommand(mountCommand.Command)
}
// jsonMountPoint stores info about each container
diff --git a/cmd/podman/pause.go b/cmd/podman/pause.go
index 466a3b136..a840cbe49 100644
--- a/cmd/podman/pause.go
+++ b/cmd/podman/pause.go
@@ -34,10 +34,10 @@ var (
func init() {
pauseCommand.Command = _pauseCommand
+ pauseCommand.SetUsageTemplate(UsageTemplate())
flags := pauseCommand.Flags()
flags.BoolVarP(&pauseCommand.All, "all", "a", false, "Pause all running containers")
- rootCmd.AddCommand(pauseCommand.Command)
}
func pauseCmd(c *cliconfig.PauseValues) error {
diff --git a/cmd/podman/play.go b/cmd/podman/play.go
index ff8320a6b..495a1f170 100644
--- a/cmd/podman/play.go
+++ b/cmd/podman/play.go
@@ -5,19 +5,18 @@ import (
"github.com/spf13/cobra"
)
-var playCommand cliconfig.PodmanCommand
-
-func init() {
- var playDescription = "Play a pod and its containers from a structured file."
- playCommand.Command = &cobra.Command{
+var (
+ playCommand cliconfig.PodmanCommand
+ playDescription = "Play a pod and its containers from a structured file."
+ _playCommand = &cobra.Command{
Use: "play",
Short: "Play a pod",
Long: playDescription,
}
-
-}
+)
func init() {
+ playCommand.Command = _playCommand
+ playCommand.SetUsageTemplate(UsageTemplate())
playCommand.AddCommand(getPlaySubCommands()...)
- rootCmd.AddCommand(playCommand.Command)
}
diff --git a/cmd/podman/play_kube.go b/cmd/podman/play_kube.go
index b314c1278..4ecd30cd4 100644
--- a/cmd/podman/play_kube.go
+++ b/cmd/podman/play_kube.go
@@ -43,6 +43,7 @@ var (
func init() {
playKubeCommand.Command = _playKubeCommand
+ playKubeCommand.SetUsageTemplate(UsageTemplate())
flags := playKubeCommand.Flags()
flags.StringVar(&playKubeCommand.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(&playKubeCommand.CertDir, "cert-dir", "", "`Pathname` of a directory containing TLS certificates and keys")
diff --git a/cmd/podman/pod.go b/cmd/podman/pod.go
index 4104c39c7..e988875ab 100644
--- a/cmd/podman/pod.go
+++ b/cmd/podman/pod.go
@@ -20,5 +20,5 @@ var podCommand = cliconfig.PodmanCommand{
func init() {
podCommand.AddCommand(getPodSubCommands()...)
- rootCmd.AddCommand(podCommand.Command)
+ podCommand.SetUsageTemplate(UsageTemplate())
}
diff --git a/cmd/podman/pod_create.go b/cmd/podman/pod_create.go
index 9ac5d94a9..0a0b86aab 100644
--- a/cmd/podman/pod_create.go
+++ b/cmd/podman/pod_create.go
@@ -9,7 +9,6 @@ import (
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod"
- "github.com/containers/libpod/pkg/rootless"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
@@ -39,6 +38,7 @@ var (
func init() {
podCreateCommand.Command = _podCreateCommand
+ podCreateCommand.SetUsageTemplate(UsageTemplate())
flags := podCreateCommand.Flags()
flags.SetInterspersed(false)
@@ -82,9 +82,6 @@ func podCreateCmd(c *cliconfig.PodCreateValues) error {
if !c.Infra {
return errors.Errorf("you must have an infra container to publish port bindings to the host")
}
- if rootless.IsRootless() {
- return errors.Errorf("rootless networking does not allow port binding to the host")
- }
}
if !c.Infra && c.Flag("share").Changed && c.Share != "none" && c.Share != "" {
diff --git a/cmd/podman/pod_inspect.go b/cmd/podman/pod_inspect.go
index f4c357e96..58b15328e 100644
--- a/cmd/podman/pod_inspect.go
+++ b/cmd/podman/pod_inspect.go
@@ -23,12 +23,13 @@ var (
podInspectCommand.GlobalFlags = MainGlobalOpts
return podInspectCmd(&podInspectCommand)
},
- Example: "[POD_NAME_OR_ID]",
+ Example: `podman pod inspect podID`,
}
)
func init() {
podInspectCommand.Command = _podInspectCommand
+ podInspectCommand.SetUsageTemplate(UsageTemplate())
flags := podInspectCommand.Flags()
flags.BoolVarP(&podInspectCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
diff --git a/cmd/podman/pod_kill.go b/cmd/podman/pod_kill.go
index 43411a988..febc820cd 100644
--- a/cmd/podman/pod_kill.go
+++ b/cmd/podman/pod_kill.go
@@ -30,6 +30,7 @@ var (
func init() {
podKillCommand.Command = _podKillCommand
+ podKillCommand.SetUsageTemplate(UsageTemplate())
flags := podKillCommand.Flags()
flags.BoolVarP(&podKillCommand.All, "all", "a", false, "Kill all containers in all pods")
flags.BoolVarP(&podKillCommand.Latest, "latest", "l", false, "Act on the latest pod podman is aware of")
diff --git a/cmd/podman/pod_pause.go b/cmd/podman/pod_pause.go
index a54783d88..2059727ae 100644
--- a/cmd/podman/pod_pause.go
+++ b/cmd/podman/pod_pause.go
@@ -27,6 +27,7 @@ var (
func init() {
podPauseCommand.Command = _podPauseCommand
+ podPauseCommand.SetUsageTemplate(UsageTemplate())
flags := podPauseCommand.Flags()
flags.BoolVarP(&podPauseCommand.All, "all", "a", false, "Pause all running pods")
flags.BoolVarP(&podPauseCommand.Latest, "latest", "l", false, "Act on the latest pod podman is aware of")
diff --git a/cmd/podman/pod_ps.go b/cmd/podman/pod_ps.go
index 991e294bf..49af91a1e 100644
--- a/cmd/podman/pod_ps.go
+++ b/cmd/podman/pod_ps.go
@@ -131,6 +131,7 @@ var (
func init() {
podPsCommand.Command = _podPsCommand
+ podPsCommand.SetUsageTemplate(UsageTemplate())
flags := podPsCommand.Flags()
flags.BoolVar(&podPsCommand.CtrNames, "ctr-names", false, "Display the container names")
flags.BoolVar(&podPsCommand.CtrIDs, "ctr-ids", false, "Display the container UUIDs. If no-trunc is not set they will be truncated")
diff --git a/cmd/podman/pod_restart.go b/cmd/podman/pod_restart.go
index 4d05205ea..f75d84956 100644
--- a/cmd/podman/pod_restart.go
+++ b/cmd/podman/pod_restart.go
@@ -28,6 +28,7 @@ var (
func init() {
podRestartCommand.Command = _podRestartCommand
+ podRestartCommand.SetUsageTemplate(UsageTemplate())
flags := podRestartCommand.Flags()
flags.BoolVarP(&podRestartCommand.All, "all", "a", false, "Restart all running pods")
flags.BoolVarP(&podRestartCommand.Latest, "latest", "l", false, "Restart the latest pod podman is aware of")
diff --git a/cmd/podman/pod_rm.go b/cmd/podman/pod_rm.go
index 445a641df..54cee2a50 100644
--- a/cmd/podman/pod_rm.go
+++ b/cmd/podman/pod_rm.go
@@ -26,12 +26,15 @@ 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`,
}
)
func init() {
podRmCommand.Command = _podRmCommand
+ podRmCommand.SetUsageTemplate(UsageTemplate())
flags := podRmCommand.Flags()
flags.BoolVarP(&podRmCommand.All, "all", "a", false, "Remove all running pods")
flags.BoolVarP(&podRmCommand.Force, "force", "f", false, "Force removal of a running pod by first stopping all containers, then removing all containers in the pod. The default is false")
diff --git a/cmd/podman/pod_start.go b/cmd/podman/pod_start.go
index 8b35d3e04..829fe2107 100644
--- a/cmd/podman/pod_start.go
+++ b/cmd/podman/pod_start.go
@@ -32,6 +32,7 @@ var (
func init() {
podStartCommand.Command = _podStartCommand
+ podStartCommand.SetUsageTemplate(UsageTemplate())
flags := podStartCommand.Flags()
flags.BoolVarP(&podStartCommand.All, "all", "a", false, "Start all pods")
flags.BoolVarP(&podStartCommand.Latest, "latest", "l", false, "Start the latest pod podman is aware of")
diff --git a/cmd/podman/pod_stats.go b/cmd/podman/pod_stats.go
index ccbcf9f7c..7afab6be9 100644
--- a/cmd/podman/pod_stats.go
+++ b/cmd/podman/pod_stats.go
@@ -2,7 +2,11 @@ package main
import (
"fmt"
+ "html/template"
+ "os"
+ "reflect"
"strings"
+ "text/tabwriter"
"time"
"encoding/json"
@@ -34,6 +38,7 @@ var (
func init() {
podStatsCommand.Command = _podStatsCommand
+ podStatsCommand.SetUsageTemplate(UsageTemplate())
flags := podStatsCommand.Flags()
flags.BoolVarP(&podStatsCommand.All, "all", "a", false, "Provide stats for all running pods")
flags.StringVar(&podStatsCommand.Format, "format", "", "Pretty-print container statistics to JSON or using a Go template")
@@ -136,6 +141,25 @@ func podStatsCmd(c *cliconfig.PodStatsValues) error {
step = 0
}
+ headerNames := make(map[string]string)
+ if c.Format != "" {
+ // Make a map of the field names for the headers
+ v := reflect.ValueOf(podStatOut{})
+ t := v.Type()
+ for i := 0; i < t.NumField(); i++ {
+ value := strings.ToUpper(splitCamelCase(t.Field(i).Name))
+ switch value {
+ case "CPU":
+ value = value + " %"
+ case "MEM":
+ value = value + " %"
+ case "MEM USAGE":
+ value = "MEM USAGE / LIMIT"
+ }
+ headerNames[t.Field(i).Name] = value
+ }
+ }
+
for i := 0; i < times; i += step {
var newStats []*libpod.PodContainerStats
for _, p := range pods {
@@ -163,7 +187,14 @@ func podStatsCmd(c *cliconfig.PodStatsValues) error {
outputJson(newStats)
} else {
- outputToStdOut(newStats)
+ results := podContainerStatsToPodStatOut(newStats)
+ if len(format) == 0 {
+ outputToStdOut(results)
+ } else {
+ if err := printPSFormat(c.Format, results, headerNames); err != nil {
+ return err
+ }
+ }
}
time.Sleep(time.Second)
previousPodStats := new([]*libpod.PodContainerStats)
@@ -177,28 +208,88 @@ func podStatsCmd(c *cliconfig.PodStatsValues) error {
return nil
}
-func outputToStdOut(stats []*libpod.PodContainerStats) {
- outFormat := ("%-14s %-14s %-12s %-6s %-19s %-6s %-19s %-19s %-4s\n")
- fmt.Printf(outFormat, "POD", "CID", "NAME", "CPU %", "MEM USAGE/ LIMIT", "MEM %", "NET IO", "BLOCK IO", "PIDS")
- for _, i := range stats {
- if len(i.ContainerStats) == 0 {
- fmt.Printf(outFormat, i.Pod.ID()[:12], "--", "--", "--", "--", "--", "--", "--", "--")
- }
- for _, c := range i.ContainerStats {
- cpu := floatToPercentString(c.CPU)
- memUsage := combineHumanValues(c.MemUsage, c.MemLimit)
- memPerc := floatToPercentString(c.MemPerc)
- netIO := combineHumanValues(c.NetInput, c.NetOutput)
- blockIO := combineHumanValues(c.BlockInput, c.BlockOutput)
- pids := pidsToString(c.PIDs)
- containerName := c.Name
- if len(c.Name) > 10 {
- containerName = containerName[:10]
+func podContainerStatsToPodStatOut(stats []*libpod.PodContainerStats) []*podStatOut {
+ var out []*podStatOut
+ for _, p := range stats {
+ for _, c := range p.ContainerStats {
+ o := podStatOut{
+ CPU: floatToPercentString(c.CPU),
+ MemUsage: combineHumanValues(c.MemUsage, c.MemLimit),
+ Mem: floatToPercentString(c.MemPerc),
+ NetIO: combineHumanValues(c.NetInput, c.NetOutput),
+ BlockIO: combineHumanValues(c.BlockInput, c.BlockOutput),
+ PIDS: pidsToString(c.PIDs),
+ CID: c.ContainerID[:12],
+ Name: c.Name,
+ Pod: p.Pod.ID()[:12],
}
- fmt.Printf(outFormat, i.Pod.ID()[:12], c.ContainerID[:12], containerName, cpu, memUsage, memPerc, netIO, blockIO, pids)
+ out = append(out, &o)
+ }
+ }
+ return out
+}
+
+type podStatOut struct {
+ CPU string
+ MemUsage string
+ Mem string
+ NetIO string
+ BlockIO string
+ PIDS string
+ Pod string
+ CID string
+ Name string
+}
+
+func printPSFormat(format string, stats []*podStatOut, headerNames map[string]string) error {
+ if len(stats) == 0 {
+ return nil
+ }
+
+ // Use a tabwriter to align column format
+ w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0)
+ // Spit out the header if "table" is present in the format
+ if strings.HasPrefix(format, "table") {
+ hformat := strings.Replace(strings.TrimSpace(format[5:]), " ", "\t", -1)
+ format = hformat
+ headerTmpl, err := template.New("header").Parse(hformat)
+ if err != nil {
+ return err
+ }
+ if err := headerTmpl.Execute(w, headerNames); err != nil {
+ return err
+ }
+ fmt.Fprintln(w, "")
+ }
+
+ // Spit out the data rows now
+ dataTmpl, err := template.New("data").Parse(format)
+ if err != nil {
+ return err
+ }
+ for _, container := range stats {
+ if err := dataTmpl.Execute(w, container); err != nil {
+ return err
+ }
+ fmt.Fprintln(w, "")
+ }
+ // Flush the writer
+ return w.Flush()
+
+}
+
+func outputToStdOut(stats []*podStatOut) {
+ w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
+ outFormat := ("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n")
+ fmt.Fprintf(w, outFormat, "POD", "CID", "NAME", "CPU %", "MEM USAGE/ LIMIT", "MEM %", "NET IO", "BLOCK IO", "PIDS")
+ for _, i := range stats {
+ if len(stats) == 0 {
+ fmt.Fprintf(w, outFormat, i.Pod, "--", "--", "--", "--", "--", "--", "--", "--")
+ } else {
+ fmt.Fprintf(w, outFormat, i.Pod, i.CID, i.Name, i.CPU, i.MemUsage, i.Mem, i.NetIO, i.BlockIO, i.PIDS)
}
}
- fmt.Println()
+ w.Flush()
}
func getPreviousPodContainerStats(podID string, prev []*libpod.PodContainerStats) map[string]*libpod.ContainerStats {
diff --git a/cmd/podman/pod_stop.go b/cmd/podman/pod_stop.go
index 63bd0f5cb..80082045d 100644
--- a/cmd/podman/pod_stop.go
+++ b/cmd/podman/pod_stop.go
@@ -33,6 +33,7 @@ var (
func init() {
podStopCommand.Command = _podStopCommand
+ podStopCommand.SetUsageTemplate(UsageTemplate())
flags := podStopCommand.Flags()
flags.BoolVarP(&podStopCommand.All, "all", "a", false, "Stop all running pods")
flags.BoolVarP(&podStopCommand.Latest, "latest", "l", false, "Stop the latest pod podman is aware of")
diff --git a/cmd/podman/pod_top.go b/cmd/podman/pod_top.go
index f1db2fac5..411c782bd 100644
--- a/cmd/podman/pod_top.go
+++ b/cmd/podman/pod_top.go
@@ -39,6 +39,7 @@ the latest pod.
func init() {
podTopCommand.Command = _podTopCommand
+ podTopCommand.SetUsageTemplate(UsageTemplate())
flags := podTopCommand.Flags()
flags.BoolVarP(&podTopCommand.Latest, "latest,", "l", false, "Act on the latest pod podman is aware of")
flags.BoolVar(&podTopCommand.ListDescriptors, "list-descriptors", false, "")
diff --git a/cmd/podman/pod_unpause.go b/cmd/podman/pod_unpause.go
index 17b771d4a..a917919c3 100644
--- a/cmd/podman/pod_unpause.go
+++ b/cmd/podman/pod_unpause.go
@@ -28,6 +28,7 @@ var (
func init() {
podUnpauseCommand.Command = _podUnpauseCommand
+ podUnpauseCommand.SetUsageTemplate(UsageTemplate())
flags := podUnpauseCommand.Flags()
flags.BoolVarP(&podUnpauseCommand.All, "all", "a", false, "Unpause all running pods")
flags.BoolVarP(&podUnpauseCommand.Latest, "latest", "l", false, "Unpause the latest pod podman is aware of")
diff --git a/cmd/podman/port.go b/cmd/podman/port.go
index 488ef2ffe..be84da065 100644
--- a/cmd/podman/port.go
+++ b/cmd/podman/port.go
@@ -34,12 +34,12 @@ var (
func init() {
portCommand.Command = _portCommand
+ portCommand.SetUsageTemplate(UsageTemplate())
flags := portCommand.Flags()
flags.BoolVarP(&portCommand.All, "all", "a", false, "Display port information for all containers")
flags.BoolVarP(&portCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
- rootCmd.AddCommand(portCommand.Command)
}
func portCmd(c *cliconfig.PortValues) error {
@@ -125,8 +125,13 @@ func portCmd(c *cliconfig.PortValues) error {
if c.All {
fmt.Println(con.ID())
}
+
+ portmappings, err := con.PortMappings()
+ if err != nil {
+ return err
+ }
// Iterate mappings
- for _, v := range con.Config().PortMappings {
+ for _, v := range portmappings {
hostIP := v.HostIP
// Set host IP to 0.0.0.0 if blank
if hostIP == "" {
diff --git a/cmd/podman/ps.go b/cmd/podman/ps.go
index 002975b87..949f78a34 100644
--- a/cmd/podman/ps.go
+++ b/cmd/podman/ps.go
@@ -172,6 +172,7 @@ var (
func init() {
psCommand.Command = _psCommand
+ psCommand.SetUsageTemplate(UsageTemplate())
flags := psCommand.Flags()
flags.BoolVarP(&psCommand.All, "all", "a", false, "Show all the containers, default is only running containers")
flags.StringSliceVarP(&psCommand.Filter, "filter", "f", []string{}, "Filter output based on conditions given")
@@ -187,9 +188,8 @@ func init() {
flags.StringVar(&psCommand.Sort, "sort", "created", "Sort output by command, created, id, image, names, runningfor, size, or status")
flags.BoolVar(&psCommand.Sync, "sync", false, "Sync container state with OCI runtime")
- rootCmd.AddCommand(psCommand.Command)
-
}
+
func psCmd(c *cliconfig.PsValues) error {
var (
filterFuncs []libpod.ContainerFilter
diff --git a/cmd/podman/pull.go b/cmd/podman/pull.go
index b9ef3f96b..6e060d6f5 100644
--- a/cmd/podman/pull.go
+++ b/cmd/podman/pull.go
@@ -42,6 +42,7 @@ specified, the image with the 'latest' tag (if it exists) is pulled
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")
@@ -51,7 +52,6 @@ func init() {
flags.StringVar(&pullCommand.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)")
flags.BoolVar(&pullCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries (default: true)")
- rootCmd.AddCommand(pullCommand.Command)
}
// pullCmd gets the data from the command line and calls pullImage
diff --git a/cmd/podman/push.go b/cmd/podman/push.go
index a1ee00a65..bbe8a4027 100644
--- a/cmd/podman/push.go
+++ b/cmd/podman/push.go
@@ -2,8 +2,6 @@ package main
import (
"fmt"
- "github.com/containers/libpod/cmd/podman/cliconfig"
- "github.com/spf13/cobra"
"io"
"os"
"strings"
@@ -11,11 +9,13 @@ import (
"github.com/containers/image/directory"
"github.com/containers/image/manifest"
"github.com/containers/image/types"
- "github.com/containers/libpod/cmd/podman/libpodruntime"
+ "github.com/containers/libpod/cmd/podman/cliconfig"
+ "github.com/containers/libpod/libpod/adapter"
"github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/util"
imgspecv1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
+ "github.com/spf13/cobra"
)
var (
@@ -40,6 +40,7 @@ var (
func init() {
pushCommand.Command = _pushCommand
+ pushCommand.SetUsageTemplate(UsageTemplate())
flags := pushCommand.Flags()
flags.MarkHidden("signature-policy")
flags.StringVar(&pushCommand.Authfile, "authfile", "", "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override")
@@ -52,7 +53,6 @@ func init() {
flags.StringVar(&pushCommand.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)")
flags.StringVar(&pushCommand.SignBy, "sign-by", "", "Add a signature at the destination using the specified key")
flags.BoolVar(&pushCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries (default: true)")
- rootCmd.AddCommand(pushCommand.Command)
}
func pushCmd(c *cliconfig.PushValues) error {
@@ -93,7 +93,7 @@ func pushCmd(c *cliconfig.PushValues) error {
registryCreds = creds
}
- runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
+ runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "could not create runtime")
}
@@ -131,12 +131,7 @@ func pushCmd(c *cliconfig.PushValues) error {
SignBy: signBy,
}
- newImage, err := runtime.ImageRuntime().NewFromLocal(srcName)
- if err != nil {
- return err
- }
-
authfile := getAuthFile(c.Authfile)
- return newImage.PushImageToHeuristicDestination(getContext(), destName, manifestType, authfile, c.SignaturePolicy, writer, c.Compress, so, &dockerRegistryOptions, nil)
+ return runtime.Push(getContext(), srcName, destName, manifestType, authfile, c.SignaturePolicy, writer, c.Compress, so, &dockerRegistryOptions, nil)
}
diff --git a/cmd/podman/refresh.go b/cmd/podman/refresh.go
index 3890188b4..641748452 100644
--- a/cmd/podman/refresh.go
+++ b/cmd/podman/refresh.go
@@ -27,7 +27,7 @@ var (
func init() {
refreshCommand.Command = _refreshCommand
- rootCmd.AddCommand(refreshCommand.Command)
+ refreshCommand.SetUsageTemplate(UsageTemplate())
}
func refreshCmd(c *cliconfig.RefreshValues) error {
diff --git a/cmd/podman/restart.go b/cmd/podman/restart.go
index f94e745ed..235107b5c 100644
--- a/cmd/podman/restart.go
+++ b/cmd/podman/restart.go
@@ -32,6 +32,7 @@ var (
func init() {
restartCommand.Command = _restartCommand
+ restartCommand.SetUsageTemplate(UsageTemplate())
flags := restartCommand.Flags()
flags.BoolVarP(&restartCommand.All, "all", "a", false, "Restart all non-running containers")
flags.BoolVarP(&restartCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
@@ -39,7 +40,6 @@ func init() {
flags.UintVarP(&restartCommand.Timeout, "timeout", "t", libpod.CtrRemoveTimeout, "Seconds to wait for stop before killing the container")
flags.UintVar(&restartCommand.Timeout, "time", libpod.CtrRemoveTimeout, "Seconds to wait for stop before killing the container")
- rootCmd.AddCommand(restartCommand.Command)
}
func restartCmd(c *cliconfig.RestartValues) error {
diff --git a/cmd/podman/restore.go b/cmd/podman/restore.go
index daee635f0..556cdb774 100644
--- a/cmd/podman/restore.go
+++ b/cmd/podman/restore.go
@@ -35,6 +35,7 @@ var (
func init() {
restoreCommand.Command = _restoreCommand
+ restoreCommand.SetUsageTemplate(UsageTemplate())
flags := restoreCommand.Flags()
flags.BoolVarP(&restoreCommand.All, "all", "a", false, "Restore all checkpointed containers")
flags.BoolVarP(&restoreCommand.Keep, "keep", "k", false, "Keep all temporary checkpoint files")
@@ -42,7 +43,6 @@ func init() {
// TODO: add ContainerStateCheckpointed
flags.BoolVar(&restoreCommand.TcpEstablished, "tcp-established", false, "Checkpoint a container with established TCP connections")
- rootCmd.AddCommand(restoreCommand.Command)
}
func restoreCmd(c *cliconfig.RestoreValues) error {
diff --git a/cmd/podman/rm.go b/cmd/podman/rm.go
index bb9a913c9..d170e5357 100644
--- a/cmd/podman/rm.go
+++ b/cmd/podman/rm.go
@@ -6,6 +6,7 @@ import (
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/cmd/podman/shared"
+ "github.com/containers/libpod/libpod"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
@@ -33,13 +34,12 @@ Running containers will not be removed without the -f option.
func init() {
rmCommand.Command = _rmCommand
+ rmCommand.SetUsageTemplate(UsageTemplate())
flags := rmCommand.Flags()
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.BoolVarP(&rmCommand.Volumes, "volumes", "v", false, "Remove the volumes associated with the container (Not implemented yet)")
-
- rootCmd.AddCommand(rmCommand.Command)
+ flags.BoolVarP(&rmCommand.Volumes, "volumes", "v", false, "Remove the volumes associated with the container")
}
// saveCmd saves the image to either docker-archive or oci
@@ -61,16 +61,24 @@ func rmCmd(c *cliconfig.RmValues) error {
delContainers, err := getAllOrLatestContainers(&c.PodmanCommand, runtime, -1, "all")
if err != nil {
+ if c.Force && len(c.InputArgs) > 0 {
+ if errors.Cause(err) == libpod.ErrNoSuchCtr {
+ err = nil
+ }
+ runtime.RemoveContainersFromStorage(c.InputArgs)
+ }
if len(delContainers) == 0 {
return err
}
- fmt.Println(err.Error())
+ if err != nil {
+ fmt.Println(err.Error())
+ }
}
for _, container := range delContainers {
con := container
f := func() error {
- return runtime.RemoveContainer(ctx, con, c.Force)
+ return runtime.RemoveContainer(ctx, con, c.Force, c.Volumes)
}
deleteFuncs = append(deleteFuncs, shared.ParallelWorkerInput{
diff --git a/cmd/podman/rmi.go b/cmd/podman/rmi.go
index 70f58e844..c5bd1e190 100644
--- a/cmd/podman/rmi.go
+++ b/cmd/podman/rmi.go
@@ -29,11 +29,10 @@ var (
func init() {
rmiCommand.Command = _rmiCommand
+ rmiCommand.SetUsageTemplate(UsageTemplate())
flags := rmiCommand.Flags()
flags.BoolVarP(&rmiCommand.All, "all", "a", false, "Remove all images")
flags.BoolVarP(&rmiCommand.Force, "force", "f", false, "Force Removal of the image")
-
- rootCmd.AddCommand(rmiCommand.Command)
}
func rmiCmd(c *cliconfig.RmiValues) error {
diff --git a/cmd/podman/run.go b/cmd/podman/run.go
index 76b29cb84..64f8b6856 100644
--- a/cmd/podman/run.go
+++ b/cmd/podman/run.go
@@ -18,30 +18,29 @@ import (
)
var (
- runCommmand cliconfig.RunValues
+ runCommand cliconfig.RunValues
runDescription = "Runs a command in a new container from the given image"
- _runCommmand = &cobra.Command{
+ _runCommand = &cobra.Command{
Use: "run",
Short: "Run a command in a new container",
Long: runDescription,
RunE: func(cmd *cobra.Command, args []string) error {
- runCommmand.InputArgs = args
- runCommmand.GlobalFlags = MainGlobalOpts
- return runCmd(&runCommmand)
+ runCommand.InputArgs = args
+ runCommand.GlobalFlags = MainGlobalOpts
+ return runCmd(&runCommand)
},
Example: "IMAGE [COMMAND [ARG...]]",
}
)
func init() {
- runCommmand.Command = _runCommmand
- flags := runCommmand.Flags()
+ runCommand.Command = _runCommand
+ runCommand.SetUsageTemplate(UsageTemplate())
+ flags := runCommand.Flags()
flags.SetInterspersed(false)
flags.Bool("sig-proxy", true, "Proxy received signals to the process (default true)")
- getCreateFlags(&runCommmand.PodmanCommand)
-
- rootCmd.AddCommand(runCommmand.Command)
+ getCreateFlags(&runCommand.PodmanCommand)
}
func runCmd(c *cliconfig.RunValues) error {
@@ -119,13 +118,21 @@ func runCmd(c *cliconfig.RunValues) error {
}
}
if err := startAttachCtr(ctr, outputStream, errorStream, inputStream, c.String("detach-keys"), c.Bool("sig-proxy"), true); err != nil {
+ // We've manually detached from the container
+ // Do not perform cleanup, or wait for container exit code
+ // Just exit immediately
+ if errors.Cause(err) == libpod.ErrDetach {
+ exitCode = 0
+ return nil
+ }
+
// This means the command did not exist
exitCode = 127
if strings.Index(err.Error(), "permission denied") > -1 {
exitCode = 126
}
if c.IsSet("rm") {
- if deleteError := runtime.RemoveContainer(ctx, ctr, true); deleteError != nil {
+ if deleteError := runtime.RemoveContainer(ctx, ctr, true, false); deleteError != nil {
logrus.Errorf("unable to remove container %s after failing to start and attach to it", ctr.ID())
}
}
@@ -148,28 +155,12 @@ func runCmd(c *cliconfig.RunValues) error {
exitCode = int(ecode)
}
- if createConfig.Rm {
- return runtime.RemoveContainer(ctx, ctr, true)
- }
-
- if err := ctr.Cleanup(ctx); err != nil {
- // If the container has been removed already, no need to error on cleanup
- // Also, if it was restarted, don't error either
- if errors.Cause(err) == libpod.ErrNoSuchCtr ||
- errors.Cause(err) == libpod.ErrCtrRemoved ||
- errors.Cause(err) == libpod.ErrCtrStateInvalid {
- return nil
- }
-
- return err
- }
-
return nil
}
// Read a container's exit file
func readExitFile(runtimeTmp, ctrID string) (int, error) {
- exitFile := filepath.Join(runtimeTmp, "exits", ctrID)
+ exitFile := filepath.Join(runtimeTmp, "exits", fmt.Sprintf("%s-old", ctrID))
logrus.Debugf("Attempting to read container %s exit code from file %s", ctrID, exitFile)
diff --git a/cmd/podman/runlabel.go b/cmd/podman/runlabel.go
index ff8a282d3..f1c61ebda 100644
--- a/cmd/podman/runlabel.go
+++ b/cmd/podman/runlabel.go
@@ -37,6 +37,7 @@ Executes a command as described by a container image label.
func init() {
runlabelCommand.Command = _runlabelCommand
+ runlabelCommand.SetUsageTemplate(UsageTemplate())
flags := runlabelCommand.Flags()
flags.StringVar(&runlabelCommand.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(&runlabelCommand.CertDir, "cert-dir", "", "`Pathname` of a directory containing TLS certificates and keys")
diff --git a/cmd/podman/save.go b/cmd/podman/save.go
index 766561f1a..1ae1bc872 100644
--- a/cmd/podman/save.go
+++ b/cmd/podman/save.go
@@ -47,13 +47,12 @@ var (
func init() {
saveCommand.Command = _saveCommand
+ saveCommand.SetUsageTemplate(UsageTemplate())
flags := saveCommand.Flags()
flags.BoolVar(&saveCommand.Compress, "compress", false, "Compress tarball image layers when saving to a directory using the 'dir' transport. (default is same compression type as source)")
flags.StringVar(&saveCommand.Format, "format", "", "Save image to oci-archive, oci-dir (directory with oci manifest type), docker-dir (directory with v2s2 manifest type)")
flags.StringVarP(&saveCommand.Output, "output", "o", "/dev/stdout", "Write to a file, default is STDOUT")
flags.BoolVarP(&saveCommand.Quiet, "quiet", "q", false, "Suppress the output")
-
- rootCmd.AddCommand(saveCommand.Command)
}
// saveCmd saves the image to either docker-archive or oci
diff --git a/cmd/podman/search.go b/cmd/podman/search.go
index b15da1f6d..2febee689 100644
--- a/cmd/podman/search.go
+++ b/cmd/podman/search.go
@@ -43,6 +43,7 @@ var (
func init() {
searchCommand.Command = _searchCommand
+ searchCommand.SetUsageTemplate(UsageTemplate())
flags := searchCommand.Flags()
flags.StringVar(&searchCommand.Authfile, "authfile", "", "Path of the authentication file. Default is ${XDG_RUNTIME_DIR}/containers/auth.json. Use REGISTRY_AUTH_FILE environment variable to override")
flags.StringSliceVarP(&searchCommand.Filter, "filter", "f", []string{}, "Filter output based on conditions provided (default [])")
@@ -50,8 +51,6 @@ func init() {
flags.IntVar(&searchCommand.Limit, "limit", 0, "Limit the number of results")
flags.BoolVar(&searchCommand.NoTrunc, "no-trunc", false, "Do not truncate the output")
flags.BoolVar(&searchCommand.TlsVerify, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries (default: true)")
-
- rootCmd.AddCommand(searchCommand.Command)
}
type searchParams struct {
diff --git a/cmd/podman/shared/container.go b/cmd/podman/shared/container.go
index c74d8fdce..81811e0f2 100644
--- a/cmd/podman/shared/container.go
+++ b/cmd/podman/shared/container.go
@@ -213,11 +213,16 @@ func NewBatchContainer(ctr *libpod.Container, opts PsOptions) (PsContainerOutput
}
}
+ ports, err := ctr.PortMappings()
+ if err != nil {
+ logrus.Errorf("unable to lookup namespace container for %s", ctr.ID())
+ }
+
pso.ID = cid
pso.Image = imageName
pso.Command = command
pso.Created = created
- pso.Ports = portsToString(ctr.PortMappings())
+ pso.Ports = portsToString(ports)
pso.Names = ctr.Name()
pso.IsInfra = ctr.IsInfra()
pso.Status = status
diff --git a/cmd/podman/sign.go b/cmd/podman/sign.go
index a87c12556..ac0d985f5 100644
--- a/cmd/podman/sign.go
+++ b/cmd/podman/sign.go
@@ -38,12 +38,11 @@ var (
func init() {
signCommand.Command = _signCommand
+ signCommand.SetUsageTemplate(UsageTemplate())
flags := signCommand.Flags()
flags.StringVarP(&signCommand.Directory, "directory", "d", "", "Define an alternate directory to store signatures")
flags.StringVar(&signCommand.SignBy, "sign-by", "", "Name of the signing key")
- rootCmd.AddCommand(signCommand.Command)
-
}
// SignatureStoreDir defines default directory to store signatures
diff --git a/cmd/podman/start.go b/cmd/podman/start.go
index 483ab4081..3a606d662 100644
--- a/cmd/podman/start.go
+++ b/cmd/podman/start.go
@@ -36,14 +36,13 @@ var (
func init() {
startCommand.Command = _startCommand
+ startCommand.SetUsageTemplate(UsageTemplate())
flags := startCommand.Flags()
flags.BoolVarP(&startCommand.Attach, "attach", "a", false, "Attach container's STDOUT and STDERR")
flags.StringVar(&startCommand.DetachKeys, "detach-keys", "", "Override the key sequence for detaching a container. Format is a single character [a-Z] or ctrl-<value> where <value> is one of: a-z, @, ^, [, , or _")
flags.BoolVarP(&startCommand.Interactive, "interactive", "i", false, "Keep STDIN open even if not attached")
flags.BoolVarP(&startCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
flags.BoolVar(&startCommand.SigProxy, "sig-proxy", true, "Proxy received signals to the process (default true if attaching, false otherwise)")
-
- rootCmd.AddCommand(startCommand.Command)
}
func startCmd(c *cliconfig.StartValues) error {
@@ -109,6 +108,13 @@ func startCmd(c *cliconfig.StartValues) error {
// attach to the container and also start it not already running
err = startAttachCtr(ctr, os.Stdout, os.Stderr, inputStream, c.DetachKeys, sigProxy, !ctrRunning)
+ if errors.Cause(err) == libpod.ErrDetach {
+ // User manually detached
+ // Exit cleanly immediately
+ exitCode = 0
+ return nil
+ }
+
if ctrRunning {
return err
}
@@ -138,7 +144,7 @@ func startCmd(c *cliconfig.StartValues) error {
logrus.Errorf("unable to detect if container %s should be deleted", ctr.ID())
}
if createArtifact.Rm {
- if rmErr := runtime.RemoveContainer(ctx, ctr, true); rmErr != nil {
+ if rmErr := runtime.RemoveContainer(ctx, ctr, true, false); rmErr != nil {
logrus.Errorf("unable to remove container %s after it failed to start", ctr.ID())
}
}
diff --git a/cmd/podman/stats.go b/cmd/podman/stats.go
index 8c79ed290..af9bbad0e 100644
--- a/cmd/podman/stats.go
+++ b/cmd/podman/stats.go
@@ -47,14 +47,13 @@ var (
func init() {
statsCommand.Command = _statsCommand
+ statsCommand.SetUsageTemplate(UsageTemplate())
flags := statsCommand.Flags()
flags.BoolVarP(&statsCommand.All, "all", "a", false, "Show all containers. Only running containers are shown by default. The default is false")
flags.StringVar(&statsCommand.Format, "format", "", "Pretty-print container statistics to JSON or using a Go template")
flags.BoolVarP(&statsCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
flags.BoolVar(&statsCommand.NoReset, "no-reset", false, "Disable resetting the screen between intervals")
flags.BoolVar(&statsCommand.NoStream, "no-stream", false, "Disable streaming stats and only pull the first result, default setting is false")
-
- rootCmd.AddCommand(statsCommand.Command)
}
func statsCmd(c *cliconfig.StatsValues) error {
diff --git a/cmd/podman/stop.go b/cmd/podman/stop.go
index e2c16fe20..134d8a069 100644
--- a/cmd/podman/stop.go
+++ b/cmd/podman/stop.go
@@ -37,13 +37,12 @@ var (
func init() {
stopCommand.Command = _stopCommand
+ stopCommand.SetUsageTemplate(UsageTemplate())
flags := stopCommand.Flags()
flags.BoolVarP(&stopCommand.All, "all", "a", false, "Stop all running containers")
flags.BoolVarP(&stopCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
flags.UintVar(&stopCommand.Timeout, "time", libpod.CtrRemoveTimeout, "Seconds to wait for stop before killing the container")
flags.UintVarP(&stopCommand.Timeout, "timeout", "t", libpod.CtrRemoveTimeout, "Seconds to wait for stop before killing the container")
-
- rootCmd.AddCommand(stopCommand.Command)
}
func stopCmd(c *cliconfig.StopValues) error {
diff --git a/cmd/podman/system.go b/cmd/podman/system.go
index f6b28fee1..741b79da5 100644
--- a/cmd/podman/system.go
+++ b/cmd/podman/system.go
@@ -17,7 +17,12 @@ var (
}
)
+var systemCommands = []*cobra.Command{
+ _infoCommand,
+}
+
func init() {
+ systemCommand.AddCommand(systemCommands...)
systemCommand.AddCommand(getSystemSubCommands()...)
- rootCmd.AddCommand(systemCommand.Command)
+ systemCommand.SetUsageTemplate(UsageTemplate())
}
diff --git a/cmd/podman/system_prune.go b/cmd/podman/system_prune.go
index c918fbe3b..a91d7bf0a 100644
--- a/cmd/podman/system_prune.go
+++ b/cmd/podman/system_prune.go
@@ -34,8 +34,8 @@ var (
)
func init() {
-
pruneSystemCommand.Command = _pruneSystemCommand
+ pruneSystemCommand.SetUsageTemplate(UsageTemplate())
flags := pruneSystemCommand.Flags()
flags.BoolVarP(&pruneSystemCommand.All, "all", "a", false, "Remove all unused data")
flags.BoolVarP(&pruneSystemCommand.Force, "force", "f", false, "Do not prompt for confirmation")
@@ -76,7 +76,7 @@ Are you sure you want to continue? [y/N] `, volumeString)
ctx := getContext()
fmt.Println("Deleted Containers")
- lasterr := pruneContainers(runtime, ctx, shared.Parallelize("rm"), false)
+ lasterr := pruneContainers(runtime, ctx, shared.Parallelize("rm"), false, false)
if c.Bool("volumes") {
fmt.Println("Deleted Volumes")
err := volumePrune(runtime, getContext())
diff --git a/cmd/podman/tag.go b/cmd/podman/tag.go
index 2c7cf4abb..135c2f7a0 100644
--- a/cmd/podman/tag.go
+++ b/cmd/podman/tag.go
@@ -26,8 +26,7 @@ var (
func init() {
tagCommand.Command = _tagCommand
- rootCmd.AddCommand(tagCommand.Command)
-
+ tagCommand.SetUsageTemplate(UsageTemplate())
}
func tagCmd(c *cliconfig.TagValues) error {
diff --git a/cmd/podman/top.go b/cmd/podman/top.go
index a03830ee5..51b813e5a 100644
--- a/cmd/podman/top.go
+++ b/cmd/podman/top.go
@@ -48,12 +48,11 @@ the latest container.
func init() {
topCommand.Command = _topCommand
+ topCommand.SetUsageTemplate(UsageTemplate())
flags := topCommand.Flags()
flags.BoolVar(&topCommand.ListDescriptors, "list-descriptors", false, "")
flags.MarkHidden("list-descriptors")
flags.BoolVarP(&topCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
-
- rootCmd.AddCommand(topCommand.Command)
}
func topCmd(c *cliconfig.TopValues) error {
diff --git a/cmd/podman/trust.go b/cmd/podman/trust.go
index 6304586c3..8b02dcdc6 100644
--- a/cmd/podman/trust.go
+++ b/cmd/podman/trust.go
@@ -16,6 +16,7 @@ var (
)
func init() {
+ trustCommand.SetUsageTemplate(UsageTemplate())
trustCommand.AddCommand(getTrustSubCommands()...)
imageCommand.AddCommand(trustCommand.Command)
}
diff --git a/cmd/podman/trust_set_show.go b/cmd/podman/trust_set_show.go
index cd9438220..f3d1cadce 100644
--- a/cmd/podman/trust_set_show.go
+++ b/cmd/podman/trust_set_show.go
@@ -49,9 +49,10 @@ var (
)
func init() {
-
setTrustCommand.Command = _setTrustCommand
+ setTrustCommand.SetUsageTemplate(UsageTemplate())
showTrustCommand.Command = _showTrustCommand
+ showTrustCommand.SetUsageTemplate(UsageTemplate())
setFlags := setTrustCommand.Flags()
setFlags.StringVar(&setTrustCommand.PolicyPath, "policypath", "", "")
setFlags.MarkHidden("policypath")
diff --git a/cmd/podman/umount.go b/cmd/podman/umount.go
index 4622e8276..20ea410c2 100644
--- a/cmd/podman/umount.go
+++ b/cmd/podman/umount.go
@@ -37,12 +37,11 @@ An unmount can be forced with the --force flag.
func init() {
umountCommand.Command = _umountCommand
+ umountCommand.SetUsageTemplate(UsageTemplate())
flags := umountCommand.Flags()
flags.BoolVarP(&umountCommand.All, "all", "a", false, "Umount all of the currently mounted containers")
flags.BoolVarP(&umountCommand.Force, "force", "f", false, "Force the complete umount all of the currently mounted containers")
flags.BoolVarP(&umountCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
-
- rootCmd.AddCommand(umountCommand.Command)
}
func umountCmd(c *cliconfig.UmountValues) error {
diff --git a/cmd/podman/unpause.go b/cmd/podman/unpause.go
index fb3a7b57a..c8f85cfd3 100644
--- a/cmd/podman/unpause.go
+++ b/cmd/podman/unpause.go
@@ -35,10 +35,9 @@ var (
func init() {
unpauseCommand.Command = _unpauseCommand
+ unpauseCommand.SetUsageTemplate(UsageTemplate())
flags := unpauseCommand.Flags()
flags.BoolVarP(&unpauseCommand.All, "all", "a", false, "Unpause all paused containers")
-
- rootCmd.AddCommand(unpauseCommand.Command)
}
func unpauseCmd(c *cliconfig.UnpauseValues) error {
diff --git a/cmd/podman/varlink.go b/cmd/podman/varlink.go
index 2b76e034e..ce54cfa85 100644
--- a/cmd/podman/varlink.go
+++ b/cmd/podman/varlink.go
@@ -1,4 +1,4 @@
-// +build varlink
+// +build varlink,!remoteclient
package main
@@ -38,10 +38,9 @@ var (
func init() {
varlinkCommand.Command = _varlinkCommand
+ varlinkCommand.SetUsageTemplate(UsageTemplate())
flags := varlinkCommand.Flags()
flags.Int64VarP(&varlinkCommand.Timeout, "timeout", "t", 1000, "Time until the varlink session expires in milliseconds. Use 0 to disable the timeout")
-
- rootCmd.AddCommand(varlinkCommand.Command)
}
func varlinkCmd(c *cliconfig.VarlinkValues) error {
@@ -84,7 +83,7 @@ func varlinkCmd(c *cliconfig.VarlinkValues) error {
logrus.Infof("varlink service expired (use --timeout to increase session time beyond %d ms, 0 means never timeout)", c.Int64("timeout"))
return nil
default:
- return errors.Errorf("unable to start varlink service")
+ return errors.Wrapf(err, "unable to start varlink service")
}
}
diff --git a/cmd/podman/varlink/io.podman.varlink b/cmd/podman/varlink/io.podman.varlink
index 101232b0c..697d9ed90 100644
--- a/cmd/podman/varlink/io.podman.varlink
+++ b/cmd/podman/varlink/io.podman.varlink
@@ -2,15 +2,13 @@
# in the [API.md](https://github.com/containers/libpod/blob/master/API.md) file in the upstream libpod repository.
interface io.podman
-
-# Version is the structure returned by GetVersion
-type Version (
- version: string,
- go_version: string,
- git_commit: string,
- built: int,
- os_arch: string,
- remote_api_version: int
+type Volume (
+ name: string,
+ labels: [string]string,
+ mountPoint: string,
+ driver: string,
+ options: [string]string,
+ scope: string
)
type NotImplemented (
@@ -20,6 +18,7 @@ type NotImplemented (
type StringResponse (
message: string
)
+
# ContainerChanges describes the return struct for ListContainerChanges
type ContainerChanges (
changed: []string,
@@ -27,14 +26,25 @@ type ContainerChanges (
deleted: []string
)
-# ImageInList describes the structure that is returned in
-# ListImages.
-type ImageInList (
+type VolumeCreateOpts (
+ volumeName: string,
+ driver: string,
+ labels: [string]string,
+ options: [string]string
+)
+
+type VolumeRemoveOpts (
+ volumes: []string,
+ all: bool,
+ force: bool
+)
+
+type Image (
id: string,
parentId: string,
repoTags: []string,
repoDigests: []string,
- created: string,
+ created: string, # as RFC3339
size: int,
virtualSize: int,
containers: int,
@@ -45,16 +55,15 @@ type ImageInList (
# ImageHistory describes the returned structure from ImageHistory.
type ImageHistory (
id: string,
- created: string,
+ created: string, # as RFC3339
createdBy: string,
tags: []string,
size: int,
comment: string
)
-# ImageSearch is the returned structure for SearchImage. It is returned
-# in array form.
-type ImageSearch (
+# Represents a single search result from SearchImages
+type ImageSearchResult (
description: string,
is_official: bool,
is_automated: bool,
@@ -62,13 +71,12 @@ type ImageSearch (
star_count: int
)
-# ListContainerData is the returned struct for an individual container
-type ListContainerData (
+type Container (
id: string,
image: string,
imageid: string,
command: []string,
- createdat: string,
+ createdat: string, # as RFC3339
runningfor: string,
status: string,
ports: []ContainerPortMappings,
@@ -303,37 +311,54 @@ type IDMap (
size: int
)
+# BuildOptions are are used to describe describe physical attributes of the build
+type BuildOptions (
+ addHosts: []string,
+ cgroupParent: string,
+ cpuPeriod: int,
+ cpuQuota: int,
+ cpuShares: int,
+ cpusetCpus: string,
+ cpusetMems: string,
+ memory: int,
+ memorySwap: int,
+ shmSize: string,
+ ulimit: []string,
+ volume: []string
+)
+
# BuildInfo is used to describe user input for building images
type BuildInfo (
- # paths to one or more dockerfiles
- dockerfile: []string,
- tags: []string,
- add_hosts: []string,
- cgroup_parent: string,
- cpu_period: int,
- cpu_quota: int,
- cpu_shares: int,
- cpuset_cpus: string,
- cpuset_mems: string,
- memory: string,
- memory_swap: string,
- security_opts: []string,
- shm_size: string,
- ulimit: []string,
- volume: []string,
- squash: bool,
- pull: bool,
- pull_always: bool,
- force_rm: bool,
- rm: bool,
- label: []string,
+ additionalTags: []string,
annotations: []string,
- build_args: [string]string,
- image_format: string
+ buildArgs: [string]string,
+ buildOptions: BuildOptions,
+ cniConfigDir: string,
+ cniPluginDir: string,
+ compression: string,
+ contextDir: string,
+ defaultsMountFilePath: string,
+ dockerfiles: []string,
+ err: string,
+ forceRmIntermediateCtrs: bool,
+ iidfile: string,
+ label: []string,
+ layers: bool,
+ nocache: bool,
+ out: string,
+ output: string,
+ outputFormat: string,
+ pullPolicy: string,
+ quiet: bool,
+ remoteIntermediateCtrs: bool,
+ reportWriter: string,
+ runtimeArgs: []string,
+ signaturePolicyPath: string,
+ squash: bool
)
-# BuildResponse is used to describe the responses for building images
-type BuildResponse (
+# MoreResponse is a struct for when responses from varlink requires longer output
+type MoreResponse (
logs: []string,
id: string
)
@@ -387,40 +412,35 @@ type Runlabel(
name: string,
pull: bool,
signaturePolicyPath: string,
- tlsVerify: bool,
+ tlsVerify: ?bool,
label: string,
extraArgs: []string,
opts: [string]string
)
-# Ping provides a response for developers to ensure their varlink setup is working.
-# #### Example
-# ~~~
-# $ varlink call -m unix:/run/podman/io.podman/io.podman.Ping
-# {
-# "ping": {
-# "message": "OK"
-# }
-# }
-# ~~~
-method Ping() -> (ping: StringResponse)
-
-# GetVersion returns a Version structure describing the libpod setup on their
-# system.
-method GetVersion() -> (version: Version)
+# GetVersion returns version and build information of the podman service
+method GetVersion() -> (
+ version: string,
+ go_version: string,
+ git_commit: string,
+ built: string, # as RFC3339
+ os_arch: string,
+ remote_api_version: int
+)
# GetInfo returns a [PodmanInfo](#PodmanInfo) struct that describes podman and its host such as storage stats,
# build information of Podman, and system-wide registries.
method GetInfo() -> (info: PodmanInfo)
-# ListContainers returns a list of containers in no particular order. There are
-# returned as an array of ListContainerData structs. See also [GetContainer](#GetContainer).
-method ListContainers() -> (containers: []ListContainerData)
+# ListContainers returns information about all containers.
+# See also [GetContainer](#GetContainer).
+method ListContainers() -> (containers: []Container)
-# GetContainer takes a name or ID of a container and returns single ListContainerData
-# structure. A [ContainerNotFound](#ContainerNotFound) error will be returned if the container cannot be found.
-# See also [ListContainers](ListContainers) and [InspectContainer](#InspectContainer).
-method GetContainer(name: string) -> (container: ListContainerData)
+# GetContainer returns information about a single container. If a container
+# with the given id doesn't exist, a [ContainerNotFound](#ContainerNotFound)
+# error will be returned. See also [ListContainers](ListContainers) and
+# [InspectContainer](#InspectContainer).
+method GetContainer(id: string) -> (container: Container)
# CreateContainer creates a new container from an image. It uses a [Create](#Create) type for input. The minimum
# input required for CreateContainer is an image name. If the image name is not found, an [ImageNotFound](#ImageNotFound)
@@ -508,7 +528,7 @@ method ExportContainer(name: string, path: string) -> (tarfile: string)
method GetContainerStats(name: string) -> (container: ContainerStats)
# This method has not be implemented yet.
-method ResizeContainerTty() -> (notimplemented: NotImplemented)
+# method ResizeContainerTty() -> (notimplemented: NotImplemented)
# StartContainer starts a created or stopped container. It takes the name or ID of container. It returns
# the container ID once started. If the container cannot be found, a [ContainerNotFound](#ContainerNotFound)
@@ -540,10 +560,10 @@ method RestartContainer(name: string, timeout: int) -> (container: string)
method KillContainer(name: string, signal: int) -> (container: string)
# This method has not be implemented yet.
-method UpdateContainer() -> (notimplemented: NotImplemented)
+# method UpdateContainer() -> (notimplemented: NotImplemented)
# This method has not be implemented yet.
-method RenameContainer() -> (notimplemented: NotImplemented)
+# method RenameContainer() -> (notimplemented: NotImplemented)
# PauseContainer takes the name or ID of container and pauses it. If the container cannot be found,
# a [ContainerNotFound](#ContainerNotFound) error will be returned; otherwise the ID of the container is returned.
@@ -556,7 +576,7 @@ method PauseContainer(name: string) -> (container: string)
method UnpauseContainer(name: string) -> (container: string)
# This method has not be implemented yet.
-method AttachToContainer() -> (notimplemented: NotImplemented)
+# method AttachToContainer() -> (notimplemented: NotImplemented)
# GetAttachSockets takes the name or ID of an existing container. It returns file paths for two sockets needed
# to properly communicate with a container. The first is the actual I/O socket that the container uses. The
@@ -580,7 +600,7 @@ method GetAttachSockets(name: string) -> (sockets: Sockets)
# a [ContainerNotFound](#ContainerNotFound) error is returned.
method WaitContainer(name: string) -> (exitcode: int)
-# RemoveContainer takes requires the name or ID of container as well a boolean representing whether a running
+# RemoveContainer takes requires the name or ID of container as well a boolean representing whether a running and a boolean indicating whether to remove builtin volumes
# container can be stopped and removed. Upon successful removal of the container, its ID is returned. If the
# container cannot be found by name or ID, a [ContainerNotFound](#ContainerNotFound) error will be returned.
# #### Example
@@ -590,7 +610,7 @@ method WaitContainer(name: string) -> (exitcode: int)
# "container": "62f4fd98cb57f529831e8f90610e54bba74bd6f02920ffb485e15376ed365c20"
# }
# ~~~
-method RemoveContainer(name: string, force: bool) -> (container: string)
+method RemoveContainer(name: string, force: bool, removeVolumes: bool) -> (container: string)
# DeleteStoppedContainers will delete all containers that are not running. It will return a list the deleted
# container IDs. See also [RemoveContainer](RemoveContainer).
@@ -608,21 +628,21 @@ method RemoveContainer(name: string, force: bool) -> (container: string)
# ~~~
method DeleteStoppedContainers() -> (containers: []string)
-# ListImages returns an array of ImageInList structures which provide basic information about
-# an image currently in storage. See also [InspectImage](InspectImage).
-method ListImages() -> (images: []ImageInList)
+# ListImages returns information about the images that are currently in storage.
+# See also [InspectImage](InspectImage).
+method ListImages() -> (images: []Image)
-# GetImage returns a single image in an [ImageInList](#ImageInList) struct. You must supply an image name as a string.
-# If the image cannot be found, an [ImageNotFound](#ImageNotFound) error will be returned.
-method GetImage(name: string) -> (image: ImageInList)
+# GetImage returns information about a single image in storage.
+# If the image caGetImage returns be found, [ImageNotFound](#ImageNotFound) will be returned.
+method GetImage(id: string) -> (image: Image)
# BuildImage takes a [BuildInfo](#BuildInfo) structure and builds an image. At a minimum, you must provide the
-# 'dockerfile' and 'tags' options in the BuildInfo structure. It will return a [BuildResponse](#BuildResponse) structure
+# 'dockerfile' and 'tags' options in the BuildInfo structure. It will return a [MoreResponse](#MoreResponse) structure
# that contains the build logs and resulting image ID.
-method BuildImage(build: BuildInfo) -> (image: BuildResponse)
+method BuildImage(build: BuildInfo) -> (image: MoreResponse)
# This function is not implemented yet.
-method CreateImage() -> (notimplemented: NotImplemented)
+# method CreateImage() -> (notimplemented: NotImplemented)
# InspectImage takes the name or ID of an image and returns a string respresentation of data associated with the
#image. You must serialize the string into JSON to use it further. An [ImageNotFound](#ImageNotFound) error will
@@ -637,8 +657,8 @@ method HistoryImage(name: string) -> (history: []ImageHistory)
# PushImage takes three input arguments: the name or ID of an image, the fully-qualified destination name of the image,
# 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 the ID of the image will be returned on success.
-method PushImage(name: string, tag: string, tlsverify: bool, signaturePolicy: string, creds: string, certDir: string, compress: bool, format: string, removeSignatures: bool, signBy: string) -> (image: string)
+# 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)
# 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.
@@ -656,10 +676,10 @@ method TagImage(name: string, tagged: string) -> (image: string)
# ~~~
method RemoveImage(name: string, force: bool) -> (image: string)
-# SearchImage takes the string of an image name and a limit of searches from each registries to be returned. SearchImage
-# will then use a glob-like match to find the image you are searching for. The images are returned in an array of
-# ImageSearch structures which contain information about the image as well as its fully-qualified name.
-method SearchImage(name: string, limit: int) -> (images: []ImageSearch)
+# 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, 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.
@@ -706,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.
@@ -913,10 +933,10 @@ method UnpausePod(name: string) -> (pod: string)
method RemovePod(name: string, force: bool) -> (pod: string)
# This method has not be implemented yet.
-method WaitPod() -> (notimplemented: NotImplemented)
+# method WaitPod() -> (notimplemented: NotImplemented)
# This method has not been implemented yet.
-method TopPod() -> (notimplemented: NotImplemented)
+# method TopPod() -> (notimplemented: NotImplemented)
# GetPodStats takes the name or ID of a pod and returns a pod name and slice of ContainerStats structure which
# contains attributes like memory and cpu usage. If the pod cannot be found, a [PodNotFound](#PodNotFound)
@@ -1020,19 +1040,19 @@ method UnmountContainer(name: string, force: bool) -> ()
method ImagesPrune(all: bool) -> (pruned: []string)
# This function is not implemented yet.
-method ListContainerPorts(name: string) -> (notimplemented: NotImplemented)
+# method ListContainerPorts(name: string) -> (notimplemented: NotImplemented)
# GenerateKube generates a Kubernetes v1 Pod description of a Podman container or pod
# and its containers. The description is in YAML. See also [ReplayKube](ReplayKube).
-method GenerateKube() -> (notimplemented: NotImplemented)
+# method GenerateKube() -> (notimplemented: NotImplemented)
# GenerateKubeService generates a Kubernetes v1 Service description of a Podman container or pod
# and its containers. The description is in YAML. See also [GenerateKube](GenerateKube).
-method GenerateKubeService() -> (notimplemented: NotImplemented)
+# method GenerateKubeService() -> (notimplemented: NotImplemented)
# ReplayKube recreates a pod and its containers based on a Kubernetes v1 Pod description (in YAML)
# like that created by GenerateKube. See also [GenerateKube](GenerateKube).
-method ReplayKube() -> (notimplemented: NotImplemented)
+# method ReplayKube() -> (notimplemented: NotImplemented)
# ContainerConfig returns a container's config in string form. This call is for
# development of Podman only and generally should not be used.
@@ -1050,14 +1070,29 @@ 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 (name: string)
+error ImageNotFound (id: string)
# ContainerNotFound means the container could not be found by the provided name or ID in local storage.
-error ContainerNotFound (name: string)
+error ContainerNotFound (id: string)
# NoContainerRunning means none of the containers requested are running in a command that requires a running container.
error NoContainerRunning ()
diff --git a/cmd/podman/varlink_dummy.go b/cmd/podman/varlink_dummy.go
index 8d7a7e8ca..430511d72 100644
--- a/cmd/podman/varlink_dummy.go
+++ b/cmd/podman/varlink_dummy.go
@@ -2,8 +2,10 @@
package main
-import (
- "github.com/containers/libpod/cmd/podman/cliconfig"
-)
+import "github.com/spf13/cobra"
-var varlinkCommand *cliconfig.PodmanCommand
+var (
+ _varlinkCommand = &cobra.Command{
+ Use: "",
+ }
+)
diff --git a/cmd/podman/version.go b/cmd/podman/version.go
index 0e7cd43d5..c65ba94f9 100644
--- a/cmd/podman/version.go
+++ b/cmd/podman/version.go
@@ -28,9 +28,9 @@ var (
func init() {
versionCommand.Command = _versionCommand
+ versionCommand.SetUsageTemplate(UsageTemplate())
flags := versionCommand.Flags()
flags.StringVarP(&versionCommand.Format, "format", "f", "", "Change the output format to JSON or a Go template")
- rootCmd.AddCommand(versionCommand.Command)
}
// versionCmd gets and prints version info for version command
diff --git a/cmd/podman/volume.go b/cmd/podman/volume.go
index bae778e52..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_create.go b/cmd/podman/volume_create.go
index e0ff4c341..fe5d69e0b 100644
--- a/cmd/podman/volume_create.go
+++ b/cmd/podman/volume_create.go
@@ -4,8 +4,7 @@ import (
"fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
- "github.com/containers/libpod/cmd/podman/libpodruntime"
- "github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/libpod/adapter"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@@ -33,6 +32,7 @@ be created at.`
func init() {
volumeCreateCommand.Command = _volumeCreateCommand
+ volumeCreateCommand.SetUsageTemplate(UsageTemplate())
flags := volumeCreateCommand.Flags()
flags.StringVar(&volumeCreateCommand.Driver, "driver", "", "Specify volume driver name (default local)")
flags.StringSliceVarP(&volumeCreateCommand.Label, "label", "l", []string{}, "Set metadata for a volume (default [])")
@@ -41,13 +41,7 @@ func init() {
}
func volumeCreateCmd(c *cliconfig.VolumeCreateValues) error {
- var (
- options []libpod.VolumeCreateOption
- err error
- volName string
- )
-
- runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
+ runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "error creating libpod runtime")
}
@@ -57,36 +51,19 @@ func volumeCreateCmd(c *cliconfig.VolumeCreateValues) error {
return errors.Errorf("too many arguments, create takes at most 1 argument")
}
- if len(c.InputArgs) > 0 {
- volName = c.InputArgs[0]
- options = append(options, libpod.WithVolumeName(volName))
- }
-
- if c.Flag("driver").Changed {
- options = append(options, libpod.WithVolumeDriver(c.String("driver")))
- }
-
labels, err := getAllLabels([]string{}, c.Label)
if err != nil {
return errors.Wrapf(err, "unable to process labels")
}
- if len(labels) != 0 {
- options = append(options, libpod.WithVolumeLabels(labels))
- }
opts, err := getAllLabels([]string{}, c.Opt)
if err != nil {
return errors.Wrapf(err, "unable to process options")
}
- if len(options) != 0 {
- options = append(options, libpod.WithVolumeOptions(opts))
- }
- vol, err := runtime.NewVolume(getContext(), options...)
- if err != nil {
- return err
+ volumeName, err := runtime.CreateVolume(getContext(), c, labels, opts)
+ if err == nil {
+ fmt.Println(volumeName)
}
- fmt.Printf("%s\n", vol.Name())
-
- return nil
+ return err
}
diff --git a/cmd/podman/volume_inspect.go b/cmd/podman/volume_inspect.go
index 7cb5703da..928ef37d0 100644
--- a/cmd/podman/volume_inspect.go
+++ b/cmd/podman/volume_inspect.go
@@ -2,9 +2,8 @@ package main
import (
"github.com/containers/libpod/cmd/podman/cliconfig"
- "github.com/containers/libpod/cmd/podman/libpodruntime"
+ "github.com/containers/libpod/libpod/adapter"
"github.com/pkg/errors"
- "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
@@ -31,6 +30,7 @@ from JSON to a Go template.
func init() {
volumeInspectCommand.Command = _volumeInspectCommand
+ volumeInspectCommand.SetUsageTemplate(UsageTemplate())
flags := volumeInspectCommand.Flags()
flags.BoolVarP(&volumeInspectCommand.All, "all", "a", false, "Inspect all volumes")
flags.StringVarP(&volumeInspectCommand.Format, "format", "f", "json", "Format volume output using Go template")
@@ -38,22 +38,19 @@ func init() {
}
func volumeInspectCmd(c *cliconfig.VolumeInspectValues) error {
- var err error
+ if (c.All && len(c.InputArgs) > 0) || (!c.All && len(c.InputArgs) < 1) {
+ return errors.New("provide one or more volume names or use --all")
+ }
- runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
+ runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "error creating libpod runtime")
}
defer runtime.Shutdown(false)
- opts := volumeLsOptions{
- Format: c.Format,
- }
-
- vols, lastError := getVolumesFromContext(&c.PodmanCommand, runtime)
- if lastError != nil {
- logrus.Errorf("%q", lastError)
+ vols, err := runtime.InspectVolumes(getContext(), c)
+ if err != nil {
+ return err
}
-
- return generateVolLsOutput(vols, opts, runtime)
+ return generateVolLsOutput(vols, volumeLsOptions{Format: c.Format})
}
diff --git a/cmd/podman/volume_ls.go b/cmd/podman/volume_ls.go
index 78fdfed64..0edadc5ac 100644
--- a/cmd/podman/volume_ls.go
+++ b/cmd/podman/volume_ls.go
@@ -6,8 +6,7 @@ import (
"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/formats"
- "github.com/containers/libpod/cmd/podman/libpodruntime"
- "github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/libpod/adapter"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
@@ -62,6 +61,7 @@ and the output format can be changed to JSON or a user specified Go template.
func init() {
volumeLsCommand.Command = _volumeLsCommand
+ volumeLsCommand.SetUsageTemplate(UsageTemplate())
flags := volumeLsCommand.Flags()
flags.StringVarP(&volumeLsCommand.Filter, "filter", "f", "", "Filter volume output")
@@ -70,7 +70,7 @@ func init() {
}
func volumeLsCmd(c *cliconfig.VolumeLsValues) error {
- runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
+ runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "error creating libpod runtime")
}
@@ -86,7 +86,7 @@ func volumeLsCmd(c *cliconfig.VolumeLsValues) error {
opts.Format = genVolLsFormat(c)
// Get the filter functions based on any filters set
- var filterFuncs []libpod.VolumeFilter
+ var filterFuncs []adapter.VolumeFilter
if c.Filter != "" {
filters := strings.Split(c.Filter, ",")
for _, f := range filters {
@@ -94,7 +94,7 @@ func volumeLsCmd(c *cliconfig.VolumeLsValues) error {
if len(filterSplit) < 2 {
return errors.Errorf("filter input must be in the form of filter=value: %s is invalid", f)
}
- generatedFunc, err := generateVolumeFilterFuncs(filterSplit[0], filterSplit[1], runtime)
+ generatedFunc, err := generateVolumeFilterFuncs(filterSplit[0], filterSplit[1])
if err != nil {
return errors.Wrapf(err, "invalid filter")
}
@@ -102,13 +102,12 @@ func volumeLsCmd(c *cliconfig.VolumeLsValues) error {
}
}
- volumes, err := runtime.GetAllVolumes()
+ volumes, err := runtime.Volumes(getContext())
if err != nil {
return err
}
-
// Get the volumes that match the filter
- volsFiltered := make([]*libpod.Volume, 0, len(volumes))
+ volsFiltered := make([]*adapter.Volume, 0, len(volumes))
for _, vol := range volumes {
include := true
for _, filter := range filterFuncs {
@@ -119,7 +118,7 @@ func volumeLsCmd(c *cliconfig.VolumeLsValues) error {
volsFiltered = append(volsFiltered, vol)
}
}
- return generateVolLsOutput(volsFiltered, opts, runtime)
+ return generateVolLsOutput(volsFiltered, opts)
}
// generate the template based on conditions given
@@ -205,7 +204,7 @@ func getVolTemplateOutput(lsParams []volumeLsJSONParams, opts volumeLsOptions) (
}
// getVolJSONParams returns the volumes in JSON format
-func getVolJSONParams(volumes []*libpod.Volume, opts volumeLsOptions, runtime *libpod.Runtime) ([]volumeLsJSONParams, error) {
+func getVolJSONParams(volumes []*adapter.Volume) []volumeLsJSONParams {
var lsOutput []volumeLsJSONParams
for _, volume := range volumes {
@@ -220,25 +219,19 @@ func getVolJSONParams(volumes []*libpod.Volume, opts volumeLsOptions, runtime *l
lsOutput = append(lsOutput, params)
}
- return lsOutput, nil
+ return lsOutput
}
// generateVolLsOutput generates the output based on the format, JSON or Go Template, and prints it out
-func generateVolLsOutput(volumes []*libpod.Volume, opts volumeLsOptions, runtime *libpod.Runtime) error {
+func generateVolLsOutput(volumes []*adapter.Volume, opts volumeLsOptions) error {
if len(volumes) == 0 && opts.Format != formats.JSONString {
return nil
}
- lsOutput, err := getVolJSONParams(volumes, opts, runtime)
- if err != nil {
- return err
- }
+ lsOutput := getVolJSONParams(volumes)
var out formats.Writer
switch opts.Format {
case formats.JSONString:
- if err != nil {
- return errors.Wrapf(err, "unable to create JSON for volume output")
- }
out = formats.JSONStructArray{Output: volLsToGeneric([]volumeLsTemplateParams{}, lsOutput)}
default:
lsOutput, err := getVolTemplateOutput(lsOutput, opts)
@@ -251,18 +244,18 @@ func generateVolLsOutput(volumes []*libpod.Volume, opts volumeLsOptions, runtime
}
// generateVolumeFilterFuncs returns the true if the volume matches the filter set, otherwise it returns false.
-func generateVolumeFilterFuncs(filter, filterValue string, runtime *libpod.Runtime) (func(volume *libpod.Volume) bool, error) {
+func generateVolumeFilterFuncs(filter, filterValue string) (func(volume *adapter.Volume) bool, error) {
switch filter {
case "name":
- return func(v *libpod.Volume) bool {
+ return func(v *adapter.Volume) bool {
return strings.Contains(v.Name(), filterValue)
}, nil
case "driver":
- return func(v *libpod.Volume) bool {
+ return func(v *adapter.Volume) bool {
return v.Driver() == filterValue
}, nil
case "scope":
- return func(v *libpod.Volume) bool {
+ return func(v *adapter.Volume) bool {
return v.Scope() == filterValue
}, nil
case "label":
@@ -273,7 +266,7 @@ func generateVolumeFilterFuncs(filter, filterValue string, runtime *libpod.Runti
} else {
filterValue = ""
}
- return func(v *libpod.Volume) bool {
+ return func(v *adapter.Volume) bool {
for labelKey, labelValue := range v.Labels() {
if labelKey == filterKey && ("" == filterValue || labelValue == filterValue) {
return true
@@ -289,7 +282,7 @@ func generateVolumeFilterFuncs(filter, filterValue string, runtime *libpod.Runti
} else {
filterValue = ""
}
- return func(v *libpod.Volume) bool {
+ return func(v *adapter.Volume) bool {
for labelKey, labelValue := range v.Options() {
if labelKey == filterKey && ("" == filterValue || labelValue == filterValue) {
return true
diff --git a/cmd/podman/volume_prune.go b/cmd/podman/volume_prune.go
index 29dc6ead4..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"
@@ -37,29 +36,27 @@ using force.
func init() {
volumePruneCommand.Command = _volumePruneCommand
+ volumePruneCommand.SetUsageTemplate(UsageTemplate())
flags := volumePruneCommand.Flags()
flags.BoolVarP(&volumePruneCommand.Force, "force", "f", false, "Do not prompt for confirmation")
}
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
}
@@ -84,6 +81,5 @@ func volumePruneCmd(c *cliconfig.VolumePruneValues) error {
return nil
}
}
-
return volumePrune(runtime, getContext())
}
diff --git a/cmd/podman/volume_rm.go b/cmd/podman/volume_rm.go
index b02a06ed9..f301749e9 100644
--- a/cmd/podman/volume_rm.go
+++ b/cmd/podman/volume_rm.go
@@ -4,9 +4,8 @@ import (
"fmt"
"github.com/containers/libpod/cmd/podman/cliconfig"
- "github.com/containers/libpod/cmd/podman/libpodruntime"
+ "github.com/containers/libpod/libpod/adapter"
"github.com/pkg/errors"
- "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
@@ -35,6 +34,7 @@ not being used by any containers. To remove the volumes anyways, use the
func init() {
volumeRmCommand.Command = _volumeRmCommand
+ volumeRmCommand.SetUsageTemplate(UsageTemplate())
flags := volumeRmCommand.Flags()
flags.BoolVarP(&volumeRmCommand.All, "all", "a", false, "Remove all volumes")
flags.BoolVarP(&volumeRmCommand.Force, "force", "f", false, "Remove a volume by force, even if it is being used by a container")
@@ -43,25 +43,28 @@ func init() {
func volumeRmCmd(c *cliconfig.VolumeRmValues) error {
var err error
- runtime, err := libpodruntime.GetRuntime(&c.PodmanCommand)
+ if (len(c.InputArgs) > 0 && c.All) || (len(c.InputArgs) < 1 && !c.All) {
+ return errors.New("choose either one or more volumes or all")
+ }
+
+ runtime, err := adapter.GetRuntime(&c.PodmanCommand)
if err != nil {
return errors.Wrapf(err, "error creating libpod runtime")
}
defer runtime.Shutdown(false)
-
- ctx := getContext()
-
- vols, lastError := getVolumesFromContext(&c.PodmanCommand, runtime)
- for _, vol := range vols {
- err = runtime.RemoveVolume(ctx, vol, c.Force, false)
- if err != nil {
- if lastError != nil {
- logrus.Errorf("%q", lastError)
- }
- lastError = errors.Wrapf(err, "failed to remove volume %q", vol.Name())
- } else {
- fmt.Println(vol.Name())
+ deletedVolumeNames, err := runtime.RemoveVolumes(getContext(), c)
+ if err != nil {
+ if len(deletedVolumeNames) > 0 {
+ printDeleteVolumes(deletedVolumeNames)
+ return err
}
}
- return lastError
+ printDeleteVolumes(deletedVolumeNames)
+ return err
+}
+
+func printDeleteVolumes(volumes []string) {
+ for _, v := range volumes {
+ fmt.Println(v)
+ }
}
diff --git a/cmd/podman/wait.go b/cmd/podman/wait.go
index fa195b7ce..616c8feb5 100644
--- a/cmd/podman/wait.go
+++ b/cmd/podman/wait.go
@@ -34,11 +34,10 @@ var (
func init() {
waitCommand.Command = _waitCommand
+ waitCommand.SetUsageTemplate(UsageTemplate())
flags := waitCommand.Flags()
flags.UintVarP(&waitCommand.Interval, "interval", "i", 250, "Milliseconds to wait before polling for completion")
flags.BoolVarP(&waitCommand.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
-
- rootCmd.AddCommand(waitCommand.Command)
}
func waitCmd(c *cliconfig.WaitValues) error {