diff options
Diffstat (limited to 'cmd')
-rw-r--r-- | cmd/podman/common/completion.go | 2 | ||||
-rw-r--r-- | cmd/podman/generate/systemd.go | 16 | ||||
-rw-r--r-- | cmd/podman/healthcheck/run.go | 5 | ||||
-rw-r--r-- | cmd/podman/inspect/inspect.go | 4 | ||||
-rw-r--r-- | cmd/podman/machine/init.go | 6 | ||||
-rw-r--r-- | cmd/podman/machine/list.go | 2 | ||||
-rw-r--r-- | cmd/podman/machine/machine.go | 2 | ||||
-rw-r--r-- | cmd/podman/machine/rm.go | 2 | ||||
-rw-r--r-- | cmd/podman/machine/ssh.go | 2 | ||||
-rw-r--r-- | cmd/podman/machine/start.go | 10 | ||||
-rw-r--r-- | cmd/podman/machine/stop.go | 2 | ||||
-rw-r--r-- | cmd/podman/networks/create.go | 9 | ||||
-rw-r--r-- | cmd/podman/pods/inspect.go | 4 | ||||
-rw-r--r-- | cmd/podman/pods/logs.go | 140 | ||||
-rw-r--r-- | cmd/podman/secrets/list.go | 2 | ||||
-rw-r--r-- | cmd/podman/system/unshare.go | 21 |
16 files changed, 207 insertions, 22 deletions
diff --git a/cmd/podman/common/completion.go b/cmd/podman/common/completion.go index 3966606e3..e925fb4f1 100644 --- a/cmd/podman/common/completion.go +++ b/cmd/podman/common/completion.go @@ -223,7 +223,7 @@ func getSecrets(cmd *cobra.Command, toComplete string) ([]string, cobra.ShellCom cobra.CompErrorln(err.Error()) return nil, cobra.ShellCompDirectiveNoFileComp } - secrets, err := engine.SecretList(registry.GetContext()) + secrets, err := engine.SecretList(registry.GetContext(), entities.SecretListRequest{}) if err != nil { cobra.CompErrorln(err.Error()) return nil, cobra.ShellCompDirectiveNoFileComp diff --git a/cmd/podman/generate/systemd.go b/cmd/podman/generate/systemd.go index b76a71f0d..2ab33c26b 100644 --- a/cmd/podman/generate/systemd.go +++ b/cmd/podman/generate/systemd.go @@ -12,15 +12,22 @@ import ( "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/cmd/podman/utils" "github.com/containers/podman/v3/pkg/domain/entities" + systemDefine "github.com/containers/podman/v3/pkg/systemd/define" "github.com/pkg/errors" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) +const ( + restartPolicyFlagName = "restart-policy" + timeFlagName = "time" +) + var ( files bool format string systemdTimeout uint + systemdRestart string systemdOptions = entities.GenerateSystemdOptions{} systemdDescription = `Generate systemd units for a pod or container. The generated units can later be controlled via systemctl(1).` @@ -47,7 +54,6 @@ func init() { flags.BoolVarP(&systemdOptions.Name, "name", "n", false, "Use container/pod names instead of IDs") flags.BoolVarP(&files, "files", "f", false, "Generate .service files instead of printing to stdout") - timeFlagName := "time" flags.UintVarP(&systemdTimeout, timeFlagName, "t", containerConfig.Engine.StopTimeout, "Stop timeout override") _ = systemdCmd.RegisterFlagCompletionFunc(timeFlagName, completion.AutocompleteNone) flags.BoolVarP(&systemdOptions.New, "new", "", false, "Create a new container or pod instead of starting an existing one") @@ -65,8 +71,7 @@ func init() { flags.StringVar(&systemdOptions.Separator, separatorFlagName, "-", "Systemd unit name separator between name/id and prefix") _ = systemdCmd.RegisterFlagCompletionFunc(separatorFlagName, completion.AutocompleteNone) - restartPolicyFlagName := "restart-policy" - flags.StringVar(&systemdOptions.RestartPolicy, restartPolicyFlagName, "on-failure", "Systemd restart-policy") + flags.StringVar(&systemdRestart, restartPolicyFlagName, systemDefine.DefaultRestartPolicy, "Systemd restart-policy") _ = systemdCmd.RegisterFlagCompletionFunc(restartPolicyFlagName, common.AutocompleteSystemdRestartOptions) formatFlagName := "format" @@ -77,9 +82,12 @@ func init() { } func systemd(cmd *cobra.Command, args []string) error { - if cmd.Flags().Changed("time") { + if cmd.Flags().Changed(timeFlagName) { systemdOptions.StopTimeout = &systemdTimeout } + if cmd.Flags().Changed(restartPolicyFlagName) { + systemdOptions.RestartPolicy = &systemdRestart + } if registry.IsRemote() { logrus.Warnln("The generated units should be placed on your remote system") diff --git a/cmd/podman/healthcheck/run.go b/cmd/podman/healthcheck/run.go index fe8dc2573..b03a07bc4 100644 --- a/cmd/podman/healthcheck/run.go +++ b/cmd/podman/healthcheck/run.go @@ -6,6 +6,7 @@ import ( "github.com/containers/podman/v3/cmd/podman/common" "github.com/containers/podman/v3/cmd/podman/registry" + "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/pkg/domain/entities" "github.com/spf13/cobra" ) @@ -34,9 +35,9 @@ func run(cmd *cobra.Command, args []string) error { if err != nil { return err } - if response.Status == "unhealthy" { + if response.Status == define.HealthCheckUnhealthy { registry.SetExitCode(1) + fmt.Println(response.Status) } - fmt.Println(response.Status) return err } diff --git a/cmd/podman/inspect/inspect.go b/cmd/podman/inspect/inspect.go index bd3060882..4c7fa33a4 100644 --- a/cmd/podman/inspect/inspect.go +++ b/cmd/podman/inspect/inspect.go @@ -254,7 +254,9 @@ func printTmpl(typ, row string, data []interface{}) error { if err != nil { return err } - return t.Execute(w, data) + err = t.Execute(w, data) + w.Flush() + return err } func (i *inspector) inspectAll(ctx context.Context, namesOrIDs []string) ([]interface{}, []error, error) { diff --git a/cmd/podman/machine/init.go b/cmd/podman/machine/init.go index ac0d06a07..ec44a707d 100644 --- a/cmd/podman/machine/init.go +++ b/cmd/podman/machine/init.go @@ -1,4 +1,4 @@ -// +build amd64,linux arm64,linux amd64,darwin arm64,darwin +// +build amd64,!windows arm64,!windows package machine @@ -40,7 +40,7 @@ func init() { flags.Uint64Var( &initOpts.CPUS, cpusFlagName, 1, - "Number of CPUs. The default is 1.", + "Number of CPUs", ) _ = initCmd.RegisterFlagCompletionFunc(cpusFlagName, completion.AutocompleteNone) @@ -57,7 +57,7 @@ func init() { flags.Uint64VarP( &initOpts.Memory, memoryFlagName, "m", 2048, - "Memory (in MB)", + "Memory in MB", ) _ = initCmd.RegisterFlagCompletionFunc(memoryFlagName, completion.AutocompleteNone) diff --git a/cmd/podman/machine/list.go b/cmd/podman/machine/list.go index 134a081ab..d4360bb9b 100644 --- a/cmd/podman/machine/list.go +++ b/cmd/podman/machine/list.go @@ -1,4 +1,4 @@ -// +build amd64,linux arm64,linux amd64,darwin arm64,darwin +// +build amd64,!windows arm64,!windows package machine diff --git a/cmd/podman/machine/machine.go b/cmd/podman/machine/machine.go index b059afc38..8ff9055f0 100644 --- a/cmd/podman/machine/machine.go +++ b/cmd/podman/machine/machine.go @@ -1,4 +1,4 @@ -// +build amd64,linux arm64,linux amd64,darwin arm64,darwin +// +build amd64,!windows arm64,!windows package machine diff --git a/cmd/podman/machine/rm.go b/cmd/podman/machine/rm.go index 02e3dfeb8..c17399c78 100644 --- a/cmd/podman/machine/rm.go +++ b/cmd/podman/machine/rm.go @@ -1,4 +1,4 @@ -// +build amd64,linux arm64,linux amd64,darwin arm64,darwin +// +build amd64,!windows arm64,!windows package machine diff --git a/cmd/podman/machine/ssh.go b/cmd/podman/machine/ssh.go index f185948f5..84e9e88ab 100644 --- a/cmd/podman/machine/ssh.go +++ b/cmd/podman/machine/ssh.go @@ -1,4 +1,4 @@ -// +build amd64,linux arm64,linux amd64,darwin arm64,darwin +// +build amd64,!windows arm64,!windows package machine diff --git a/cmd/podman/machine/start.go b/cmd/podman/machine/start.go index f8f0eed09..4ae31e6de 100644 --- a/cmd/podman/machine/start.go +++ b/cmd/podman/machine/start.go @@ -1,8 +1,10 @@ -// +build amd64,linux arm64,linux amd64,darwin arm64,darwin +// +build amd64,!windows arm64,!windows package machine import ( + "fmt" + "github.com/containers/podman/v3/cmd/podman/registry" "github.com/containers/podman/v3/pkg/machine" "github.com/containers/podman/v3/pkg/machine/qemu" @@ -58,5 +60,9 @@ func start(cmd *cobra.Command, args []string) error { if err != nil { return err } - return vm.Start(vmName, machine.StartOptions{}) + if err := vm.Start(vmName, machine.StartOptions{}); err != nil { + return err + } + fmt.Printf("Machine %q started successfully\n", vmName) + return nil } diff --git a/cmd/podman/machine/stop.go b/cmd/podman/machine/stop.go index 2d5aa7b95..76ba85601 100644 --- a/cmd/podman/machine/stop.go +++ b/cmd/podman/machine/stop.go @@ -1,4 +1,4 @@ -// +build amd64,linux arm64,linux amd64,darwin arm64,darwin +// +build amd64,!windows arm64,!windows package machine diff --git a/cmd/podman/networks/create.go b/cmd/podman/networks/create.go index 1f3b321ba..b5ddd215f 100644 --- a/cmd/podman/networks/create.go +++ b/cmd/podman/networks/create.go @@ -11,6 +11,7 @@ import ( "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/pkg/domain/entities" "github.com/pkg/errors" + "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -56,7 +57,8 @@ func networkCreateFlags(cmd *cobra.Command) { macvlanFlagName := "macvlan" flags.StringVar(&networkCreateOptions.MacVLAN, macvlanFlagName, "", "create a Macvlan connection based on this device") - _ = cmd.RegisterFlagCompletionFunc(macvlanFlagName, completion.AutocompleteNone) + // This option is deprecated + flags.MarkHidden(macvlanFlagName) labelFlagName := "label" flags.StringArrayVar(&labels, labelFlagName, nil, "set metadata on a network") @@ -100,6 +102,11 @@ func networkCreate(cmd *cobra.Command, args []string) error { if err != nil { return errors.Wrapf(err, "unable to process options") } + + if networkCreateOptions.MacVLAN != "" { + logrus.Warn("The --macvlan option is deprecated, use `--driver macvlan --opt parent=<device>` instead") + } + response, err := registry.ContainerEngine().NetworkCreate(registry.Context(), name, networkCreateOptions) if err != nil { return err diff --git a/cmd/podman/pods/inspect.go b/cmd/podman/pods/inspect.go index 4bb88f48a..96eaec3b9 100644 --- a/cmd/podman/pods/inspect.go +++ b/cmd/podman/pods/inspect.go @@ -80,5 +80,7 @@ func inspect(cmd *cobra.Command, args []string) error { if err != nil { return err } - return t.Execute(w, *responses) + err = t.Execute(w, *responses) + w.Flush() + return err } diff --git a/cmd/podman/pods/logs.go b/cmd/podman/pods/logs.go new file mode 100644 index 000000000..fe5205669 --- /dev/null +++ b/cmd/podman/pods/logs.go @@ -0,0 +1,140 @@ +package pods + +import ( + "os" + + "github.com/containers/common/pkg/completion" + "github.com/containers/podman/v3/cmd/podman/common" + "github.com/containers/podman/v3/cmd/podman/registry" + "github.com/containers/podman/v3/cmd/podman/validate" + "github.com/containers/podman/v3/libpod/define" + "github.com/containers/podman/v3/pkg/domain/entities" + "github.com/containers/podman/v3/pkg/util" + "github.com/pkg/errors" + "github.com/spf13/cobra" +) + +// logsOptionsWrapper wraps entities.LogsOptions and prevents leaking +// CLI-only fields into the API types. +type logsOptionsWrapper struct { + entities.PodLogsOptions + + SinceRaw string + + UntilRaw string +} + +var ( + logsPodOptions logsOptionsWrapper + logsPodDescription = `Displays logs for pod with one or more containers.` + logsPodCommand = &cobra.Command{ + Use: "logs [options] POD", + Short: "Fetch logs for pod with one or more containers", + Long: logsPodDescription, + // We dont want users to invoke latest and pod togather + Args: func(cmd *cobra.Command, args []string) error { + switch { + case registry.IsRemote() && logsPodOptions.Latest: + return errors.New(cmd.Name() + " does not support 'latest' when run remotely") + case len(args) > 1: + return errors.New("requires exactly 1 arg") + case logsPodOptions.Latest && len(args) > 0: + return errors.New("--latest and pods cannot be used together") + case !logsPodOptions.Latest && len(args) < 1: + return errors.New("specify at least one pod name or ID to log") + } + return nil + }, + RunE: logs, + ValidArgsFunction: common.AutocompletePods, + Example: `podman pod logs podID + podman pod logs -c ctrname podName + podman pod logs --tail 2 mywebserver + podman pod logs --follow=true --since 10m podID + podman pod logs mywebserver`, + } + + containerLogsCommand = &cobra.Command{ + Use: logsPodCommand.Use, + Short: logsPodCommand.Short, + Long: logsPodCommand.Long, + Args: logsPodCommand.Args, + RunE: logsPodCommand.RunE, + ValidArgsFunction: logsPodCommand.ValidArgsFunction, + Example: `podman pod logs podId + podman pod logs -c ctrname podName + podman pod logs --tail 2 mywebserver + podman pod logs --follow=true --since 10m podID`, + } +) + +func init() { + registry.Commands = append(registry.Commands, registry.CliCommand{ + Command: logsPodCommand, + }) + logsFlags(logsPodCommand) + validate.AddLatestFlag(logsPodCommand, &logsPodOptions.Latest) + + // container logs + registry.Commands = append(registry.Commands, registry.CliCommand{ + Command: containerLogsCommand, + Parent: podCmd, + }) + logsFlags(containerLogsCommand) + validate.AddLatestFlag(containerLogsCommand, &logsPodOptions.Latest) +} + +func logsFlags(cmd *cobra.Command) { + flags := cmd.Flags() + + flags.BoolVar(&logsPodOptions.Details, "details", false, "Show extra details provided to the logs") + flags.BoolVarP(&logsPodOptions.Follow, "follow", "f", false, "Follow log output.") + + containerNameFlag := "container" + flags.StringVarP(&logsPodOptions.ContainerName, containerNameFlag, "c", "", "Filter logs by container name or id which belongs to pod") + _ = cmd.RegisterFlagCompletionFunc(containerNameFlag, common.AutocompleteContainers) + + sinceFlagName := "since" + flags.StringVar(&logsPodOptions.SinceRaw, sinceFlagName, "", "Show logs since TIMESTAMP") + _ = cmd.RegisterFlagCompletionFunc(sinceFlagName, completion.AutocompleteNone) + + untilFlagName := "until" + flags.StringVar(&logsPodOptions.UntilRaw, untilFlagName, "", "Show logs until TIMESTAMP") + _ = cmd.RegisterFlagCompletionFunc(untilFlagName, completion.AutocompleteNone) + + tailFlagName := "tail" + flags.Int64Var(&logsPodOptions.Tail, tailFlagName, -1, "Output the specified number of LINES at the end of the logs.") + _ = cmd.RegisterFlagCompletionFunc(tailFlagName, completion.AutocompleteNone) + + flags.BoolVarP(&logsPodOptions.Timestamps, "timestamps", "t", false, "Output the timestamps in the log") + flags.SetInterspersed(false) + _ = flags.MarkHidden("details") +} + +func logs(_ *cobra.Command, args []string) error { + if logsPodOptions.SinceRaw != "" { + // parse time, error out if something is wrong + since, err := util.ParseInputTime(logsPodOptions.SinceRaw, true) + if err != nil { + return errors.Wrapf(err, "error parsing --since %q", logsPodOptions.SinceRaw) + } + logsPodOptions.Since = since + } + if logsPodOptions.UntilRaw != "" { + // parse time, error out if something is wrong + until, err := util.ParseInputTime(logsPodOptions.UntilRaw, false) + if err != nil { + return errors.Wrapf(err, "error parsing --until %q", logsPodOptions.UntilRaw) + } + logsPodOptions.Until = until + } + + // Remote can only process one container at a time + if registry.IsRemote() && logsPodOptions.ContainerName == "" { + return errors.Wrapf(define.ErrInvalidArg, "-c or --container cannot be empty") + } + + logsPodOptions.StdoutWriter = os.Stdout + logsPodOptions.StderrWriter = os.Stderr + return registry.ContainerEngine().PodLogs(registry.GetContext(), args[0], logsPodOptions.PodLogsOptions) +} diff --git a/cmd/podman/secrets/list.go b/cmd/podman/secrets/list.go index e64990c6f..f136de4ab 100644 --- a/cmd/podman/secrets/list.go +++ b/cmd/podman/secrets/list.go @@ -48,7 +48,7 @@ func init() { } func ls(cmd *cobra.Command, args []string) error { - responses, err := registry.ContainerEngine().SecretList(context.Background()) + responses, err := registry.ContainerEngine().SecretList(context.Background(), entities.SecretListRequest{}) if err != nil { return err } diff --git a/cmd/podman/system/unshare.go b/cmd/podman/system/unshare.go index f930d8b62..50230609e 100644 --- a/cmd/podman/system/unshare.go +++ b/cmd/podman/system/unshare.go @@ -2,6 +2,7 @@ package system import ( "os" + "os/exec" "github.com/containers/common/pkg/completion" "github.com/containers/podman/v3/cmd/podman/registry" @@ -50,5 +51,23 @@ func unshare(cmd *cobra.Command, args []string) error { args = []string{shell} } - return registry.ContainerEngine().Unshare(registry.Context(), args, unshareOptions) + err := registry.ContainerEngine().Unshare(registry.Context(), args, unshareOptions) + if err != nil { + if exitError, ok := err.(*exec.ExitError); ok { + // the user command inside the unshare env has failed + // we set the exit code, do not return the error to the user + // otherwise "exit status X" will be printed + registry.SetExitCode(exitError.ExitCode()) + return nil + } + // cmd.Run() can return fs.ErrNotExist, fs.ErrPermission or exec.ErrNotFound + // follow podman run/exec standard with the exit codes + if errors.Is(err, os.ErrNotExist) || errors.Is(err, exec.ErrNotFound) { + registry.SetExitCode(127) + } else if errors.Is(err, os.ErrPermission) { + registry.SetExitCode(126) + } + return err + } + return nil } |