From 9b152ef20e9cadf61547897ae21071098256bf79 Mon Sep 17 00:00:00 2001 From: Toshiki Sonoda Date: Wed, 20 Jul 2022 19:30:11 +0900 Subject: Add pause/unpause --latest, --cidfile, --filter --latest : pause/unpause the latest container. --filter : pause/unpause the filtered container. --cidfile : Read container ID from the specified file and pause/unpause the container. Signed-off-by: Toshiki Sonoda --- cmd/podman/containers/pause.go | 83 ++++++++++++++++++++++++++++---------- cmd/podman/containers/unpause.go | 86 ++++++++++++++++++++++++++++++---------- 2 files changed, 127 insertions(+), 42 deletions(-) (limited to 'cmd/podman') diff --git a/cmd/podman/containers/pause.go b/cmd/podman/containers/pause.go index af6f740f2..53aa423ac 100644 --- a/cmd/podman/containers/pause.go +++ b/cmd/podman/containers/pause.go @@ -2,61 +2,88 @@ package containers import ( "context" - "errors" "fmt" + "io/ioutil" + "strings" + "github.com/containers/common/pkg/completion" "github.com/containers/podman/v4/cmd/podman/common" "github.com/containers/podman/v4/cmd/podman/registry" "github.com/containers/podman/v4/cmd/podman/utils" + "github.com/containers/podman/v4/cmd/podman/validate" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/spf13/cobra" - "github.com/spf13/pflag" ) var ( pauseDescription = `Pauses one or more running containers. The container name or ID can be used.` pauseCommand = &cobra.Command{ - Use: "pause [options] CONTAINER [CONTAINER...]", - Short: "Pause all the processes in one or more containers", - Long: pauseDescription, - RunE: pause, + Use: "pause [options] CONTAINER [CONTAINER...]", + Short: "Pause all the processes in one or more containers", + Long: pauseDescription, + RunE: pause, + Args: func(cmd *cobra.Command, args []string) error { + return validate.CheckAllLatestAndIDFile(cmd, args, false, "cidfile") + }, ValidArgsFunction: common.AutocompleteContainersRunning, Example: `podman pause mywebserver podman pause 860a4b23 - podman pause -a`, + podman pause --all`, } containerPauseCommand = &cobra.Command{ - Use: pauseCommand.Use, - Short: pauseCommand.Short, - Long: pauseCommand.Long, - RunE: pauseCommand.RunE, + Use: pauseCommand.Use, + Short: pauseCommand.Short, + Long: pauseCommand.Long, + RunE: pauseCommand.RunE, + Args: func(cmd *cobra.Command, args []string) error { + return validate.CheckAllLatestAndIDFile(cmd, args, false, "cidfile") + }, ValidArgsFunction: pauseCommand.ValidArgsFunction, Example: `podman container pause mywebserver podman container pause 860a4b23 - podman container pause -a`, + podman container pause --all`, } +) - pauseOpts = entities.PauseUnPauseOptions{} +var ( + pauseOpts = entities.PauseUnPauseOptions{ + Filters: make(map[string][]string), + } + pauseCidFiles = []string{} ) -func pauseFlags(flags *pflag.FlagSet) { +func pauseFlags(cmd *cobra.Command) { + flags := cmd.Flags() + flags.BoolVarP(&pauseOpts.All, "all", "a", false, "Pause all running containers") + + cidfileFlagName := "cidfile" + flags.StringArrayVar(&pauseCidFiles, cidfileFlagName, nil, "Read the container ID from the file") + _ = cmd.RegisterFlagCompletionFunc(cidfileFlagName, completion.AutocompleteDefault) + + filterFlagName := "filter" + flags.StringSliceVarP(&filters, filterFlagName, "f", []string{}, "Filter output based on conditions given") + _ = cmd.RegisterFlagCompletionFunc(filterFlagName, common.AutocompletePsFilters) + + if registry.IsRemote() { + _ = flags.MarkHidden("cidfile") + } } func init() { registry.Commands = append(registry.Commands, registry.CliCommand{ Command: pauseCommand, }) - flags := pauseCommand.Flags() - pauseFlags(flags) + pauseFlags(pauseCommand) + validate.AddLatestFlag(pauseCommand, &pauseOpts.Latest) registry.Commands = append(registry.Commands, registry.CliCommand{ Command: containerPauseCommand, Parent: containerCmd, }) - containerPauseFlags := containerPauseCommand.Flags() - pauseFlags(containerPauseFlags) + pauseFlags(containerPauseCommand) + validate.AddLatestFlag(containerPauseCommand, &pauseOpts.Latest) } func pause(cmd *cobra.Command, args []string) error { @@ -64,16 +91,30 @@ func pause(cmd *cobra.Command, args []string) error { errs utils.OutputErrors ) - if len(args) < 1 && !pauseOpts.All { - return errors.New("you must provide at least one container name or id") + for _, cidFile := range pauseCidFiles { + content, err := ioutil.ReadFile(cidFile) + if err != nil { + return fmt.Errorf("error reading CIDFile: %w", err) + } + id := strings.Split(string(content), "\n")[0] + args = append(args, id) + } + + for _, f := range filters { + split := strings.SplitN(f, "=", 2) + if len(split) < 2 { + return fmt.Errorf("invalid filter %q", f) + } + pauseOpts.Filters[split[0]] = append(pauseOpts.Filters[split[0]], split[1]) } + responses, err := registry.ContainerEngine().ContainerPause(context.Background(), args, pauseOpts) if err != nil { return err } for _, r := range responses { if r.Err == nil { - fmt.Println(r.Id) + fmt.Println(r.RawInput) } else { errs = append(errs, r.Err) } diff --git a/cmd/podman/containers/unpause.go b/cmd/podman/containers/unpause.go index a5375e737..4282e490e 100644 --- a/cmd/podman/containers/unpause.go +++ b/cmd/podman/containers/unpause.go @@ -4,59 +4,87 @@ import ( "context" "errors" "fmt" + "io/ioutil" + "strings" "github.com/containers/common/pkg/cgroups" + "github.com/containers/common/pkg/completion" "github.com/containers/podman/v4/cmd/podman/common" "github.com/containers/podman/v4/cmd/podman/registry" "github.com/containers/podman/v4/cmd/podman/utils" + "github.com/containers/podman/v4/cmd/podman/validate" "github.com/containers/podman/v4/pkg/domain/entities" "github.com/containers/podman/v4/pkg/rootless" "github.com/spf13/cobra" - "github.com/spf13/pflag" ) var ( unpauseDescription = `Unpauses one or more previously paused containers. The container name or ID can be used.` unpauseCommand = &cobra.Command{ - Use: "unpause [options] CONTAINER [CONTAINER...]", - Short: "Unpause the processes in one or more containers", - Long: unpauseDescription, - RunE: unpause, + Use: "unpause [options] CONTAINER [CONTAINER...]", + Short: "Unpause the processes in one or more containers", + Long: unpauseDescription, + RunE: unpause, + Args: func(cmd *cobra.Command, args []string) error { + return validate.CheckAllLatestAndIDFile(cmd, args, false, "cidfile") + }, ValidArgsFunction: common.AutocompleteContainersPaused, Example: `podman unpause ctrID podman unpause --all`, } - unPauseOptions = entities.PauseUnPauseOptions{} containerUnpauseCommand = &cobra.Command{ - Use: unpauseCommand.Use, - Short: unpauseCommand.Short, - Long: unpauseCommand.Long, - RunE: unpauseCommand.RunE, + Use: unpauseCommand.Use, + Short: unpauseCommand.Short, + Long: unpauseCommand.Long, + RunE: unpauseCommand.RunE, + Args: func(cmd *cobra.Command, args []string) error { + return validate.CheckAllLatestAndIDFile(cmd, args, false, "cidfile") + }, ValidArgsFunction: unpauseCommand.ValidArgsFunction, Example: `podman container unpause ctrID podman container unpause --all`, } ) -func unpauseFlags(flags *pflag.FlagSet) { - flags.BoolVarP(&unPauseOptions.All, "all", "a", false, "Pause all running containers") +var ( + unpauseOpts = entities.PauseUnPauseOptions{ + Filters: make(map[string][]string), + } + unpauseCidFiles = []string{} +) + +func unpauseFlags(cmd *cobra.Command) { + flags := cmd.Flags() + + flags.BoolVarP(&unpauseOpts.All, "all", "a", false, "Unpause all paused containers") + + cidfileFlagName := "cidfile" + flags.StringArrayVar(&unpauseCidFiles, cidfileFlagName, nil, "Read the container ID from the file") + _ = cmd.RegisterFlagCompletionFunc(cidfileFlagName, completion.AutocompleteDefault) + + filterFlagName := "filter" + flags.StringSliceVarP(&filters, filterFlagName, "f", []string{}, "Filter output based on conditions given") + _ = cmd.RegisterFlagCompletionFunc(filterFlagName, common.AutocompletePsFilters) + + if registry.IsRemote() { + _ = flags.MarkHidden("cidfile") + } } func init() { registry.Commands = append(registry.Commands, registry.CliCommand{ Command: unpauseCommand, }) - flags := unpauseCommand.Flags() - unpauseFlags(flags) + unpauseFlags(unpauseCommand) + validate.AddLatestFlag(unpauseCommand, &unpauseOpts.Latest) registry.Commands = append(registry.Commands, registry.CliCommand{ Command: containerUnpauseCommand, Parent: containerCmd, }) - - unpauseCommandFlags := containerUnpauseCommand.Flags() - unpauseFlags(unpauseCommandFlags) + unpauseFlags(containerUnpauseCommand) + validate.AddLatestFlag(containerUnpauseCommand, &unpauseOpts.Latest) } func unpause(cmd *cobra.Command, args []string) error { @@ -69,16 +97,32 @@ func unpause(cmd *cobra.Command, args []string) error { return errors.New("unpause is not supported for cgroupv1 rootless containers") } } - if len(args) < 1 && !unPauseOptions.All { - return errors.New("you must provide at least one container name or id") + + for _, cidFile := range unpauseCidFiles { + content, err := ioutil.ReadFile(cidFile) + if err != nil { + return fmt.Errorf("error reading CIDFile: %w", err) + } + id := strings.Split(string(content), "\n")[0] + args = append(args, id) + } + + for _, f := range filters { + split := strings.SplitN(f, "=", 2) + if len(split) < 2 { + return fmt.Errorf("invalid filter %q", f) + } + unpauseOpts.Filters[split[0]] = append(unpauseOpts.Filters[split[0]], split[1]) } - responses, err := registry.ContainerEngine().ContainerUnpause(context.Background(), args, unPauseOptions) + + responses, err := registry.ContainerEngine().ContainerUnpause(context.Background(), args, unpauseOpts) if err != nil { return err } + for _, r := range responses { if r.Err == nil { - fmt.Println(r.Id) + fmt.Println(r.RawInput) } else { errs = append(errs, r.Err) } -- cgit v1.2.3-54-g00ecf