From 0e547a4cc3c8c49053338ea73c02be708257c3d9 Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Sun, 5 Jul 2020 15:39:34 +0200 Subject: podman ps truncate the command With a long create command the output from ps is basically unreadable. This is a regression that was introduced with Podman 2.0. Signed-off-by: Paul Holzinger --- cmd/podman/containers/ps.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'cmd') diff --git a/cmd/podman/containers/ps.go b/cmd/podman/containers/ps.go index 5cd7f40ac..24266244e 100644 --- a/cmd/podman/containers/ps.go +++ b/cmd/podman/containers/ps.go @@ -313,7 +313,13 @@ func (l psReporter) Status() string { // Command returns the container command in string format func (l psReporter) Command() string { - return strings.Join(l.ListContainer.Command, " ") + command := strings.Join(l.ListContainer.Command, " ") + if !noTrunc { + if len(command) > 17 { + return command[0:17] + "..." + } + } + return command } // Size returns the rootfs and virtual sizes in human duration in -- cgit v1.2.3-54-g00ecf From d59ef411949564518e3b5d0b5bbc1625ede45486 Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Mon, 6 Jul 2020 11:14:33 +0200 Subject: auto-update: clarify systemd-unit requirements Clarify in the help message and the man page that auto updates only work with systemd units that are similar to the ones from `generate systemd --new`. Units that merely start/stop a container do not work as they will use the same image. Fixes: #6793 Signed-off-by: Valentin Rothberg --- cmd/podman/auto-update.go | 2 ++ docs/source/markdown/podman-auto-update.1.md | 3 +++ 2 files changed, 5 insertions(+) (limited to 'cmd') diff --git a/cmd/podman/auto-update.go b/cmd/podman/auto-update.go index 7a67f3d18..a12eeb6cb 100644 --- a/cmd/podman/auto-update.go +++ b/cmd/podman/auto-update.go @@ -16,6 +16,8 @@ var ( autoUpdateDescription = `Auto update containers according to their auto-update policy. Auto-update policies are specified with the "io.containers.autoupdate" label. + Containers are expected to run in systemd units created with "podman-generate-systemd --new", + or similar units that create new containers in order to run the updated images. Note that this command is experimental. Please refer to the podman-auto-update(1) man page for details.` autoUpdateCommand = &cobra.Command{ Use: "auto-update [flags]", diff --git a/docs/source/markdown/podman-auto-update.1.md b/docs/source/markdown/podman-auto-update.1.md index 90e581e42..73d75be1f 100644 --- a/docs/source/markdown/podman-auto-update.1.md +++ b/docs/source/markdown/podman-auto-update.1.md @@ -23,6 +23,9 @@ Note that `podman auto-update` relies on systemd and requires a fully-qualified This enforcement is necessary to know which image to actually check and pull. If an image ID was used, Podman would not know which image to check/pull anymore. +Moreover, the systemd units are expected to be generated with `podman-generate-systemd --new`, or similar units that create new containers in order to run the updated images. +Systemd units that start and stop a container cannot run a new image. + ## OPTIONS **--authfile**=*path* -- cgit v1.2.3-54-g00ecf From 0c4a734353eb2d02d1baf16418068edfcdb505de Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Tue, 30 Jun 2020 08:07:42 -0400 Subject: Set TMPDIR to /var/tmp by default if not set Containers/image will use TMPDIR for the location of pulled layer blobs. If TMPDIR is not set, it will use /tmp. Since this is known to be of limited space on most systems, we change the default to /var/tmp if the user has not told the tools where to store temporary files. Signed-off-by: Daniel J Walsh --- cmd/podman/main.go | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'cmd') diff --git a/cmd/podman/main.go b/cmd/podman/main.go index 77cadc842..f3b1dcc5d 100644 --- a/cmd/podman/main.go +++ b/cmd/podman/main.go @@ -27,6 +27,11 @@ func main() { return } + // Hard code TMPDIR functions to use /var/tmp, if user did not override + if _, ok := os.LookupEnv("TMPDIR"); !ok { + os.Setenv("TMPDIR", "/var/tmp") + } + cfg := registry.PodmanConfig() for _, c := range registry.Commands { for _, m := range c.Mode { -- cgit v1.2.3-54-g00ecf From 1c02d5ab890ba7de6d0ad0603438107e086c18b7 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Sun, 28 Jun 2020 11:06:46 -0400 Subject: Allow empty host port in --publish flag I didn't believe that this was actually legal, but it looks like it is. And, unlike our previous understanding (host port being empty means just use container port), empty host port actually carries the same meaning as `--expose` + `--publish-all` (that is, assign a random host port to the given container port). This requires a significant rework of our port handling code to handle this new case. I don't foresee this being commonly used, so I optimized having a fixed port number as fast path, which this random assignment code running after the main port handling code only if necessary. Fixes #6806 Signed-off-by: Matthew Heon --- cmd/podman/common/util.go | 26 ++++---- docs/source/markdown/podman-create.1.md | 2 + docs/source/markdown/podman-run.1.md | 3 + pkg/specgen/generate/ports.go | 112 ++++++++++++++++++++++++++------ pkg/specgen/specgen.go | 3 +- test/e2e/run_networking_test.go | 24 +++++++ 6 files changed, 136 insertions(+), 34 deletions(-) (limited to 'cmd') diff --git a/cmd/podman/common/util.go b/cmd/podman/common/util.go index a3ce6198c..e21e349d9 100644 --- a/cmd/podman/common/util.go +++ b/cmd/podman/common/util.go @@ -184,22 +184,24 @@ func parseSplitPort(hostIP, hostPort *string, ctrPort string, protocol *string) } if hostPort != nil { if *hostPort == "" { - return newPort, errors.Errorf("must provide a non-empty container host port to publish") - } - hostStart, hostLen, err := parseAndValidateRange(*hostPort) - if err != nil { - return newPort, errors.Wrapf(err, "error parsing host port") - } - if hostLen != ctrLen { - return newPort, errors.Errorf("host and container port ranges have different lengths: %d vs %d", hostLen, ctrLen) + // Set 0 as a placeholder. The server side of Specgen + // will find a random, open, unused port to use. + newPort.HostPort = 0 + } else { + hostStart, hostLen, err := parseAndValidateRange(*hostPort) + if err != nil { + return newPort, errors.Wrapf(err, "error parsing host port") + } + if hostLen != ctrLen { + return newPort, errors.Errorf("host and container port ranges have different lengths: %d vs %d", hostLen, ctrLen) + } + newPort.HostPort = hostStart } - newPort.HostPort = hostStart + } else { + newPort.HostPort = newPort.ContainerPort } hport := newPort.HostPort - if hport == 0 { - hport = newPort.ContainerPort - } logrus.Debugf("Adding port mapping from %d to %d length %d protocol %q", hport, newPort.ContainerPort, newPort.Range, newPort.Protocol) return newPort, nil diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md index 3ec91a3ad..7c2903e33 100644 --- a/docs/source/markdown/podman-create.1.md +++ b/docs/source/markdown/podman-create.1.md @@ -623,6 +623,8 @@ When specifying ranges for both, the number of container ports in the range must (e.g., `podman run -p 1234-1236:1222-1224 --name thisWorks -t busybox` but not `podman run -p 1230-1236:1230-1240 --name RangeContainerPortsBiggerThanRangeHostPorts -t busybox`) With ip: `podman run -p 127.0.0.1:$HOSTPORT:$CONTAINERPORT --name CONTAINER -t someimage` +Host port does not have to be specified (e.g. `podman run -p 127.0.0.1::80`). +If it is not, the container port will be randomly assigned a port on the host. Use `podman port` to see the actual mapping: `podman port CONTAINER $CONTAINERPORT` **--publish-all**, **-P**=*true|false* diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md index 7e91a06a3..6b6ab03f6 100644 --- a/docs/source/markdown/podman-run.1.md +++ b/docs/source/markdown/podman-run.1.md @@ -632,6 +632,9 @@ Both hostPort and containerPort can be specified as a range of ports. When specifying ranges for both, the number of container ports in the range must match the number of host ports in the range. +Host port does not have to be specified (e.g. `podman run -p 127.0.0.1::80`). +If it is not, the container port will be randomly assigned a port on the host. + Use **podman port** to see the actual mapping: **podman port $CONTAINER $CONTAINERPORT**. **--publish-all**, **-P**=**true**|**false** diff --git a/pkg/specgen/generate/ports.go b/pkg/specgen/generate/ports.go index b529fd4cd..9412ecfbf 100644 --- a/pkg/specgen/generate/ports.go +++ b/pkg/specgen/generate/ports.go @@ -43,6 +43,8 @@ func parsePortMapping(portMappings []specgen.PortMapping) ([]ocicni.PortMapping, containerPortValidate[proto] = make(map[string]map[uint16]uint16) } + postAssignHostPort := false + // Iterate through all port mappings, generating OCICNI PortMapping // structs and validating there is no overlap. for _, port := range portMappings { @@ -71,9 +73,6 @@ func parsePortMapping(portMappings []specgen.PortMapping) ([]ocicni.PortMapping, return nil, nil, nil, errors.Errorf("container port number must be non-0") } hostPort := port.HostPort - if hostPort == 0 { - hostPort = containerPort - } if uint32(len-1)+uint32(containerPort) > 65535 { return nil, nil, nil, errors.Errorf("container port range exceeds maximum allowable port number") } @@ -105,26 +104,42 @@ func parsePortMapping(portMappings []specgen.PortMapping) ([]ocicni.PortMapping, cPort := containerPort + index hPort := hostPort + index - if cPort == 0 || hPort == 0 { - return nil, nil, nil, errors.Errorf("host and container ports cannot be 0") - } - - testCPort := ctrPortMap[cPort] - if testCPort != 0 && testCPort != hPort { - // This is an attempt to redefine a port - return nil, nil, nil, errors.Errorf("conflicting port mappings for container port %d (protocol %s)", cPort, p) + if cPort == 0 { + return nil, nil, nil, errors.Errorf("container port cannot be 0") } - ctrPortMap[cPort] = hPort - testHPort := hostPortMap[hPort] - if testHPort != 0 && testHPort != cPort { - return nil, nil, nil, errors.Errorf("conflicting port mappings for host port %d (protocol %s)", hPort, p) - } - hostPortMap[hPort] = cPort - - // If we have an exact duplicate, just continue - if testCPort == hPort && testHPort == cPort { - continue + // Host port is allowed to be 0. If it is, we + // select a random port on the host. + // This will happen *after* all other ports are + // placed, to ensure we don't accidentally + // select a port that a later mapping wanted. + if hPort == 0 { + // If we already have a host port + // assigned to their container port - + // just use that. + if ctrPortMap[cPort] != 0 { + hPort = ctrPortMap[cPort] + } else { + postAssignHostPort = true + } + } else { + testCPort := ctrPortMap[cPort] + if testCPort != 0 && testCPort != hPort { + // This is an attempt to redefine a port + return nil, nil, nil, errors.Errorf("conflicting port mappings for container port %d (protocol %s)", cPort, p) + } + ctrPortMap[cPort] = hPort + + testHPort := hostPortMap[hPort] + if testHPort != 0 && testHPort != cPort { + return nil, nil, nil, errors.Errorf("conflicting port mappings for host port %d (protocol %s)", hPort, p) + } + hostPortMap[hPort] = cPort + + // If we have an exact duplicate, just continue + if testCPort == hPort && testHPort == cPort { + continue + } } // We appear to be clear. Make an OCICNI port @@ -142,6 +157,61 @@ func parsePortMapping(portMappings []specgen.PortMapping) ([]ocicni.PortMapping, } } + // Handle any 0 host ports now by setting random container ports. + if postAssignHostPort { + remadeMappings := make([]ocicni.PortMapping, 0, len(finalMappings)) + + // Iterate over all + for _, p := range finalMappings { + if p.HostPort != 0 { + remadeMappings = append(remadeMappings, p) + continue + } + + hostIPMap := hostPortValidate[p.Protocol] + ctrIPMap := containerPortValidate[p.Protocol] + + hostPortMap, ok := hostIPMap[p.HostIP] + if !ok { + hostPortMap = make(map[uint16]uint16) + hostIPMap[p.HostIP] = hostPortMap + } + ctrPortMap, ok := ctrIPMap[p.HostIP] + if !ok { + ctrPortMap = make(map[uint16]uint16) + ctrIPMap[p.HostIP] = ctrPortMap + } + + // See if container port has been used elsewhere + if ctrPortMap[uint16(p.ContainerPort)] != 0 { + // Duplicate definition. Let's not bother + // including it. + continue + } + + // Max retries to ensure we don't loop forever. + for i := 0; i < 15; i++ { + candidate, err := getRandomPort() + if err != nil { + return nil, nil, nil, errors.Wrapf(err, "error getting candidate host port for container port %d", p.ContainerPort) + } + + if hostPortMap[uint16(candidate)] == 0 { + logrus.Debugf("Successfully assigned container port %d to host port %d (IP %s Protocol %s)", p.ContainerPort, candidate, p.HostIP, p.Protocol) + hostPortMap[uint16(candidate)] = uint16(p.ContainerPort) + ctrPortMap[uint16(p.ContainerPort)] = uint16(candidate) + p.HostPort = int32(candidate) + break + } + } + if p.HostPort == 0 { + return nil, nil, nil, errors.Errorf("could not find open host port to map container port %d to", p.ContainerPort) + } + remadeMappings = append(remadeMappings, p) + } + return remadeMappings, containerPortValidate, hostPortValidate, nil + } + return finalMappings, containerPortValidate, hostPortValidate, nil } diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go index 03e840ab4..327c15c5a 100644 --- a/pkg/specgen/specgen.go +++ b/pkg/specgen/specgen.go @@ -430,7 +430,8 @@ type PortMapping struct { ContainerPort uint16 `json:"container_port"` // HostPort is the port number that will be forwarded from the host into // the container. - // If omitted, will be assumed to be identical to + // If omitted, a random port on the host (guaranteed to be over 1024) + // will be assigned. HostPort uint16 `json:"host_port,omitempty"` // Range is the number of ports that will be forwarded, starting at // HostPort and ContainerPort and counting up. diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go index dd018b910..6c049c5c1 100644 --- a/test/e2e/run_networking_test.go +++ b/test/e2e/run_networking_test.go @@ -184,6 +184,30 @@ var _ = Describe("Podman run networking", func() { Expect(inspectOut[0].NetworkSettings.Ports["80/tcp"][0].HostIP).To(Equal("")) }) + It("podman run -p 127.0.0.1::8080/udp", func() { + name := "testctr" + session := podmanTest.Podman([]string{"create", "-t", "-p", "127.0.0.1::8080/udp", "--name", name, ALPINE, "/bin/sh"}) + session.WaitWithDefaultTimeout() + inspectOut := podmanTest.InspectContainer(name) + Expect(len(inspectOut)).To(Equal(1)) + Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1)) + Expect(len(inspectOut[0].NetworkSettings.Ports["8080/udp"])).To(Equal(1)) + Expect(inspectOut[0].NetworkSettings.Ports["8080/udp"][0].HostPort).To(Not(Equal("8080"))) + Expect(inspectOut[0].NetworkSettings.Ports["8080/udp"][0].HostIP).To(Equal("127.0.0.1")) + }) + + It("podman run -p :8080", func() { + name := "testctr" + session := podmanTest.Podman([]string{"create", "-t", "-p", ":8080", "--name", name, ALPINE, "/bin/sh"}) + session.WaitWithDefaultTimeout() + inspectOut := podmanTest.InspectContainer(name) + Expect(len(inspectOut)).To(Equal(1)) + Expect(len(inspectOut[0].NetworkSettings.Ports)).To(Equal(1)) + Expect(len(inspectOut[0].NetworkSettings.Ports["8080/tcp"])).To(Equal(1)) + Expect(inspectOut[0].NetworkSettings.Ports["8080/tcp"][0].HostPort).To(Not(Equal("8080"))) + Expect(inspectOut[0].NetworkSettings.Ports["8080/tcp"][0].HostIP).To(Equal("")) + }) + It("podman run network expose host port 80 to container port 8000", func() { SkipIfRootless() session := podmanTest.Podman([]string{"run", "-dt", "-p", "80:8000", ALPINE, "/bin/sh"}) -- cgit v1.2.3-54-g00ecf From de6a8609a81472b5be786c7404576905ebb981fb Mon Sep 17 00:00:00 2001 From: Brent Baude Date: Fri, 26 Jun 2020 16:22:04 -0500 Subject: Set console mode for windows Windows terminal handling is different than darwin and linux. It needs to have the terminal mode set to enable virtual terminal processing. This allows colors and other things to work. Signed-off-by: Brent Baude Signed-off-by: Matt Heon --- cmd/podman/main.go | 6 ++++++ pkg/terminal/console_unix.go | 8 ++++++++ pkg/terminal/console_windows.go | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 pkg/terminal/console_unix.go create mode 100644 pkg/terminal/console_windows.go (limited to 'cmd') diff --git a/cmd/podman/main.go b/cmd/podman/main.go index f3b1dcc5d..c229e9881 100644 --- a/cmd/podman/main.go +++ b/cmd/podman/main.go @@ -16,7 +16,9 @@ import ( _ "github.com/containers/libpod/v2/cmd/podman/system" _ "github.com/containers/libpod/v2/cmd/podman/volumes" "github.com/containers/libpod/v2/pkg/rootless" + "github.com/containers/libpod/pkg/terminal" "github.com/containers/storage/pkg/reexec" + "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -58,6 +60,10 @@ func main() { } } } + if err := terminal.SetConsole(); err != nil { + logrus.Error(err) + os.Exit(1) + } Execute() os.Exit(0) diff --git a/pkg/terminal/console_unix.go b/pkg/terminal/console_unix.go new file mode 100644 index 000000000..6eee6aa2f --- /dev/null +++ b/pkg/terminal/console_unix.go @@ -0,0 +1,8 @@ +// +build !windows + +package terminal + +// SetConsole for non-windows environments is a no-op +func SetConsole() error { + return nil +} diff --git a/pkg/terminal/console_windows.go b/pkg/terminal/console_windows.go new file mode 100644 index 000000000..c7691857c --- /dev/null +++ b/pkg/terminal/console_windows.go @@ -0,0 +1,37 @@ +// +build windows + +package terminal + +import ( + "github.com/sirupsen/logrus" + "golang.org/x/sys/windows" +) + +// SetConsole switches the windows terminal mode to be able to handle colors, etc +func SetConsole() error { + if err := setConsoleMode(windows.Stdout, windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING); err != nil { + return err + } + if err := setConsoleMode(windows.Stderr, windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING); err != nil { + return err + } + if err := setConsoleMode(windows.Stdin, windows.ENABLE_VIRTUAL_TERMINAL_PROCESSING); err != nil { + return err + } + return nil +} + +func setConsoleMode(handle windows.Handle, flags uint32) error { + var mode uint32 + err := windows.GetConsoleMode(handle, &mode) + if err != nil { + return err + } + if err := windows.SetConsoleMode(handle, mode|flags); err != nil { + // In similar code, it is not considered an error if we cannot set the + // console mode. Following same line of thinking here. + logrus.WithError(err).Error("Failed to set console mode for cli") + } + + return nil +} -- cgit v1.2.3-54-g00ecf From 8dd26289bf516dcfbd9aaad6d2dd65c9f84380c8 Mon Sep 17 00:00:00 2001 From: Jhon Honce Date: Mon, 22 Jun 2020 14:29:04 -0700 Subject: Fixes --remote flag issues * --remote, --url and --identity are now anchored to podman command. Subcommands should no longer have issues * TraverseChildren now set to V1 expectations * Latest flag now has helper function. Now has consistent usage. * IsRemote() uses cobra parser to determin if --remote is given * Moved validation functions from parser pkg to validate pkg * Fixes #6598 Fixes #6704 Signed-off-by: Jhon Honce Signed-off-by: Matt Heon --- cmd/podman/containers/attach.go | 14 ++-- cmd/podman/containers/checkpoint.go | 9 +-- cmd/podman/containers/cleanup.go | 7 +- cmd/podman/containers/create.go | 1 + cmd/podman/containers/diff.go | 9 +-- cmd/podman/containers/exec.go | 15 ++--- cmd/podman/containers/init.go | 11 ++-- cmd/podman/containers/inspect.go | 3 +- cmd/podman/containers/kill.go | 21 +++--- cmd/podman/containers/list.go | 1 + cmd/podman/containers/logs.go | 14 ++-- cmd/podman/containers/mount.go | 15 ++--- cmd/podman/containers/pause.go | 1 + cmd/podman/containers/port.go | 23 +++---- cmd/podman/containers/ps.go | 6 +- cmd/podman/containers/restart.go | 18 ++--- cmd/podman/containers/restore.go | 11 ++-- cmd/podman/containers/rm.go | 17 +++-- cmd/podman/containers/run.go | 1 + cmd/podman/containers/start.go | 12 ++-- cmd/podman/containers/stats.go | 14 ++-- cmd/podman/containers/stop.go | 16 ++--- cmd/podman/containers/top.go | 13 ++-- cmd/podman/containers/unmount.go | 16 ++--- cmd/podman/containers/wait.go | 11 ++-- cmd/podman/diff.go | 16 ++--- cmd/podman/generate/generate.go | 9 ++- cmd/podman/healthcheck/healthcheck.go | 9 ++- cmd/podman/images/build.go | 10 +-- cmd/podman/images/diff.go | 4 +- cmd/podman/images/image.go | 9 ++- cmd/podman/images/search.go | 1 + cmd/podman/inspect.go | 9 ++- cmd/podman/inspect/inspect.go | 3 +- cmd/podman/main.go | 2 +- cmd/podman/manifest/manifest.go | 9 ++- cmd/podman/manifest/push.go | 1 + cmd/podman/networks/network.go | 9 ++- cmd/podman/parse/common.go | 112 -------------------------------- cmd/podman/play/kube.go | 1 - cmd/podman/play/play.go | 9 ++- cmd/podman/pods/inspect.go | 6 +- cmd/podman/pods/kill.go | 13 ++-- cmd/podman/pods/pause.go | 11 ++-- cmd/podman/pods/pod.go | 9 ++- cmd/podman/pods/ps.go | 7 +- cmd/podman/pods/restart.go | 9 +-- cmd/podman/pods/rm.go | 10 +-- cmd/podman/pods/start.go | 9 +-- cmd/podman/pods/stats.go | 7 +- cmd/podman/pods/stop.go | 9 +-- cmd/podman/pods/top.go | 9 +-- cmd/podman/pods/unpause.go | 12 ++-- cmd/podman/registry/config.go | 16 +---- cmd/podman/registry/remote.go | 19 +++++- cmd/podman/root.go | 74 ++++++++++++--------- cmd/podman/system/connection.go | 1 - cmd/podman/system/system.go | 9 ++- cmd/podman/validate/args.go | 119 +++++++++++++++++++++++++++++++++- cmd/podman/validate/latest.go | 15 +++++ cmd/podman/volumes/volume.go | 9 ++- 61 files changed, 405 insertions(+), 460 deletions(-) delete mode 100644 cmd/podman/parse/common.go create mode 100644 cmd/podman/validate/latest.go (limited to 'cmd') diff --git a/cmd/podman/containers/attach.go b/cmd/podman/containers/attach.go index 6835d4e32..eca9e0787 100644 --- a/cmd/podman/containers/attach.go +++ b/cmd/podman/containers/attach.go @@ -44,10 +44,6 @@ func attachFlags(flags *pflag.FlagSet) { flags.StringVar(&attachOpts.DetachKeys, "detach-keys", containerConfig.DetachKeys(), "Select the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `ctrl-`, where `` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`") flags.BoolVar(&attachOpts.NoStdin, "no-stdin", false, "Do not attach STDIN. The default is false") flags.BoolVar(&attachOpts.SigProxy, "sig-proxy", true, "Proxy received signals to the process") - flags.BoolVarP(&attachOpts.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } } func init() { @@ -55,22 +51,24 @@ func init() { Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, Command: attachCommand, }) - flags := attachCommand.Flags() - attachFlags(flags) + attachFlags(attachCommand.Flags()) + validate.AddLatestFlag(attachCommand, &attachOpts.Latest) registry.Commands = append(registry.Commands, registry.CliCommand{ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, Command: containerAttachCommand, Parent: containerCmd, }) - containerAttachFlags := containerAttachCommand.Flags() - attachFlags(containerAttachFlags) + attachFlags(containerAttachCommand.Flags()) + validate.AddLatestFlag(containerAttachCommand, &attachOpts.Latest) + } func attach(cmd *cobra.Command, args []string) error { if len(args) > 1 || (len(args) == 0 && !attachOpts.Latest) { return errors.Errorf("attach requires the name or id of one running container or the latest flag") } + var name string if len(args) > 0 { name = args[0] diff --git a/cmd/podman/containers/checkpoint.go b/cmd/podman/containers/checkpoint.go index 6aa4304af..683437000 100644 --- a/cmd/podman/containers/checkpoint.go +++ b/cmd/podman/containers/checkpoint.go @@ -4,9 +4,9 @@ import ( "context" "fmt" - "github.com/containers/libpod/v2/cmd/podman/parse" "github.com/containers/libpod/v2/cmd/podman/registry" "github.com/containers/libpod/v2/cmd/podman/utils" + "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/pkg/domain/entities" "github.com/containers/libpod/v2/pkg/rootless" "github.com/pkg/errors" @@ -25,7 +25,7 @@ var ( Long: checkpointDescription, RunE: checkpoint, Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, false) + return validate.CheckAllLatestAndCIDFile(cmd, args, false, false) }, Example: `podman container checkpoint --keep ctrID podman container checkpoint --all @@ -48,12 +48,9 @@ func init() { flags.BoolVarP(&checkpointOptions.LeaveRunning, "leave-running", "R", false, "Leave the container running after writing checkpoint to disk") flags.BoolVar(&checkpointOptions.TCPEstablished, "tcp-established", false, "Checkpoint a container with established TCP connections") flags.BoolVarP(&checkpointOptions.All, "all", "a", false, "Checkpoint all running containers") - flags.BoolVarP(&checkpointOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") flags.StringVarP(&checkpointOptions.Export, "export", "e", "", "Export the checkpoint image to a tar.gz") flags.BoolVar(&checkpointOptions.IgnoreRootFS, "ignore-rootfs", false, "Do not include root file-system changes when exporting") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } + validate.AddLatestFlag(checkpointCommand, &checkpointOptions.Latest) } func checkpoint(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/containers/cleanup.go b/cmd/podman/containers/cleanup.go index f36dcf6d4..5dea77b7a 100644 --- a/cmd/podman/containers/cleanup.go +++ b/cmd/podman/containers/cleanup.go @@ -3,9 +3,9 @@ package containers import ( "fmt" - "github.com/containers/libpod/v2/cmd/podman/parse" "github.com/containers/libpod/v2/cmd/podman/registry" "github.com/containers/libpod/v2/cmd/podman/utils" + "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/pkg/domain/entities" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -24,7 +24,7 @@ var ( Long: cleanupDescription, RunE: cleanup, Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, false) + return validate.CheckAllLatestAndCIDFile(cmd, args, false, false) }, Example: `podman container cleanup --latest podman container cleanup ctrID1 ctrID2 ctrID3 @@ -44,11 +44,10 @@ func init() { }) flags := cleanupCommand.Flags() flags.BoolVarP(&cleanupOptions.All, "all", "a", false, "Cleans up all containers") - flags.BoolVarP(&cleanupOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") flags.StringVar(&cleanupOptions.Exec, "exec", "", "Clean up the given exec session instead of the container") flags.BoolVar(&cleanupOptions.Remove, "rm", false, "After cleanup, remove the container entirely") flags.BoolVar(&cleanupOptions.RemoveImage, "rmi", false, "After cleanup, remove the image entirely") - + validate.AddLatestFlag(cleanupCommand, &cleanupOptions.Latest) } func cleanup(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go index 42cee022e..cb0ee6e1f 100644 --- a/cmd/podman/containers/create.go +++ b/cmd/podman/containers/create.go @@ -58,6 +58,7 @@ func createFlags(flags *pflag.FlagSet) { flags.AddFlagSet(common.GetCreateFlags(&cliVals)) flags.AddFlagSet(common.GetNetFlags()) flags.SetNormalizeFunc(common.AliasFlags) + if registry.IsRemote() { _ = flags.MarkHidden("authfile") _ = flags.MarkHidden("env-host") diff --git a/cmd/podman/containers/diff.go b/cmd/podman/containers/diff.go index d61f92bb7..f39b22ede 100644 --- a/cmd/podman/containers/diff.go +++ b/cmd/podman/containers/diff.go @@ -14,8 +14,8 @@ var ( diffCmd = &cobra.Command{ Use: "diff [flags] CONTAINER", Args: validate.IDOrLatestArgs, - Short: "Inspect changes on container's file systems", - Long: `Displays changes on a container filesystem. The container will be compared to its parent layer.`, + Short: "Inspect changes to the container's file systems", + Long: `Displays changes to the container filesystem's'. The container will be compared to its parent layer.`, RunE: diff, Example: `podman container diff myCtr podman container diff -l --format json myCtr`, @@ -35,10 +35,7 @@ func init() { flags.BoolVar(&diffOpts.Archive, "archive", true, "Save the diff as a tar archive") _ = flags.MarkHidden("archive") flags.StringVar(&diffOpts.Format, "format", "", "Change the output format") - - if !registry.IsRemote() { - flags.BoolVarP(&diffOpts.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - } + validate.AddLatestFlag(diffCmd, &diffOpts.Latest) } func diff(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/containers/exec.go b/cmd/podman/containers/exec.go index 4b2f0e9a2..e0fc740b5 100644 --- a/cmd/podman/containers/exec.go +++ b/cmd/podman/containers/exec.go @@ -6,6 +6,7 @@ import ( "os" "github.com/containers/libpod/v2/cmd/podman/registry" + "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/libpod/define" "github.com/containers/libpod/v2/pkg/domain/entities" envLib "github.com/containers/libpod/v2/pkg/env" @@ -53,14 +54,13 @@ func execFlags(flags *pflag.FlagSet) { flags.StringArrayVarP(&envInput, "env", "e", []string{}, "Set environment variables") flags.StringSliceVar(&envFile, "env-file", []string{}, "Read in a file of environment variables") flags.BoolVarP(&execOpts.Interactive, "interactive", "i", false, "Keep STDIN open even if not attached") - flags.BoolVarP(&execOpts.Latest, "latest", "l", false, "Act on the latest container podman is aware of") flags.BoolVar(&execOpts.Privileged, "privileged", false, "Give the process extended Linux capabilities inside the container. The default is false") flags.BoolVarP(&execOpts.Tty, "tty", "t", false, "Allocate a pseudo-TTY. The default is false") flags.StringVarP(&execOpts.User, "user", "u", "", "Sets the username or UID used and optionally the groupname or GID for the specified command") flags.UintVar(&execOpts.PreserveFDs, "preserve-fds", 0, "Pass N additional file descriptors to the container") flags.StringVarP(&execOpts.WorkDir, "workdir", "w", "", "Working directory inside the container") + if registry.IsRemote() { - _ = flags.MarkHidden("latest") _ = flags.MarkHidden("preserve-fds") } } @@ -70,20 +70,19 @@ func init() { Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, Command: execCommand, }) - flags := execCommand.Flags() - execFlags(flags) + execFlags(execCommand.Flags()) + validate.AddLatestFlag(execCommand, &execOpts.Latest) registry.Commands = append(registry.Commands, registry.CliCommand{ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, Command: containerExecCommand, Parent: containerCmd, }) - - containerExecFlags := containerExecCommand.Flags() - execFlags(containerExecFlags) + execFlags(containerExecCommand.Flags()) + validate.AddLatestFlag(containerExecCommand, &execOpts.Latest) } -func exec(cmd *cobra.Command, args []string) error { +func exec(_ *cobra.Command, args []string) error { var nameOrID string if len(args) == 0 && !execOpts.Latest { diff --git a/cmd/podman/containers/init.go b/cmd/podman/containers/init.go index c1f166d51..98f69fa4b 100644 --- a/cmd/podman/containers/init.go +++ b/cmd/podman/containers/init.go @@ -3,9 +3,9 @@ package containers import ( "fmt" - "github.com/containers/libpod/v2/cmd/podman/parse" "github.com/containers/libpod/v2/cmd/podman/registry" "github.com/containers/libpod/v2/cmd/podman/utils" + "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/pkg/domain/entities" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -20,7 +20,7 @@ var ( Long: initDescription, RunE: initContainer, Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, false) + return validate.CheckAllLatestAndCIDFile(cmd, args, false, false) }, Example: `podman init --latest podman init 3c45ef19d893 @@ -45,10 +45,6 @@ var ( func initFlags(flags *pflag.FlagSet) { flags.BoolVarP(&initOptions.All, "all", "a", false, "Initialize all containers") - flags.BoolVarP(&initOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } } func init() { @@ -58,15 +54,16 @@ func init() { }) flags := initCommand.Flags() initFlags(flags) + validate.AddLatestFlag(initCommand, &initOptions.Latest) registry.Commands = append(registry.Commands, registry.CliCommand{ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, Parent: containerCmd, Command: containerInitCommand, }) - containerInitFlags := containerInitCommand.Flags() initFlags(containerInitFlags) + validate.AddLatestFlag(containerInitCommand, &initOptions.Latest) } func initContainer(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/containers/inspect.go b/cmd/podman/containers/inspect.go index bea5cefd7..9ef3c2c4a 100644 --- a/cmd/podman/containers/inspect.go +++ b/cmd/podman/containers/inspect.go @@ -3,6 +3,7 @@ package containers import ( "github.com/containers/libpod/v2/cmd/podman/inspect" "github.com/containers/libpod/v2/cmd/podman/registry" + "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/pkg/domain/entities" "github.com/spf13/cobra" ) @@ -30,7 +31,7 @@ func init() { flags := inspectCmd.Flags() flags.BoolVarP(&inspectOpts.Size, "size", "s", false, "Display total file size") flags.StringVarP(&inspectOpts.Format, "format", "f", "json", "Format the output to a Go template or json") - flags.BoolVarP(&inspectOpts.Latest, "latest", "l", false, "Act on the latest container Podman is aware of") + validate.AddLatestFlag(inspectCmd, &inspectOpts.Latest) } func inspectExec(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/containers/kill.go b/cmd/podman/containers/kill.go index 22f7383b1..da60fcf52 100644 --- a/cmd/podman/containers/kill.go +++ b/cmd/podman/containers/kill.go @@ -5,9 +5,9 @@ import ( "errors" "fmt" - "github.com/containers/libpod/v2/cmd/podman/parse" "github.com/containers/libpod/v2/cmd/podman/registry" "github.com/containers/libpod/v2/cmd/podman/utils" + "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/pkg/domain/entities" "github.com/containers/libpod/v2/pkg/signal" "github.com/spf13/cobra" @@ -22,7 +22,7 @@ var ( Long: killDescription, RunE: kill, Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, false) + return validate.CheckAllLatestAndCIDFile(cmd, args, false, false) }, Example: `podman kill mywebserver podman kill 860a4b23 @@ -31,7 +31,7 @@ var ( containerKillCommand = &cobra.Command{ Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, false) + return validate.CheckAllLatestAndCIDFile(cmd, args, false, false) }, Use: killCommand.Use, Short: killCommand.Short, @@ -50,10 +50,6 @@ var ( func killFlags(flags *pflag.FlagSet) { flags.BoolVarP(&killOptions.All, "all", "a", false, "Signal all running containers") flags.StringVarP(&killOptions.Signal, "signal", "s", "KILL", "Signal to send to the container") - flags.BoolVarP(&killOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } } func init() { @@ -61,20 +57,19 @@ func init() { Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, Command: killCommand, }) - flags := killCommand.Flags() - killFlags(flags) + killFlags(killCommand.Flags()) + validate.AddLatestFlag(killCommand, &killOptions.Latest) registry.Commands = append(registry.Commands, registry.CliCommand{ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, Command: containerKillCommand, Parent: containerCmd, }) - - containerKillFlags := containerKillCommand.Flags() - killFlags(containerKillFlags) + killFlags(containerKillCommand.Flags()) + validate.AddLatestFlag(containerKillCommand, &killOptions.Latest) } -func kill(cmd *cobra.Command, args []string) error { +func kill(_ *cobra.Command, args []string) error { var ( err error errs utils.OutputErrors diff --git a/cmd/podman/containers/list.go b/cmd/podman/containers/list.go index e2688623d..2d107d51d 100644 --- a/cmd/podman/containers/list.go +++ b/cmd/podman/containers/list.go @@ -29,4 +29,5 @@ func init() { Parent: containerCmd, }) listFlagSet(listCmd.Flags()) + validate.AddLatestFlag(listCmd, &listOpts.Latest) } diff --git a/cmd/podman/containers/logs.go b/cmd/podman/containers/logs.go index 85d3262da..850cb2e1f 100644 --- a/cmd/podman/containers/logs.go +++ b/cmd/podman/containers/logs.go @@ -4,6 +4,7 @@ import ( "os" "github.com/containers/libpod/v2/cmd/podman/registry" + "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/pkg/domain/entities" "github.com/containers/libpod/v2/pkg/util" "github.com/pkg/errors" @@ -68,9 +69,8 @@ func init() { Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, Command: logsCommand, }) - - flags := logsCommand.Flags() - logsFlags(flags) + logsFlags(logsCommand.Flags()) + validate.AddLatestFlag(logsCommand, &logsOptions.Latest) // container logs registry.Commands = append(registry.Commands, registry.CliCommand{ @@ -78,15 +78,13 @@ func init() { Command: containerLogsCommand, Parent: containerCmd, }) - - containerLogsFlags := containerLogsCommand.Flags() - logsFlags(containerLogsFlags) + logsFlags(containerLogsCommand.Flags()) + validate.AddLatestFlag(containerLogsCommand, &logsOptions.Latest) } func logsFlags(flags *pflag.FlagSet) { flags.BoolVar(&logsOptions.Details, "details", false, "Show extra details provided to the logs") flags.BoolVarP(&logsOptions.Follow, "follow", "f", false, "Follow log output. The default is false") - flags.BoolVarP(&logsOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") flags.StringVar(&logsOptions.SinceRaw, "since", "", "Show logs since TIMESTAMP") flags.Int64Var(&logsOptions.Tail, "tail", -1, "Output the specified number of LINES at the end of the logs. Defaults to -1, which prints all lines") flags.BoolVarP(&logsOptions.Timestamps, "timestamps", "t", false, "Output the timestamps in the log") @@ -95,7 +93,7 @@ func logsFlags(flags *pflag.FlagSet) { _ = flags.MarkHidden("details") } -func logs(cmd *cobra.Command, args []string) error { +func logs(_ *cobra.Command, args []string) error { if logsOptions.SinceRaw != "" { // parse time, error out if something is wrong since, err := util.ParseInputTime(logsOptions.SinceRaw) diff --git a/cmd/podman/containers/mount.go b/cmd/podman/containers/mount.go index f2b66a2cd..44af27801 100644 --- a/cmd/podman/containers/mount.go +++ b/cmd/podman/containers/mount.go @@ -6,9 +6,9 @@ import ( "text/tabwriter" "text/template" - "github.com/containers/libpod/v2/cmd/podman/parse" "github.com/containers/libpod/v2/cmd/podman/registry" "github.com/containers/libpod/v2/cmd/podman/utils" + "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/pkg/domain/entities" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -28,7 +28,7 @@ var ( Long: mountDescription, RunE: mount, Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, true, false) + return validate.CheckAllLatestAndCIDFile(cmd, args, true, false) }, } @@ -47,7 +47,6 @@ var ( func mountFlags(flags *pflag.FlagSet) { flags.BoolVarP(&mountOpts.All, "all", "a", false, "Mount all containers") flags.StringVar(&mountOpts.Format, "format", "", "Change the output format to Go template") - flags.BoolVarP(&mountOpts.Latest, "latest", "l", false, "Act on the latest container podman is aware of") flags.BoolVar(&mountOpts.NoTruncate, "notruncate", false, "Do not truncate output") } @@ -56,19 +55,19 @@ func init() { Mode: []entities.EngineMode{entities.ABIMode}, Command: mountCommand, }) - flags := mountCommand.Flags() - mountFlags(flags) + mountFlags(mountCommand.Flags()) + validate.AddLatestFlag(mountCommand, &mountOpts.Latest) registry.Commands = append(registry.Commands, registry.CliCommand{ Mode: []entities.EngineMode{entities.ABIMode}, Command: containerMountCommmand, Parent: containerCmd, }) - containerMountFlags := containerMountCommmand.Flags() - mountFlags(containerMountFlags) + mountFlags(containerMountCommmand.Flags()) + validate.AddLatestFlag(containerMountCommmand, &mountOpts.Latest) } -func mount(cmd *cobra.Command, args []string) error { +func mount(_ *cobra.Command, args []string) error { var ( errs utils.OutputErrors ) diff --git a/cmd/podman/containers/pause.go b/cmd/podman/containers/pause.go index 83a3824cf..33d6ff06f 100644 --- a/cmd/podman/containers/pause.go +++ b/cmd/podman/containers/pause.go @@ -66,6 +66,7 @@ func pause(cmd *cobra.Command, args []string) error { if rootless.IsRootless() && !registry.IsRemote() { return errors.New("pause is not supported for rootless containers") } + if len(args) < 1 && !pauseOpts.All { return errors.Errorf("you must provide at least one container name or id") } diff --git a/cmd/podman/containers/port.go b/cmd/podman/containers/port.go index 3ef8f0fde..7e548b6c9 100644 --- a/cmd/podman/containers/port.go +++ b/cmd/podman/containers/port.go @@ -5,8 +5,8 @@ import ( "strconv" "strings" - "github.com/containers/libpod/v2/cmd/podman/parse" "github.com/containers/libpod/v2/cmd/podman/registry" + "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/pkg/domain/entities" "github.com/cri-o/ocicni/pkg/ocicni" "github.com/pkg/errors" @@ -23,7 +23,7 @@ var ( Long: portDescription, RunE: port, Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, true, false) + return validate.CheckAllLatestAndCIDFile(cmd, args, true, false) }, Example: `podman port --all podman port ctrID 80/tcp @@ -36,7 +36,7 @@ var ( Long: portDescription, RunE: portCommand.RunE, Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, true, false) + return validate.CheckAllLatestAndCIDFile(cmd, args, true, false) }, Example: `podman container port --all podman container port --latest 80`, @@ -49,10 +49,6 @@ var ( func portFlags(flags *pflag.FlagSet) { flags.BoolVarP(&portOpts.All, "all", "a", false, "Display port information for all containers") - flags.BoolVarP(&portOpts.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } } func init() { @@ -60,22 +56,19 @@ func init() { Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, Command: portCommand, }) - - flags := portCommand.Flags() - portFlags(flags) + portFlags(portCommand.Flags()) + validate.AddLatestFlag(portCommand, &portOpts.Latest) registry.Commands = append(registry.Commands, registry.CliCommand{ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, Command: containerPortCommand, Parent: containerCmd, }) - - containerPortflags := containerPortCommand.Flags() - portFlags(containerPortflags) - + portFlags(containerPortCommand.Flags()) + validate.AddLatestFlag(containerPortCommand, &portOpts.Latest) } -func port(cmd *cobra.Command, args []string) error { +func port(_ *cobra.Command, args []string) error { var ( container string err error diff --git a/cmd/podman/containers/ps.go b/cmd/podman/containers/ps.go index 24266244e..7c84cbae1 100644 --- a/cmd/podman/containers/ps.go +++ b/cmd/podman/containers/ps.go @@ -50,6 +50,7 @@ func init() { Command: psCommand, }) listFlagSet(psCommand.Flags()) + validate.AddLatestFlag(psCommand, &listOpts.Latest) } func listFlagSet(flags *pflag.FlagSet) { @@ -57,7 +58,6 @@ func listFlagSet(flags *pflag.FlagSet) { flags.StringSliceVarP(&filters, "filter", "f", []string{}, "Filter output based on conditions given") flags.StringVar(&listOpts.Format, "format", "", "Pretty-print containers to JSON or using a Go template") flags.IntVarP(&listOpts.Last, "last", "n", -1, "Print the n last created containers (all states)") - flags.BoolVarP(&listOpts.Latest, "latest", "l", false, "Show the latest container created (all states)") flags.BoolVar(&listOpts.Namespace, "namespace", false, "Display namespace information") flags.BoolVar(&listOpts.Namespace, "ns", false, "Display namespace information") flags.BoolVar(&noTrunc, "no-trunc", false, "Display the extended information") @@ -69,10 +69,6 @@ func listFlagSet(flags *pflag.FlagSet) { sort := validate.Value(&listOpts.Sort, "command", "created", "id", "image", "names", "runningfor", "size", "status") flags.Var(sort, "sort", "Sort output by: "+sort.Choices()) - - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } } func checkFlags(c *cobra.Command) error { // latest, and last are mutually exclusive. diff --git a/cmd/podman/containers/restart.go b/cmd/podman/containers/restart.go index d3e90c160..393b003a9 100644 --- a/cmd/podman/containers/restart.go +++ b/cmd/podman/containers/restart.go @@ -4,9 +4,9 @@ import ( "context" "fmt" - "github.com/containers/libpod/v2/cmd/podman/parse" "github.com/containers/libpod/v2/cmd/podman/registry" "github.com/containers/libpod/v2/cmd/podman/utils" + "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/libpod/define" "github.com/containers/libpod/v2/pkg/domain/entities" "github.com/pkg/errors" @@ -25,7 +25,7 @@ var ( Long: restartDescription, RunE: restart, Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, false) + return validate.CheckAllLatestAndCIDFile(cmd, args, false, false) }, Example: `podman restart ctrID podman restart --latest @@ -50,12 +50,9 @@ var ( func restartFlags(flags *pflag.FlagSet) { flags.BoolVarP(&restartOptions.All, "all", "a", false, "Restart all non-running containers") - flags.BoolVarP(&restartOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") flags.BoolVar(&restartOptions.Running, "running", false, "Restart only running containers when --all is used") flags.UintVarP(&restartTimeout, "time", "t", containerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } + flags.SetNormalizeFunc(utils.AliasFlags) } @@ -64,17 +61,16 @@ func init() { Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, Command: restartCommand, }) - flags := restartCommand.Flags() - restartFlags(flags) + restartFlags(restartCommand.Flags()) + validate.AddLatestFlag(restartCommand, &restartOptions.Latest) registry.Commands = append(registry.Commands, registry.CliCommand{ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, Command: containerRestartCommand, Parent: containerCmd, }) - - containerRestartFlags := containerRestartCommand.Flags() - restartFlags(containerRestartFlags) + restartFlags(containerRestartCommand.Flags()) + validate.AddLatestFlag(containerRestartCommand, &restartOptions.Latest) } func restart(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/containers/restore.go b/cmd/podman/containers/restore.go index 975087a97..e9e0ad6fc 100644 --- a/cmd/podman/containers/restore.go +++ b/cmd/podman/containers/restore.go @@ -4,9 +4,9 @@ import ( "context" "fmt" - "github.com/containers/libpod/v2/cmd/podman/parse" "github.com/containers/libpod/v2/cmd/podman/registry" "github.com/containers/libpod/v2/cmd/podman/utils" + "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/pkg/domain/entities" "github.com/containers/libpod/v2/pkg/rootless" "github.com/pkg/errors" @@ -25,7 +25,7 @@ var ( Long: restoreDescription, RunE: restore, Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, true, false) + return validate.CheckAllLatestAndCIDFile(cmd, args, true, false) }, Example: `podman container restore ctrID podman container restore --latest @@ -46,19 +46,16 @@ func init() { flags := restoreCommand.Flags() flags.BoolVarP(&restoreOptions.All, "all", "a", false, "Restore all checkpointed containers") flags.BoolVarP(&restoreOptions.Keep, "keep", "k", false, "Keep all temporary checkpoint files") - flags.BoolVarP(&restoreOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") flags.BoolVar(&restoreOptions.TCPEstablished, "tcp-established", false, "Restore a container with established TCP connections") flags.StringVarP(&restoreOptions.Import, "import", "i", "", "Restore from exported checkpoint archive (tar.gz)") flags.StringVarP(&restoreOptions.Name, "name", "n", "", "Specify new name for container restored from exported checkpoint (only works with --import)") flags.BoolVar(&restoreOptions.IgnoreRootFS, "ignore-rootfs", false, "Do not apply root file-system changes when importing from exported checkpoint") flags.BoolVar(&restoreOptions.IgnoreStaticIP, "ignore-static-ip", false, "Ignore IP address set via --static-ip") flags.BoolVar(&restoreOptions.IgnoreStaticMAC, "ignore-static-mac", false, "Ignore MAC address set via --mac-address") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } + validate.AddLatestFlag(restoreCommand, &restoreOptions.Latest) } -func restore(cmd *cobra.Command, args []string) error { +func restore(_ *cobra.Command, args []string) error { var errs utils.OutputErrors if rootless.IsRootless() { return errors.New("restoring a container requires root") diff --git a/cmd/podman/containers/rm.go b/cmd/podman/containers/rm.go index 3afda4c5d..427e1e72c 100644 --- a/cmd/podman/containers/rm.go +++ b/cmd/podman/containers/rm.go @@ -5,9 +5,9 @@ import ( "fmt" "strings" - "github.com/containers/libpod/v2/cmd/podman/parse" "github.com/containers/libpod/v2/cmd/podman/registry" "github.com/containers/libpod/v2/cmd/podman/utils" + "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/libpod/define" "github.com/containers/libpod/v2/pkg/domain/entities" "github.com/pkg/errors" @@ -26,7 +26,7 @@ var ( Long: rmDescription, RunE: rm, Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, true) + return validate.CheckAllLatestAndCIDFile(cmd, args, false, true) }, Example: `podman rm imageID podman rm mywebserver myflaskserver 860a4b23 @@ -40,7 +40,7 @@ var ( Long: rmCommand.Long, RunE: rmCommand.RunE, Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, true) + return validate.CheckAllLatestAndCIDFile(cmd, args, false, true) }, Example: `podman container rm imageID podman container rm mywebserver myflaskserver 860a4b23 @@ -57,12 +57,11 @@ func rmFlags(flags *pflag.FlagSet) { flags.BoolVarP(&rmOptions.All, "all", "a", false, "Remove all containers") flags.BoolVarP(&rmOptions.Ignore, "ignore", "i", false, "Ignore errors when a specified container is missing") flags.BoolVarP(&rmOptions.Force, "force", "f", false, "Force removal of a running or unusable container. The default is false") - flags.BoolVarP(&rmOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") flags.BoolVar(&rmOptions.Storage, "storage", false, "Remove container from storage library") flags.BoolVarP(&rmOptions.Volumes, "volumes", "v", false, "Remove anonymous volumes associated with the container") flags.StringArrayVarP(&rmOptions.CIDFiles, "cidfile", "", nil, "Read the container ID from the file") + if registry.IsRemote() { - _ = flags.MarkHidden("latest") _ = flags.MarkHidden("ignore") _ = flags.MarkHidden("cidfile") _ = flags.MarkHidden("storage") @@ -75,18 +74,18 @@ func init() { Command: rmCommand, }) rmFlags(rmCommand.Flags()) + validate.AddLatestFlag(rmCommand, &rmOptions.Latest) registry.Commands = append(registry.Commands, registry.CliCommand{ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, Command: containerRmCommand, Parent: containerCmd, }) - - containerRmFlags := containerRmCommand.Flags() - rmFlags(containerRmFlags) + rmFlags(containerRmCommand.Flags()) + validate.AddLatestFlag(containerRmCommand, &rmOptions.Latest) } -func rm(cmd *cobra.Command, args []string) error { +func rm(_ *cobra.Command, args []string) error { return removeContainers(args, rmOptions, true) } diff --git a/cmd/podman/containers/run.go b/cmd/podman/containers/run.go index c1af2c1d3..638b1c96e 100644 --- a/cmd/podman/containers/run.go +++ b/cmd/podman/containers/run.go @@ -61,6 +61,7 @@ func runFlags(flags *pflag.FlagSet) { flags.SetNormalizeFunc(common.AliasFlags) flags.BoolVar(&runOpts.SigProxy, "sig-proxy", true, "Proxy received signals to the process") flags.BoolVar(&runRmi, "rmi", false, "Remove container image unless used by other containers") + if registry.IsRemote() { _ = flags.MarkHidden("authfile") _ = flags.MarkHidden("env-host") diff --git a/cmd/podman/containers/start.go b/cmd/podman/containers/start.go index 3c3bffaba..941588137 100644 --- a/cmd/podman/containers/start.go +++ b/cmd/podman/containers/start.go @@ -6,6 +6,7 @@ import ( "github.com/containers/libpod/v2/cmd/podman/registry" "github.com/containers/libpod/v2/cmd/podman/utils" + "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/libpod/define" "github.com/containers/libpod/v2/pkg/domain/entities" "github.com/pkg/errors" @@ -44,10 +45,9 @@ func startFlags(flags *pflag.FlagSet) { flags.BoolVarP(&startOptions.Attach, "attach", "a", false, "Attach container's STDOUT and STDERR") flags.StringVar(&startOptions.DetachKeys, "detach-keys", containerConfig.DetachKeys(), "Select the key sequence for detaching a container. Format is a single character `[a-Z]` or a comma separated sequence of `ctrl-`, where `` is one of: `a-z`, `@`, `^`, `[`, `\\`, `]`, `^` or `_`") flags.BoolVarP(&startOptions.Interactive, "interactive", "i", false, "Keep STDIN open even if not attached") - flags.BoolVarP(&startOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") flags.BoolVar(&startOptions.SigProxy, "sig-proxy", false, "Proxy received signals to the process (default true if attaching, false otherwise)") + if registry.IsRemote() { - _ = flags.MarkHidden("latest") _ = flags.MarkHidden("sig-proxy") } } @@ -56,17 +56,17 @@ func init() { Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, Command: startCommand, }) - flags := startCommand.Flags() - startFlags(flags) + startFlags(startCommand.Flags()) + validate.AddLatestFlag(startCommand, &startOptions.Latest) registry.Commands = append(registry.Commands, registry.CliCommand{ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, Command: containerStartCommand, Parent: containerCmd, }) + startFlags(containerStartCommand.Flags()) + validate.AddLatestFlag(containerStartCommand, &startOptions.Latest) - containerStartFlags := containerStartCommand.Flags() - startFlags(containerStartFlags) } func start(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/containers/stats.go b/cmd/podman/containers/stats.go index 9b877b3af..86674cfc9 100644 --- a/cmd/podman/containers/stats.go +++ b/cmd/podman/containers/stats.go @@ -10,6 +10,7 @@ import ( tm "github.com/buger/goterm" "github.com/containers/libpod/v2/cmd/podman/registry" + "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/libpod/define" "github.com/containers/libpod/v2/pkg/cgroups" "github.com/containers/libpod/v2/pkg/domain/entities" @@ -56,12 +57,8 @@ var ( func statFlags(flags *pflag.FlagSet) { flags.BoolVarP(&statsOptions.All, "all", "a", false, "Show all containers. Only running containers are shown by default. The default is false") flags.StringVar(&statsOptions.Format, "format", "", "Pretty-print container statistics to JSON or using a Go template") - flags.BoolVarP(&statsOptions.Latest, "latest", "l", false, "Act on the latest container Podman is aware of") flags.BoolVar(&statsOptions.NoReset, "no-reset", false, "Disable resetting the screen between intervals") flags.BoolVar(&statsOptions.NoStream, "no-stream", false, "Disable streaming stats and only pull the first result, default setting is false") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } } func init() { @@ -69,17 +66,16 @@ func init() { Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, Command: statsCommand, }) - flags := statsCommand.Flags() - statFlags(flags) + statFlags(statsCommand.Flags()) + validate.AddLatestFlag(statsCommand, &statsOptions.Latest) registry.Commands = append(registry.Commands, registry.CliCommand{ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, Command: containerStatsCommand, Parent: containerCmd, }) - - containerStatsFlags := containerStatsCommand.Flags() - statFlags(containerStatsFlags) + statFlags(containerStatsCommand.Flags()) + validate.AddLatestFlag(containerStatsCommand, &statsOptions.Latest) } // stats is different in that it will assume running containers if diff --git a/cmd/podman/containers/stop.go b/cmd/podman/containers/stop.go index 7e741d161..7959918a8 100644 --- a/cmd/podman/containers/stop.go +++ b/cmd/podman/containers/stop.go @@ -4,9 +4,9 @@ import ( "context" "fmt" - "github.com/containers/libpod/v2/cmd/podman/parse" "github.com/containers/libpod/v2/cmd/podman/registry" "github.com/containers/libpod/v2/cmd/podman/utils" + "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/pkg/domain/entities" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -22,7 +22,7 @@ var ( Long: stopDescription, RunE: stop, Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, true) + return validate.CheckAllLatestAndCIDFile(cmd, args, false, true) }, Example: `podman stop ctrID podman stop --latest @@ -35,7 +35,7 @@ var ( Long: stopCommand.Long, RunE: stopCommand.RunE, Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, true) + return validate.CheckAllLatestAndCIDFile(cmd, args, false, true) }, Example: `podman container stop ctrID podman container stop --latest @@ -52,11 +52,9 @@ func stopFlags(flags *pflag.FlagSet) { flags.BoolVarP(&stopOptions.All, "all", "a", false, "Stop all running containers") flags.BoolVarP(&stopOptions.Ignore, "ignore", "i", false, "Ignore errors when a specified container is missing") flags.StringArrayVarP(&stopOptions.CIDFiles, "cidfile", "", nil, "Read the container ID from the file") - flags.BoolVarP(&stopOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") flags.UintVarP(&stopTimeout, "time", "t", containerConfig.Engine.StopTimeout, "Seconds to wait for stop before killing the container") if registry.IsRemote() { - _ = flags.MarkHidden("latest") _ = flags.MarkHidden("cidfile") _ = flags.MarkHidden("ignore") } @@ -68,8 +66,8 @@ func init() { Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, Command: stopCommand, }) - flags := stopCommand.Flags() - stopFlags(flags) + stopFlags(stopCommand.Flags()) + validate.AddLatestFlag(stopCommand, &stopOptions.Latest) registry.Commands = append(registry.Commands, registry.CliCommand{ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, @@ -77,8 +75,8 @@ func init() { Parent: containerCmd, }) - containerStopFlags := containerStopCommand.Flags() - stopFlags(containerStopFlags) + stopFlags(containerStopCommand.Flags()) + validate.AddLatestFlag(containerStopCommand, &stopOptions.Latest) } func stop(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/containers/top.go b/cmd/podman/containers/top.go index adeba5ee8..079a0ca1e 100644 --- a/cmd/podman/containers/top.go +++ b/cmd/podman/containers/top.go @@ -8,6 +8,7 @@ import ( "text/tabwriter" "github.com/containers/libpod/v2/cmd/podman/registry" + "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/pkg/domain/entities" "github.com/containers/libpod/v2/pkg/util" "github.com/pkg/errors" @@ -51,11 +52,7 @@ podman container top ctrID -eo user,pid,comm`, func topFlags(flags *pflag.FlagSet) { flags.SetInterspersed(false) flags.BoolVar(&topOptions.ListDescriptors, "list-descriptors", false, "") - flags.BoolVarP(&topOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") _ = flags.MarkHidden("list-descriptors") // meant only for bash completion - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } } func init() { @@ -63,8 +60,8 @@ func init() { Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, Command: topCommand, }) - flags := topCommand.Flags() - topFlags(flags) + topFlags(topCommand.Flags()) + validate.AddLatestFlag(topCommand, &topOptions.Latest) descriptors, err := util.GetContainerPidInformationDescriptors() if err == nil { @@ -77,8 +74,8 @@ func init() { Command: containerTopCommand, Parent: containerCmd, }) - containerTopFlags := containerTopCommand.Flags() - topFlags(containerTopFlags) + topFlags(containerTopCommand.Flags()) + validate.AddLatestFlag(containerTopCommand, &topOptions.Latest) } func top(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/containers/unmount.go b/cmd/podman/containers/unmount.go index 11889e8b0..c40c2be7e 100644 --- a/cmd/podman/containers/unmount.go +++ b/cmd/podman/containers/unmount.go @@ -3,9 +3,9 @@ package containers import ( "fmt" - "github.com/containers/libpod/v2/cmd/podman/parse" "github.com/containers/libpod/v2/cmd/podman/registry" "github.com/containers/libpod/v2/cmd/podman/utils" + "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/pkg/domain/entities" "github.com/spf13/cobra" "github.com/spf13/pflag" @@ -25,7 +25,7 @@ var ( Long: description, RunE: unmount, Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, false) + return validate.CheckAllLatestAndCIDFile(cmd, args, false, false) }, Example: `podman umount ctrID podman umount ctrID1 ctrID2 ctrID3 @@ -38,7 +38,7 @@ var ( Long: umountCommand.Long, RunE: umountCommand.RunE, Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, false) + return validate.CheckAllLatestAndCIDFile(cmd, args, false, false) }, Example: `podman container umount ctrID podman container umount ctrID1 ctrID2 ctrID3 @@ -53,7 +53,6 @@ var ( func umountFlags(flags *pflag.FlagSet) { flags.BoolVarP(&unmountOpts.All, "all", "a", false, "Umount all of the currently mounted containers") flags.BoolVarP(&unmountOpts.Force, "force", "f", false, "Force the complete umount all of the currently mounted containers") - flags.BoolVarP(&unmountOpts.Latest, "latest", "l", false, "Act on the latest container podman is aware of") } func init() { @@ -61,17 +60,16 @@ func init() { Mode: []entities.EngineMode{entities.ABIMode}, Command: umountCommand, }) - flags := umountCommand.Flags() - umountFlags(flags) + umountFlags(umountCommand.Flags()) + validate.AddLatestFlag(umountCommand, &unmountOpts.Latest) registry.Commands = append(registry.Commands, registry.CliCommand{ Mode: []entities.EngineMode{entities.ABIMode}, Command: containerUnmountCommand, Parent: containerCmd, }) - - containerUmountFlags := containerUnmountCommand.Flags() - umountFlags(containerUmountFlags) + umountFlags(containerUnmountCommand.Flags()) + validate.AddLatestFlag(containerUnmountCommand, &unmountOpts.Latest) } func unmount(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/containers/wait.go b/cmd/podman/containers/wait.go index 82bfb2020..c30bfe405 100644 --- a/cmd/podman/containers/wait.go +++ b/cmd/podman/containers/wait.go @@ -47,9 +47,6 @@ var ( func waitFlags(flags *pflag.FlagSet) { flags.DurationVarP(&waitOptions.Interval, "interval", "i", time.Duration(250), "Milliseconds to wait before polling for completion") flags.StringVar(&waitCondition, "condition", "stopped", "Condition to wait on") - if !registry.IsRemote() { - flags.BoolVarP(&waitOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - } } func init() { @@ -57,17 +54,17 @@ func init() { Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, Command: waitCommand, }) - flags := waitCommand.Flags() - waitFlags(flags) + waitFlags(waitCommand.Flags()) + validate.AddLatestFlag(waitCommand, &waitOptions.Latest) registry.Commands = append(registry.Commands, registry.CliCommand{ Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode}, Command: containerWaitCommand, Parent: containerCmd, }) + waitFlags(containerWaitCommand.Flags()) + validate.AddLatestFlag(containerWaitCommand, &waitOptions.Latest) - containerWaitFlags := containerWaitCommand.Flags() - waitFlags(containerWaitFlags) } func wait(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/diff.go b/cmd/podman/diff.go index 14a4529d5..cdd908cf1 100644 --- a/cmd/podman/diff.go +++ b/cmd/podman/diff.go @@ -17,12 +17,11 @@ var ( // Command: podman _diff_ Object_ID diffDescription = `Displays changes on a container or image's filesystem. The container or image will be compared to its parent layer.` diffCmd = &cobra.Command{ - Use: "diff [flags] {CONTAINER_ID | IMAGE_ID}", - Args: validate.IDOrLatestArgs, - Short: "Display the changes of object's file system", - Long: diffDescription, - TraverseChildren: true, - RunE: diff, + Use: "diff [flags] {CONTAINER_ID | IMAGE_ID}", + Args: validate.IDOrLatestArgs, + Short: "Display the changes to the object's file system", + Long: diffDescription, + RunE: diff, Example: `podman diff imageID podman diff ctrID podman diff --format json redis:alpine`, @@ -40,10 +39,7 @@ func init() { flags.BoolVar(&diffOpts.Archive, "archive", true, "Save the diff as a tar archive") _ = flags.MarkHidden("archive") flags.StringVar(&diffOpts.Format, "format", "", "Change the output format") - - if !registry.IsRemote() { - flags.BoolVarP(&diffOpts.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - } + validate.AddLatestFlag(diffCmd, &diffOpts.Latest) } func diff(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/generate/generate.go b/cmd/podman/generate/generate.go index 3b3cb238d..d85d93347 100644 --- a/cmd/podman/generate/generate.go +++ b/cmd/podman/generate/generate.go @@ -11,11 +11,10 @@ import ( var ( // Command: podman _generate_ generateCmd = &cobra.Command{ - Use: "generate", - Short: "Generate structured data based on containers and pods.", - Long: "Generate structured data (e.g., Kubernetes yaml or systemd units) based on containers and pods.", - TraverseChildren: true, - RunE: validate.SubCommandExists, + Use: "generate", + Short: "Generate structured data based on containers and pods.", + Long: "Generate structured data (e.g., Kubernetes yaml or systemd units) based on containers and pods.", + RunE: validate.SubCommandExists, } containerConfig = util.DefaultContainerConfig() ) diff --git a/cmd/podman/healthcheck/healthcheck.go b/cmd/podman/healthcheck/healthcheck.go index 8b5d7bf80..fdf40e872 100644 --- a/cmd/podman/healthcheck/healthcheck.go +++ b/cmd/podman/healthcheck/healthcheck.go @@ -10,11 +10,10 @@ import ( var ( // Command: healthcheck healthCmd = &cobra.Command{ - Use: "healthcheck", - Short: "Manage health checks on containers", - Long: "Run health checks on containers", - TraverseChildren: true, - RunE: validate.SubCommandExists, + Use: "healthcheck", + Short: "Manage health checks on containers", + Long: "Run health checks on containers", + RunE: validate.SubCommandExists, } ) diff --git a/cmd/podman/images/build.go b/cmd/podman/images/build.go index 40a9a8e7f..3ea74b4af 100644 --- a/cmd/podman/images/build.go +++ b/cmd/podman/images/build.go @@ -40,11 +40,11 @@ var ( // Command: podman _diff_ Object_ID buildDescription = "Builds an OCI or Docker image using instructions from one or more Containerfiles and a specified build context directory." buildCmd = &cobra.Command{ - Use: "build [flags] [CONTEXT]", - Short: "Build an image using instructions from Containerfiles", - Long: buildDescription, - TraverseChildren: true, - RunE: build, + Use: "build [flags] [CONTEXT]", + Short: "Build an image using instructions from Containerfiles", + Long: buildDescription, + Args: cobra.MaximumNArgs(1), + RunE: build, Example: `podman build . podman build --creds=username:password -t imageName -f Containerfile.simple . podman build --layers --force-rm --tag imageName .`, diff --git a/cmd/podman/images/diff.go b/cmd/podman/images/diff.go index cd674ee9c..10a1c06ec 100644 --- a/cmd/podman/images/diff.go +++ b/cmd/podman/images/diff.go @@ -14,8 +14,8 @@ var ( diffCmd = &cobra.Command{ Use: "diff [flags] IMAGE", Args: cobra.ExactArgs(1), - Short: "Inspect changes on image's file systems", - Long: `Displays changes on a image's filesystem. The image will be compared to its parent layer.`, + Short: "Inspect changes to the image's file systems", + Long: `Displays changes to the image's filesystem. The image will be compared to its parent layer.`, RunE: diff, Example: `podman image diff myImage podman image diff --format json redis:alpine`, diff --git a/cmd/podman/images/image.go b/cmd/podman/images/image.go index 85c1afc0e..89badd035 100644 --- a/cmd/podman/images/image.go +++ b/cmd/podman/images/image.go @@ -13,11 +13,10 @@ var ( // Command: podman _image_ imageCmd = &cobra.Command{ - Use: "image", - Short: "Manage images", - Long: "Manage images", - TraverseChildren: true, - RunE: validate.SubCommandExists, + Use: "image", + Short: "Manage images", + Long: "Manage images", + RunE: validate.SubCommandExists, } ) diff --git a/cmd/podman/images/search.go b/cmd/podman/images/search.go index 7c5bd890d..f1a2cda96 100644 --- a/cmd/podman/images/search.go +++ b/cmd/podman/images/search.go @@ -86,6 +86,7 @@ func searchFlags(flags *pflag.FlagSet) { flags.BoolVar(&searchOptions.NoTrunc, "no-trunc", false, "Do not truncate the output") flags.StringVar(&searchOptions.Authfile, "authfile", auth.GetDefaultAuthFile(), "Path of the authentication file. Use REGISTRY_AUTH_FILE environment variable to override") flags.BoolVar(&searchOptions.TLSVerifyCLI, "tls-verify", true, "Require HTTPS and verify certificates when contacting registries") + if registry.IsRemote() { _ = flags.MarkHidden("authfile") _ = flags.MarkHidden("tls-verify") diff --git a/cmd/podman/inspect.go b/cmd/podman/inspect.go index 667271aaf..4dd6b4a9a 100644 --- a/cmd/podman/inspect.go +++ b/cmd/podman/inspect.go @@ -10,11 +10,10 @@ import ( var ( // Command: podman _inspect_ Object_ID inspectCmd = &cobra.Command{ - Use: "inspect [flags] {CONTAINER_ID | IMAGE_ID}", - Short: "Display the configuration of object denoted by ID", - Long: "Displays the low-level information on an object identified by name or ID", - TraverseChildren: true, - RunE: inspectExec, + Use: "inspect [flags] {CONTAINER_ID | IMAGE_ID}", + Short: "Display the configuration of object denoted by ID", + Long: "Displays the low-level information on an object identified by name or ID", + RunE: inspectExec, Example: `podman inspect fedora podman inspect --type image fedora podman inspect CtrID ImgID diff --git a/cmd/podman/inspect/inspect.go b/cmd/podman/inspect/inspect.go index ce51bc1e9..6fcca597b 100644 --- a/cmd/podman/inspect/inspect.go +++ b/cmd/podman/inspect/inspect.go @@ -8,6 +8,7 @@ import ( "github.com/containers/buildah/pkg/formats" "github.com/containers/libpod/v2/cmd/podman/registry" + "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/pkg/domain/entities" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -32,8 +33,8 @@ func AddInspectFlagSet(cmd *cobra.Command) *entities.InspectOptions { flags.BoolVarP(&opts.Size, "size", "s", false, "Display total file size") flags.StringVarP(&opts.Format, "format", "f", "json", "Format the output to a Go template or json") flags.StringVarP(&opts.Type, "type", "t", AllType, fmt.Sprintf("Specify inspect-oject type (%q, %q or %q)", ImageType, ContainerType, AllType)) - flags.BoolVarP(&opts.Latest, "latest", "l", false, "Act on the latest container Podman is aware of") + validate.AddLatestFlag(cmd, &opts.Latest) return &opts } diff --git a/cmd/podman/main.go b/cmd/podman/main.go index c229e9881..5f740a006 100644 --- a/cmd/podman/main.go +++ b/cmd/podman/main.go @@ -16,7 +16,7 @@ import ( _ "github.com/containers/libpod/v2/cmd/podman/system" _ "github.com/containers/libpod/v2/cmd/podman/volumes" "github.com/containers/libpod/v2/pkg/rootless" - "github.com/containers/libpod/pkg/terminal" + "github.com/containers/libpod/v2/pkg/terminal" "github.com/containers/storage/pkg/reexec" "github.com/sirupsen/logrus" "github.com/spf13/cobra" diff --git a/cmd/podman/manifest/manifest.go b/cmd/podman/manifest/manifest.go index 2bdbec662..f992705c1 100644 --- a/cmd/podman/manifest/manifest.go +++ b/cmd/podman/manifest/manifest.go @@ -10,11 +10,10 @@ import ( var ( manifestDescription = "Creates, modifies, and pushes manifest lists and image indexes." manifestCmd = &cobra.Command{ - Use: "manifest", - Short: "Manipulate manifest lists and image indexes", - Long: manifestDescription, - TraverseChildren: true, - RunE: validate.SubCommandExists, + Use: "manifest", + Short: "Manipulate manifest lists and image indexes", + Long: manifestDescription, + RunE: validate.SubCommandExists, Example: `podman manifest add mylist:v1.11 image:v1.11-amd64 podman manifest create localhost/list podman manifest inspect localhost/list diff --git a/cmd/podman/manifest/push.go b/cmd/podman/manifest/push.go index 226dc716c..d1eb37ae5 100644 --- a/cmd/podman/manifest/push.go +++ b/cmd/podman/manifest/push.go @@ -49,6 +49,7 @@ func init() { flags.StringVar(&manifestPushOpts.SignBy, "sign-by", "", "sign the image using a GPG key with the specified `FINGERPRINT`") flags.BoolVar(&manifestPushOpts.TLSVerifyCLI, "tls-verify", true, "require HTTPS and verify certificates when accessing the registry") flags.BoolVarP(&manifestPushOpts.Quiet, "quiet", "q", false, "don't output progress information when pushing lists") + if registry.IsRemote() { _ = flags.MarkHidden("authfile") _ = flags.MarkHidden("cert-dir") diff --git a/cmd/podman/networks/network.go b/cmd/podman/networks/network.go index aa319f15e..953e4678c 100644 --- a/cmd/podman/networks/network.go +++ b/cmd/podman/networks/network.go @@ -10,11 +10,10 @@ import ( var ( // Command: podman _network_ networkCmd = &cobra.Command{ - Use: "network", - Short: "Manage networks", - Long: "Manage networks", - TraverseChildren: true, - RunE: validate.SubCommandExists, + Use: "network", + Short: "Manage networks", + Long: "Manage networks", + RunE: validate.SubCommandExists, } ) diff --git a/cmd/podman/parse/common.go b/cmd/podman/parse/common.go deleted file mode 100644 index b3aa88da2..000000000 --- a/cmd/podman/parse/common.go +++ /dev/null @@ -1,112 +0,0 @@ -package parse - -import ( - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -// TODO: the two functions here are almost identical. It may be worth looking -// into generalizing the two a bit more and share code but time is scarce and -// we only live once. - -// CheckAllLatestAndCIDFile checks that --all and --latest are used correctly. -// If cidfile is set, also check for the --cidfile flag. -func CheckAllLatestAndCIDFile(c *cobra.Command, args []string, ignoreArgLen bool, cidfile bool) error { - argLen := len(args) - if c.Flags().Lookup("all") == nil || c.Flags().Lookup("latest") == nil { - if !cidfile { - return errors.New("unable to lookup values for 'latest' or 'all'") - } else if c.Flags().Lookup("cidfile") == nil { - return errors.New("unable to lookup values for 'latest', 'all' or 'cidfile'") - } - } - - specifiedAll, _ := c.Flags().GetBool("all") - specifiedLatest, _ := c.Flags().GetBool("latest") - specifiedCIDFile := false - if cid, _ := c.Flags().GetStringArray("cidfile"); len(cid) > 0 { - specifiedCIDFile = true - } - - if specifiedCIDFile && (specifiedAll || specifiedLatest) { - return errors.Errorf("--all, --latest and --cidfile cannot be used together") - } else if specifiedAll && specifiedLatest { - return errors.Errorf("--all and --latest cannot be used together") - } - - if (argLen > 0) && specifiedAll { - return errors.Errorf("no arguments are needed with --all") - } - - if ignoreArgLen { - return nil - } - - if argLen > 0 { - if specifiedLatest { - return errors.Errorf("no arguments are needed with --latest") - } else if cidfile && (specifiedLatest || specifiedCIDFile) { - return errors.Errorf("no arguments are needed with --latest or --cidfile") - } - } - - if specifiedCIDFile { - return nil - } - - if argLen < 1 && !specifiedAll && !specifiedLatest && !specifiedCIDFile { - return errors.Errorf("you must provide at least one name or id") - } - return nil -} - -// CheckAllLatestAndPodIDFile checks that --all and --latest are used correctly. -// If withIDFile is set, also check for the --pod-id-file flag. -func CheckAllLatestAndPodIDFile(c *cobra.Command, args []string, ignoreArgLen bool, withIDFile bool) error { - argLen := len(args) - if c.Flags().Lookup("all") == nil || c.Flags().Lookup("latest") == nil { - if !withIDFile { - return errors.New("unable to lookup values for 'latest' or 'all'") - } else if c.Flags().Lookup("pod-id-file") == nil { - return errors.New("unable to lookup values for 'latest', 'all' or 'pod-id-file'") - } - } - - specifiedAll, _ := c.Flags().GetBool("all") - specifiedLatest, _ := c.Flags().GetBool("latest") - specifiedPodIDFile := false - if pid, _ := c.Flags().GetStringArray("pod-id-file"); len(pid) > 0 { - specifiedPodIDFile = true - } - - if specifiedPodIDFile && (specifiedAll || specifiedLatest) { - return errors.Errorf("--all, --latest and --pod-id-file cannot be used together") - } else if specifiedAll && specifiedLatest { - return errors.Errorf("--all and --latest cannot be used together") - } - - if (argLen > 0) && specifiedAll { - return errors.Errorf("no arguments are needed with --all") - } - - if ignoreArgLen { - return nil - } - - if argLen > 0 { - if specifiedLatest { - return errors.Errorf("no arguments are needed with --latest") - } else if withIDFile && (specifiedLatest || specifiedPodIDFile) { - return errors.Errorf("no arguments are needed with --latest or --pod-id-file") - } - } - - if specifiedPodIDFile { - return nil - } - - if argLen < 1 && !specifiedAll && !specifiedLatest && !specifiedPodIDFile { - return errors.Errorf("you must provide at least one name or id") - } - return nil -} diff --git a/cmd/podman/play/kube.go b/cmd/podman/play/kube.go index 3567295bf..9bd5c10db 100644 --- a/cmd/podman/play/kube.go +++ b/cmd/podman/play/kube.go @@ -61,7 +61,6 @@ func init() { flags.StringVar(&kubeOptions.SignaturePolicy, "signature-policy", "", "`Pathname` of signature policy file (not usually used)") flags.StringVar(&kubeOptions.SeccompProfileRoot, "seccomp-profile-root", defaultSeccompRoot, "Directory path for seccomp profiles") } - _ = flags.MarkHidden("signature-policy") } diff --git a/cmd/podman/play/play.go b/cmd/podman/play/play.go index f7018eafb..eb8873595 100644 --- a/cmd/podman/play/play.go +++ b/cmd/podman/play/play.go @@ -10,11 +10,10 @@ import ( var ( // Command: podman _play_ playCmd = &cobra.Command{ - Use: "play", - Short: "Play a pod and its containers from a structured file.", - Long: "Play structured data (e.g., Kubernetes pod or service yaml) based on containers and pods.", - TraverseChildren: true, - RunE: validate.SubCommandExists, + Use: "play", + Short: "Play a pod and its containers from a structured file.", + Long: "Play structured data (e.g., Kubernetes pod or service yaml) based on containers and pods.", + RunE: validate.SubCommandExists, } ) diff --git a/cmd/podman/pods/inspect.go b/cmd/podman/pods/inspect.go index 7d31385de..e21c7a74b 100644 --- a/cmd/podman/pods/inspect.go +++ b/cmd/podman/pods/inspect.go @@ -6,6 +6,7 @@ import ( "github.com/containers/buildah/pkg/formats" "github.com/containers/libpod/v2/cmd/podman/registry" + "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/pkg/domain/entities" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -36,11 +37,8 @@ func init() { Parent: podCmd, }) flags := inspectCmd.Flags() - flags.BoolVarP(&inspectOptions.Latest, "latest", "l", false, "Act on the latest pod podman is aware of") flags.StringVarP(&inspectOptions.Format, "format", "f", "json", "Format the output to a Go template or json") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } + validate.AddLatestFlag(inspectCmd, &inspectOptions.Latest) } func inspect(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/pods/kill.go b/cmd/podman/pods/kill.go index 2076d55e9..2f4930897 100644 --- a/cmd/podman/pods/kill.go +++ b/cmd/podman/pods/kill.go @@ -4,9 +4,9 @@ import ( "context" "fmt" - "github.com/containers/libpod/v2/cmd/podman/parse" "github.com/containers/libpod/v2/cmd/podman/registry" "github.com/containers/libpod/v2/cmd/podman/utils" + "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/pkg/domain/entities" "github.com/spf13/cobra" ) @@ -21,7 +21,7 @@ var ( Long: podKillDescription, RunE: kill, Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, false) + return validate.CheckAllLatestAndCIDFile(cmd, args, false, false) }, Example: `podman pod kill podID podman pod kill --signal TERM mywebserver @@ -41,14 +41,11 @@ func init() { }) flags := killCommand.Flags() flags.BoolVarP(&killOpts.All, "all", "a", false, "Kill all containers in all pods") - flags.BoolVarP(&killOpts.Latest, "latest", "l", false, "Act on the latest pod podman is aware of") flags.StringVarP(&killOpts.Signal, "signal", "s", "KILL", "Signal to send to the containers in the pod") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } - + validate.AddLatestFlag(killCommand, &killOpts.Latest) } -func kill(cmd *cobra.Command, args []string) error { + +func kill(_ *cobra.Command, args []string) error { var ( errs utils.OutputErrors ) diff --git a/cmd/podman/pods/pause.go b/cmd/podman/pods/pause.go index d495db601..f79d88973 100644 --- a/cmd/podman/pods/pause.go +++ b/cmd/podman/pods/pause.go @@ -4,9 +4,9 @@ import ( "context" "fmt" - "github.com/containers/libpod/v2/cmd/podman/parse" "github.com/containers/libpod/v2/cmd/podman/registry" "github.com/containers/libpod/v2/cmd/podman/utils" + "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/pkg/domain/entities" "github.com/spf13/cobra" ) @@ -21,7 +21,7 @@ var ( Long: podPauseDescription, RunE: pause, Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, false) + return validate.CheckAllLatestAndCIDFile(cmd, args, false, false) }, Example: `podman pod pause podID1 podID2 podman pod pause --latest @@ -41,12 +41,9 @@ func init() { }) flags := pauseCommand.Flags() flags.BoolVarP(&pauseOptions.All, "all", "a", false, "Pause all running pods") - flags.BoolVarP(&pauseOptions.Latest, "latest", "l", false, "Act on the latest pod podman is aware of") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } + validate.AddLatestFlag(pauseCommand, &pauseOptions.Latest) } -func pause(cmd *cobra.Command, args []string) error { +func pause(_ *cobra.Command, args []string) error { var ( errs utils.OutputErrors ) diff --git a/cmd/podman/pods/pod.go b/cmd/podman/pods/pod.go index 6eccade22..fff5ea615 100644 --- a/cmd/podman/pods/pod.go +++ b/cmd/podman/pods/pod.go @@ -14,11 +14,10 @@ var ( // Command: podman _pod_ podCmd = &cobra.Command{ - Use: "pod", - Short: "Manage pods", - Long: "Pods are a group of one or more containers sharing the same network, pid and ipc namespaces.", - TraverseChildren: true, - RunE: validate.SubCommandExists, + Use: "pod", + Short: "Manage pods", + Long: "Pods are a group of one or more containers sharing the same network, pid and ipc namespaces.", + RunE: validate.SubCommandExists, } containerConfig = util.DefaultContainerConfig() ) diff --git a/cmd/podman/pods/ps.go b/cmd/podman/pods/ps.go index 49407d39b..7a1221480 100644 --- a/cmd/podman/pods/ps.go +++ b/cmd/podman/pods/ps.go @@ -53,18 +53,15 @@ func init() { // TODO should we make this a [] ? flags.StringSliceVarP(&inputFilters, "filter", "f", []string{}, "Filter output based on conditions given") flags.StringVar(&psInput.Format, "format", "", "Pretty-print pods to JSON or using a Go template") - flags.BoolVarP(&psInput.Latest, "latest", "l", false, "Act on the latest pod podman is aware of") flags.BoolVar(&psInput.Namespace, "namespace", false, "Display namespace information of the pod") flags.BoolVar(&psInput.Namespace, "ns", false, "Display namespace information of the pod") flags.BoolVar(&noTrunc, "no-trunc", false, "Do not truncate pod and container IDs") flags.BoolVarP(&psInput.Quiet, "quiet", "q", false, "Print the numeric IDs of the pods only") flags.StringVar(&psInput.Sort, "sort", "created", "Sort output by created, id, name, or number") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } + validate.AddLatestFlag(psCmd, &psInput.Latest) } -func pods(cmd *cobra.Command, args []string) error { +func pods(cmd *cobra.Command, _ []string) error { var ( w io.Writer = os.Stdout row string diff --git a/cmd/podman/pods/restart.go b/cmd/podman/pods/restart.go index 7ca6b3cac..77d9f62d4 100644 --- a/cmd/podman/pods/restart.go +++ b/cmd/podman/pods/restart.go @@ -4,9 +4,9 @@ import ( "context" "fmt" - "github.com/containers/libpod/v2/cmd/podman/parse" "github.com/containers/libpod/v2/cmd/podman/registry" "github.com/containers/libpod/v2/cmd/podman/utils" + "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/pkg/domain/entities" "github.com/spf13/cobra" ) @@ -21,7 +21,7 @@ var ( Long: podRestartDescription, RunE: restart, Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, false) + return validate.CheckAllLatestAndCIDFile(cmd, args, false, false) }, Example: `podman pod restart podID1 podID2 podman pod restart --latest @@ -42,10 +42,7 @@ func init() { flags := restartCommand.Flags() flags.BoolVarP(&restartOptions.All, "all", "a", false, "Restart all running pods") - flags.BoolVarP(&restartOptions.Latest, "latest", "l", false, "Restart the latest pod podman is aware of") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } + validate.AddLatestFlag(restartCommand, &restartOptions.Latest) } func restart(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/pods/rm.go b/cmd/podman/pods/rm.go index 60972da76..3e07b31e9 100644 --- a/cmd/podman/pods/rm.go +++ b/cmd/podman/pods/rm.go @@ -5,9 +5,9 @@ import ( "fmt" "github.com/containers/libpod/v2/cmd/podman/common" - "github.com/containers/libpod/v2/cmd/podman/parse" "github.com/containers/libpod/v2/cmd/podman/registry" "github.com/containers/libpod/v2/cmd/podman/utils" + "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/pkg/domain/entities" "github.com/spf13/cobra" ) @@ -30,7 +30,7 @@ var ( Long: podRmDescription, RunE: rm, Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndPodIDFile(cmd, args, false, true) + return validate.CheckAllLatestAndPodIDFile(cmd, args, false, true) }, Example: `podman pod rm mywebserverpod podman pod rm -f 860a4b23 @@ -49,15 +49,15 @@ func init() { flags.BoolVarP(&rmOptions.All, "all", "a", false, "Remove all running pods") flags.BoolVarP(&rmOptions.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") flags.BoolVarP(&rmOptions.Ignore, "ignore", "i", false, "Ignore errors when a specified pod is missing") - flags.BoolVarP(&rmOptions.Latest, "latest", "l", false, "Remove the latest pod podman is aware of") flags.StringArrayVarP(&rmOptions.PodIDFiles, "pod-id-file", "", nil, "Read the pod ID from the file") + validate.AddLatestFlag(rmCommand, &rmOptions.Latest) + if registry.IsRemote() { - _ = flags.MarkHidden("latest") _ = flags.MarkHidden("ignore") } } -func rm(cmd *cobra.Command, args []string) error { +func rm(_ *cobra.Command, args []string) error { ids, err := common.ReadPodIDFiles(rmOptions.PodIDFiles) if err != nil { return err diff --git a/cmd/podman/pods/start.go b/cmd/podman/pods/start.go index db09f1bce..586737fb2 100644 --- a/cmd/podman/pods/start.go +++ b/cmd/podman/pods/start.go @@ -5,9 +5,9 @@ import ( "fmt" "github.com/containers/libpod/v2/cmd/podman/common" - "github.com/containers/libpod/v2/cmd/podman/parse" "github.com/containers/libpod/v2/cmd/podman/registry" "github.com/containers/libpod/v2/cmd/podman/utils" + "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/pkg/domain/entities" "github.com/spf13/cobra" ) @@ -29,7 +29,7 @@ var ( Long: podStartDescription, RunE: start, Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndPodIDFile(cmd, args, false, true) + return validate.CheckAllLatestAndPodIDFile(cmd, args, false, true) }, Example: `podman pod start podID podman pod start --latest @@ -50,11 +50,8 @@ func init() { flags := startCommand.Flags() flags.BoolVarP(&startOptions.All, "all", "a", false, "Restart all running pods") - flags.BoolVarP(&startOptions.Latest, "latest", "l", false, "Restart the latest pod podman is aware of") flags.StringArrayVarP(&startOptions.PodIDFiles, "pod-id-file", "", nil, "Read the pod ID from the file") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } + validate.AddLatestFlag(startCommand, &startOptions.Latest) } func start(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/pods/stats.go b/cmd/podman/pods/stats.go index 19ff750aa..930a6d15c 100644 --- a/cmd/podman/pods/stats.go +++ b/cmd/podman/pods/stats.go @@ -13,6 +13,7 @@ import ( "github.com/buger/goterm" "github.com/containers/buildah/pkg/formats" "github.com/containers/libpod/v2/cmd/podman/registry" + "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/pkg/domain/entities" "github.com/containers/libpod/v2/pkg/util/camelcase" "github.com/spf13/cobra" @@ -55,13 +56,9 @@ func init() { flags := statsCmd.Flags() flags.BoolVarP(&statsOptions.All, "all", "a", false, "Provide stats for all pods") flags.StringVar(&statsOptions.Format, "format", "", "Pretty-print container statistics to JSON or using a Go template") - flags.BoolVarP(&statsOptions.Latest, "latest", "l", false, "Provide stats on the latest pod Podman is aware of") flags.BoolVar(&statsOptions.NoReset, "no-reset", false, "Disable resetting the screen when streaming") flags.BoolVar(&statsOptions.NoStream, "no-stream", false, "Disable streaming stats and only pull the first result") - - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } + validate.AddLatestFlag(statsCmd, &statsOptions.Latest) } func stats(cmd *cobra.Command, args []string) error { diff --git a/cmd/podman/pods/stop.go b/cmd/podman/pods/stop.go index afe3b6eae..84190fd08 100644 --- a/cmd/podman/pods/stop.go +++ b/cmd/podman/pods/stop.go @@ -5,9 +5,9 @@ import ( "fmt" "github.com/containers/libpod/v2/cmd/podman/common" - "github.com/containers/libpod/v2/cmd/podman/parse" "github.com/containers/libpod/v2/cmd/podman/registry" "github.com/containers/libpod/v2/cmd/podman/utils" + "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/pkg/domain/entities" "github.com/spf13/cobra" ) @@ -34,7 +34,7 @@ var ( Long: podStopDescription, RunE: stop, Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndPodIDFile(cmd, args, false, true) + return validate.CheckAllLatestAndPodIDFile(cmd, args, false, true) }, Example: `podman pod stop mywebserverpod podman pod stop --latest @@ -51,13 +51,14 @@ func init() { flags := stopCommand.Flags() flags.BoolVarP(&stopOptions.All, "all", "a", false, "Stop all running pods") flags.BoolVarP(&stopOptions.Ignore, "ignore", "i", false, "Ignore errors when a specified pod is missing") - flags.BoolVarP(&stopOptions.Latest, "latest", "l", false, "Stop the latest pod podman is aware of") flags.UintVarP(&stopOptions.TimeoutCLI, "time", "t", containerConfig.Engine.StopTimeout, "Seconds to wait for pod stop before killing the container") flags.StringArrayVarP(&stopOptions.PodIDFiles, "pod-id-file", "", nil, "Read the pod ID from the file") + validate.AddLatestFlag(stopCommand, &stopOptions.Latest) + if registry.IsRemote() { - _ = flags.MarkHidden("latest") _ = flags.MarkHidden("ignore") } + flags.SetNormalizeFunc(utils.AliasFlags) } diff --git a/cmd/podman/pods/top.go b/cmd/podman/pods/top.go index 551eeccac..840d2da0a 100644 --- a/cmd/podman/pods/top.go +++ b/cmd/podman/pods/top.go @@ -8,6 +8,7 @@ import ( "text/tabwriter" "github.com/containers/libpod/v2/cmd/podman/registry" + "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/pkg/domain/entities" "github.com/containers/libpod/v2/pkg/util" "github.com/pkg/errors" @@ -50,15 +51,11 @@ func init() { flags := topCommand.Flags() flags.SetInterspersed(false) flags.BoolVar(&topOptions.ListDescriptors, "list-descriptors", false, "") - flags.BoolVarP(&topOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of") - _ = flags.MarkHidden("list-descriptors") // meant only for bash completion - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } + validate.AddLatestFlag(topCommand, &topOptions.Latest) } -func top(cmd *cobra.Command, args []string) error { +func top(_ *cobra.Command, args []string) error { if topOptions.ListDescriptors { descriptors, err := util.GetContainerPidInformationDescriptors() if err != nil { diff --git a/cmd/podman/pods/unpause.go b/cmd/podman/pods/unpause.go index 09f2e472d..f96f3481c 100644 --- a/cmd/podman/pods/unpause.go +++ b/cmd/podman/pods/unpause.go @@ -4,9 +4,9 @@ import ( "context" "fmt" - "github.com/containers/libpod/v2/cmd/podman/parse" "github.com/containers/libpod/v2/cmd/podman/registry" "github.com/containers/libpod/v2/cmd/podman/utils" + "github.com/containers/libpod/v2/cmd/podman/validate" "github.com/containers/libpod/v2/pkg/domain/entities" "github.com/spf13/cobra" ) @@ -21,7 +21,7 @@ var ( Long: podUnpauseDescription, RunE: unpause, Args: func(cmd *cobra.Command, args []string) error { - return parse.CheckAllLatestAndCIDFile(cmd, args, false, false) + return validate.CheckAllLatestAndCIDFile(cmd, args, false, false) }, Example: `podman pod unpause podID1 podID2 podman pod unpause --all @@ -41,12 +41,10 @@ func init() { }) flags := unpauseCommand.Flags() flags.BoolVarP(&unpauseOptions.All, "all", "a", false, "Pause all running pods") - flags.BoolVarP(&unpauseOptions.Latest, "latest", "l", false, "Act on the latest pod podman is aware of") - if registry.IsRemote() { - _ = flags.MarkHidden("latest") - } + validate.AddLatestFlag(unpauseCommand, &unpauseOptions.Latest) } -func unpause(cmd *cobra.Command, args []string) error { + +func unpause(_ *cobra.Command, args []string) error { var ( errs utils.OutputErrors ) diff --git a/cmd/podman/registry/config.go b/cmd/podman/registry/config.go index 85bf5f944..75e67b35d 100644 --- a/cmd/podman/registry/config.go +++ b/cmd/podman/registry/config.go @@ -5,7 +5,6 @@ import ( "os" "path/filepath" "runtime" - "strings" "sync" "github.com/containers/common/pkg/config" @@ -45,7 +44,7 @@ func newPodmanConfig() { case "linux": // Some linux clients might only be compiled without ABI // support (e.g., podman-remote). - if abiSupport { + if abiSupport && !remoteOverride { mode = entities.ABIMode } else { mode = entities.TunnelMode @@ -55,19 +54,6 @@ func newPodmanConfig() { os.Exit(1) } - // Check if need to fallback to the tunnel mode if --remote is used. - if abiSupport && mode == entities.ABIMode { - // cobra.Execute() may not be called yet, so we peek at os.Args. - for _, v := range os.Args { - // Prefix checking works because of how default EngineMode's - // have been defined. - if strings.HasPrefix(v, "--remote") { - mode = entities.TunnelMode - break - } - } - } - cfg, err := config.NewConfig("") if err != nil { fmt.Fprint(os.Stderr, "Failed to obtain podman configuration: "+err.Error()) diff --git a/cmd/podman/registry/remote.go b/cmd/podman/registry/remote.go index 3040c4c2a..006a1b900 100644 --- a/cmd/podman/registry/remote.go +++ b/cmd/podman/registry/remote.go @@ -1,9 +1,26 @@ package registry import ( + "os" + "sync" + "github.com/containers/libpod/v2/pkg/domain/entities" + "github.com/spf13/cobra" +) + +var ( + // Was --remote given on command line + remoteOverride bool + remoteSync sync.Once ) +// IsRemote returns true if podman was built to run remote +// Use in init() functions as a initialization check func IsRemote() bool { - return podmanOptions.EngineMode == entities.TunnelMode + remoteSync.Do(func() { + remote := &cobra.Command{} + remote.Flags().BoolVarP(&remoteOverride, "remote", "r", false, "") + _ = remote.ParseFlags(os.Args) + }) + return podmanOptions.EngineMode == entities.TunnelMode || remoteOverride } diff --git a/cmd/podman/root.go b/cmd/podman/root.go index 1ca358e71..7c54da91a 100644 --- a/cmd/podman/root.go +++ b/cmd/podman/root.go @@ -6,6 +6,7 @@ import ( "path" "runtime" "runtime/pprof" + "strconv" "strings" "github.com/containers/common/pkg/config" @@ -20,7 +21,6 @@ import ( "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/cobra" - "github.com/spf13/pflag" ) // HelpTemplate is the help template for podman commands @@ -79,7 +79,7 @@ func init() { syslogHook, ) - rootFlags(registry.PodmanConfig(), rootCmd.PersistentFlags()) + rootFlags(rootCmd, registry.PodmanConfig()) // "version" is a local flag to avoid collisions with sub-commands that use "-v" var dummyVersion bool @@ -111,6 +111,15 @@ func persistentPreRunE(cmd *cobra.Command, args []string) error { cfg := registry.PodmanConfig() + // Validate --remote and --latest not given on same command + latest := cmd.Flags().Lookup("latest") + if latest != nil { + value, _ := strconv.ParseBool(latest.Value.String()) + if cfg.Remote && value { + return errors.Errorf("For %s \"--remote\" and \"--latest\", are mutually exclusive flags", cmd.CommandPath()) + } + } + // Prep the engines if _, err := registry.NewImageEngine(cmd, args); err != nil { return err @@ -193,7 +202,7 @@ func loggingHook() { } } if !found { - fmt.Fprintf(os.Stderr, "Log Level \"%s\" is not supported, choose from: %s\n", logLevel, strings.Join(logLevels, ", ")) + fmt.Fprintf(os.Stderr, "Log Level %q is not supported, choose from: %s\n", logLevel, strings.Join(logLevels, ", ")) os.Exit(1) } @@ -209,44 +218,45 @@ func loggingHook() { } } -func rootFlags(opts *entities.PodmanConfig, flags *pflag.FlagSet) { - // V2 flags - flags.BoolVarP(&opts.Remote, "remote", "r", false, "Access remote Podman service (default false)") +func rootFlags(cmd *cobra.Command, opts *entities.PodmanConfig) { + cfg := opts.Config + lFlags := cmd.Flags() custom, _ := config.ReadCustomConfig() defaultURI := custom.Engine.RemoteURI if defaultURI == "" { defaultURI = registry.DefaultAPIAddress() } - flags.StringVar(&opts.URI, "url", defaultURI, "URL to access Podman service (CONTAINER_HOST)") - flags.StringVar(&opts.Identity, "identity", custom.Engine.RemoteIdentity, "path to SSH identity file, (CONTAINER_SSHKEY)") - - cfg := opts.Config - flags.StringVar(&cfg.Engine.CgroupManager, "cgroup-manager", cfg.Engine.CgroupManager, "Cgroup manager to use (\"cgroupfs\"|\"systemd\")") - flags.StringVar(&opts.CPUProfile, "cpu-profile", "", "Path for the cpu profiling results") - flags.StringVar(&opts.ConmonPath, "conmon", "", "Path of the conmon binary") - flags.StringVar(&cfg.Engine.NetworkCmdPath, "network-cmd-path", cfg.Engine.NetworkCmdPath, "Path to the command for configuring the network") - flags.StringVar(&cfg.Network.NetworkConfigDir, "cni-config-dir", cfg.Network.NetworkConfigDir, "Path of the configuration directory for CNI networks") - flags.StringVar(&cfg.Containers.DefaultMountsFile, "default-mounts-file", cfg.Containers.DefaultMountsFile, "Path to default mounts file") - flags.StringVar(&cfg.Engine.EventsLogger, "events-backend", cfg.Engine.EventsLogger, `Events backend to use ("file"|"journald"|"none")`) - flags.StringSliceVar(&cfg.Engine.HooksDir, "hooks-dir", cfg.Engine.HooksDir, "Set the OCI hooks directory path (may be set multiple times)") - flags.IntVar(&opts.MaxWorks, "max-workers", (runtime.NumCPU()*3)+1, "The maximum number of workers for parallel operations") - flags.StringVar(&cfg.Engine.Namespace, "namespace", cfg.Engine.Namespace, "Set the libpod namespace, used to create separate views of the containers and pods on the system") - flags.StringVar(&cfg.Engine.StaticDir, "root", "", "Path to the root directory in which data, including images, is stored") - flags.StringVar(&opts.RegistriesConf, "registries-conf", "", "Path to a registries.conf to use for image processing") - flags.StringVar(&opts.Runroot, "runroot", "", "Path to the 'run directory' where all state information is stored") - flags.StringVar(&opts.RuntimePath, "runtime", "", "Path to the OCI-compatible binary used to run containers, default is /usr/bin/runc") + lFlags.BoolVarP(&opts.Remote, "remote", "r", false, "Access remote Podman service (default false)") + lFlags.StringVar(&opts.URI, "url", defaultURI, "URL to access Podman service (CONTAINER_HOST)") + lFlags.StringVar(&opts.Identity, "identity", custom.Engine.RemoteIdentity, "path to SSH identity file, (CONTAINER_SSHKEY)") + + pFlags := cmd.PersistentFlags() + pFlags.StringVar(&cfg.Engine.CgroupManager, "cgroup-manager", cfg.Engine.CgroupManager, "Cgroup manager to use (\"cgroupfs\"|\"systemd\")") + pFlags.StringVar(&opts.CPUProfile, "cpu-profile", "", "Path for the cpu profiling results") + pFlags.StringVar(&opts.ConmonPath, "conmon", "", "Path of the conmon binary") + pFlags.StringVar(&cfg.Engine.NetworkCmdPath, "network-cmd-path", cfg.Engine.NetworkCmdPath, "Path to the command for configuring the network") + pFlags.StringVar(&cfg.Network.NetworkConfigDir, "cni-config-dir", cfg.Network.NetworkConfigDir, "Path of the configuration directory for CNI networks") + pFlags.StringVar(&cfg.Containers.DefaultMountsFile, "default-mounts-file", cfg.Containers.DefaultMountsFile, "Path to default mounts file") + pFlags.StringVar(&cfg.Engine.EventsLogger, "events-backend", cfg.Engine.EventsLogger, `Events backend to use ("file"|"journald"|"none")`) + pFlags.StringSliceVar(&cfg.Engine.HooksDir, "hooks-dir", cfg.Engine.HooksDir, "Set the OCI hooks directory path (may be set multiple times)") + pFlags.IntVar(&opts.MaxWorks, "max-workers", (runtime.NumCPU()*3)+1, "The maximum number of workers for parallel operations") + pFlags.StringVar(&cfg.Engine.Namespace, "namespace", cfg.Engine.Namespace, "Set the libpod namespace, used to create separate views of the containers and pods on the system") + pFlags.StringVar(&cfg.Engine.StaticDir, "root", "", "Path to the root directory in which data, including images, is stored") + pFlags.StringVar(&opts.RegistriesConf, "registries-conf", "", "Path to a registries.conf to use for image processing") + pFlags.StringVar(&opts.Runroot, "runroot", "", "Path to the 'run directory' where all state information is stored") + pFlags.StringVar(&opts.RuntimePath, "runtime", "", "Path to the OCI-compatible binary used to run containers, default is /usr/bin/runc") // -s is deprecated due to conflict with -s on subcommands - flags.StringVar(&opts.StorageDriver, "storage-driver", "", "Select which storage driver is used to manage storage of images and containers (default is overlay)") - flags.StringArrayVar(&opts.StorageOpts, "storage-opt", []string{}, "Used to pass an option to the storage driver") + pFlags.StringVar(&opts.StorageDriver, "storage-driver", "", "Select which storage driver is used to manage storage of images and containers (default is overlay)") + pFlags.StringArrayVar(&opts.StorageOpts, "storage-opt", []string{}, "Used to pass an option to the storage driver") - flags.StringVar(&opts.Engine.TmpDir, "tmpdir", "", "Path to the tmp directory for libpod state content.\n\nNote: use the environment variable 'TMPDIR' to change the temporary storage location for container images, '/var/tmp'.\n") - flags.BoolVar(&opts.Trace, "trace", false, "Enable opentracing output (default false)") + pFlags.StringVar(&opts.Engine.TmpDir, "tmpdir", "", "Path to the tmp directory for libpod state content.\n\nNote: use the environment variable 'TMPDIR' to change the temporary storage location for container images, '/var/tmp'.\n") + pFlags.BoolVar(&opts.Trace, "trace", false, "Enable opentracing output (default false)") // Override default --help information of `--help` global flag var dummyHelp bool - flags.BoolVar(&dummyHelp, "help", false, "Help for podman") - flags.StringVar(&logLevel, "log-level", logLevel, fmt.Sprintf("Log messages above specified level (%s)", strings.Join(logLevels, ", "))) + pFlags.BoolVar(&dummyHelp, "help", false, "Help for podman") + pFlags.StringVar(&logLevel, "log-level", logLevel, fmt.Sprintf("Log messages above specified level (%s)", strings.Join(logLevels, ", "))) // Hide these flags for both ABI and Tunneling for _, f := range []string{ @@ -256,13 +266,13 @@ func rootFlags(opts *entities.PodmanConfig, flags *pflag.FlagSet) { "registries-conf", "trace", } { - if err := flags.MarkHidden(f); err != nil { + if err := pFlags.MarkHidden(f); err != nil { logrus.Warnf("unable to mark %s flag as hidden: %s", f, err.Error()) } } // Only create these flags for ABI connections if !registry.IsRemote() { - flags.BoolVar(&useSyslog, "syslog", false, "Output logging information to syslog as well as the console (default false)") + pFlags.BoolVar(&useSyslog, "syslog", false, "Output logging information to syslog as well as the console (default false)") } } diff --git a/cmd/podman/system/connection.go b/cmd/podman/system/connection.go index cb22522aa..bdb113ea3 100644 --- a/cmd/podman/system/connection.go +++ b/cmd/podman/system/connection.go @@ -60,7 +60,6 @@ func init() { }) flags := connectionCmd.Flags() - flags.StringVar(&cOpts.Identity, "identity", "", "path to ssh identity file") flags.IntVarP(&cOpts.Port, "port", "p", 22, "port number for destination") flags.StringVar(&cOpts.UDSPath, "socket-path", "", "path to podman socket on remote host. (default '/run/podman/podman.sock' or '/run/user/{uid}/podman/podman.sock)") } diff --git a/cmd/podman/system/system.go b/cmd/podman/system/system.go index 6c4b26955..2dd6cf774 100644 --- a/cmd/podman/system/system.go +++ b/cmd/podman/system/system.go @@ -13,11 +13,10 @@ var ( // Command: podman _system_ systemCmd = &cobra.Command{ - Use: "system", - Short: "Manage podman", - Long: "Manage podman", - TraverseChildren: true, - RunE: validate.SubCommandExists, + Use: "system", + Short: "Manage podman", + Long: "Manage podman", + RunE: validate.SubCommandExists, } ) diff --git a/cmd/podman/validate/args.go b/cmd/podman/validate/args.go index 69240798f..a33f47959 100644 --- a/cmd/podman/validate/args.go +++ b/cmd/podman/validate/args.go @@ -2,6 +2,7 @@ package validate import ( "fmt" + "strconv" "github.com/pkg/errors" "github.com/spf13/cobra" @@ -25,8 +26,122 @@ func SubCommandExists(cmd *cobra.Command, args []string) error { // IDOrLatestArgs used to validate a nameOrId was provided or the "--latest" flag func IDOrLatestArgs(cmd *cobra.Command, args []string) error { - if len(args) > 1 || (len(args) == 0 && !cmd.Flag("latest").Changed) { - return fmt.Errorf("`%s` requires a name, id or the \"--latest\" flag", cmd.CommandPath()) + if len(args) > 1 { + return fmt.Errorf("`%s` accepts at most one argument", cmd.CommandPath()) + } + + latest := cmd.Flag("latest") + if latest != nil { + given, _ := strconv.ParseBool(cmd.Flag("latest").Value.String()) + if len(args) == 0 && !given { + return fmt.Errorf("%q requires a name, id, or the \"--latest\" flag", cmd.CommandPath()) + } + } + return nil +} + +// TODO: the two functions CheckAllLatestAndCIDFile and CheckAllLatestAndPodIDFile are almost identical. +// It may be worth looking into generalizing the two a bit more and share code but time is scarce and +// we only live once. + +// CheckAllLatestAndCIDFile checks that --all and --latest are used correctly. +// If cidfile is set, also check for the --cidfile flag. +func CheckAllLatestAndCIDFile(c *cobra.Command, args []string, ignoreArgLen bool, cidfile bool) error { + argLen := len(args) + if c.Flags().Lookup("all") == nil || c.Flags().Lookup("latest") == nil { + if !cidfile { + return errors.New("unable to lookup values for 'latest' or 'all'") + } else if c.Flags().Lookup("cidfile") == nil { + return errors.New("unable to lookup values for 'latest', 'all' or 'cidfile'") + } + } + + specifiedAll, _ := c.Flags().GetBool("all") + specifiedLatest, _ := c.Flags().GetBool("latest") + specifiedCIDFile := false + if cid, _ := c.Flags().GetStringArray("cidfile"); len(cid) > 0 { + specifiedCIDFile = true + } + + if specifiedCIDFile && (specifiedAll || specifiedLatest) { + return errors.Errorf("--all, --latest and --cidfile cannot be used together") + } else if specifiedAll && specifiedLatest { + return errors.Errorf("--all and --latest cannot be used together") + } + + if (argLen > 0) && specifiedAll { + return errors.Errorf("no arguments are needed with --all") + } + + if ignoreArgLen { + return nil + } + + if argLen > 0 { + if specifiedLatest { + return errors.Errorf("no arguments are needed with --latest") + } else if cidfile && (specifiedLatest || specifiedCIDFile) { + return errors.Errorf("no arguments are needed with --latest or --cidfile") + } + } + + if specifiedCIDFile { + return nil + } + + if argLen < 1 && !specifiedAll && !specifiedLatest && !specifiedCIDFile { + return errors.Errorf("you must provide at least one name or id") + } + return nil +} + +// CheckAllLatestAndPodIDFile checks that --all and --latest are used correctly. +// If withIDFile is set, also check for the --pod-id-file flag. +func CheckAllLatestAndPodIDFile(c *cobra.Command, args []string, ignoreArgLen bool, withIDFile bool) error { + argLen := len(args) + if c.Flags().Lookup("all") == nil || c.Flags().Lookup("latest") == nil { + if !withIDFile { + return errors.New("unable to lookup values for 'latest' or 'all'") + } else if c.Flags().Lookup("pod-id-file") == nil { + return errors.New("unable to lookup values for 'latest', 'all' or 'pod-id-file'") + } + } + + specifiedAll, _ := c.Flags().GetBool("all") + specifiedLatest, _ := c.Flags().GetBool("latest") + specifiedPodIDFile := false + if pid, _ := c.Flags().GetStringArray("pod-id-file"); len(pid) > 0 { + specifiedPodIDFile = true + } + + if specifiedPodIDFile && (specifiedAll || specifiedLatest) { + return errors.Errorf("--all, --latest and --pod-id-file cannot be used together") + } else if specifiedAll && specifiedLatest { + return errors.Errorf("--all and --latest cannot be used together") + } + + if (argLen > 0) && specifiedAll { + return errors.Errorf("no arguments are needed with --all") + } + + if ignoreArgLen { + return nil + } + + if argLen > 0 { + if specifiedLatest { + return errors.Errorf("no arguments are needed with --latest") + } else if withIDFile && (specifiedLatest || specifiedPodIDFile) { + return errors.Errorf("no arguments are needed with --latest or --pod-id-file") + } + } + + if specifiedPodIDFile { + return nil + } + + if argLen < 1 && !specifiedAll && !specifiedLatest && !specifiedPodIDFile { + return errors.Errorf("you must provide at least one name or id") } return nil } diff --git a/cmd/podman/validate/latest.go b/cmd/podman/validate/latest.go new file mode 100644 index 000000000..6e2aa063b --- /dev/null +++ b/cmd/podman/validate/latest.go @@ -0,0 +1,15 @@ +package validate + +import ( + "github.com/containers/libpod/cmd/podman/registry" + "github.com/spf13/cobra" +) + +func AddLatestFlag(cmd *cobra.Command, b *bool) { + // Initialization flag verification + cmd.Flags().BoolVarP(b, "latest", "l", false, + "Act on the latest container podman is aware of\nNot supported with the \"--remote\" flag") + if registry.IsRemote() { + _ = cmd.Flags().MarkHidden("latest") + } +} diff --git a/cmd/podman/volumes/volume.go b/cmd/podman/volumes/volume.go index 4514be88a..3ef20a027 100644 --- a/cmd/podman/volumes/volume.go +++ b/cmd/podman/volumes/volume.go @@ -13,11 +13,10 @@ var ( // Command: podman _volume_ volumeCmd = &cobra.Command{ - Use: "volume", - Short: "Manage volumes", - Long: "Volumes are created in and can be shared between containers", - TraverseChildren: true, - RunE: validate.SubCommandExists, + Use: "volume", + Short: "Manage volumes", + Long: "Volumes are created in and can be shared between containers", + RunE: validate.SubCommandExists, } ) -- cgit v1.2.3-54-g00ecf From 2fb9bb20df49f665dbc7420a80dc2da57530278f Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Mon, 6 Jul 2020 14:44:40 -0400 Subject: Fix imports to ensure v2 is used with libpod Signed-off-by: Matthew Heon --- cmd/podman/validate/latest.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'cmd') diff --git a/cmd/podman/validate/latest.go b/cmd/podman/validate/latest.go index 6e2aa063b..0ebed7227 100644 --- a/cmd/podman/validate/latest.go +++ b/cmd/podman/validate/latest.go @@ -1,7 +1,7 @@ package validate import ( - "github.com/containers/libpod/cmd/podman/registry" + "github.com/containers/libpod/v2/cmd/podman/registry" "github.com/spf13/cobra" ) -- cgit v1.2.3-54-g00ecf