mirror of
https://github.com/containers/podman.git
synced 2025-05-20 16:47:39 +08:00
podmanv2 add core container commands
add core container commands for podmanv2: kill, pause, restart, rm, stop, unpause Signed-off-by: Brent Baude <bbaude@redhat.com>
This commit is contained in:
71
cmd/podmanV2/containers/kill.go
Normal file
71
cmd/podmanV2/containers/kill.go
Normal file
@ -0,0 +1,71 @@
|
||||
package containers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/libpod/cmd/podmanV2/parse"
|
||||
"github.com/containers/libpod/cmd/podmanV2/registry"
|
||||
"github.com/containers/libpod/cmd/podmanV2/utils"
|
||||
"github.com/containers/libpod/pkg/domain/entities"
|
||||
"github.com/containers/libpod/pkg/signal"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
killDescription = "The main process inside each container specified will be sent SIGKILL, or any signal specified with option --signal."
|
||||
killCommand = &cobra.Command{
|
||||
Use: "kill [flags] CONTAINER [CONTAINER...]",
|
||||
Short: "Kill one or more running containers with a specific signal",
|
||||
Long: killDescription,
|
||||
RunE: kill,
|
||||
Args: func(cmd *cobra.Command, args []string) error {
|
||||
return parse.CheckAllLatestAndCIDFile(cmd, args, false, false)
|
||||
},
|
||||
Example: `podman kill mywebserver
|
||||
podman kill 860a4b23
|
||||
podman kill --signal TERM ctrID`,
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
killOptions = entities.KillOptions{}
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.Commands = append(registry.Commands, registry.CliCommand{
|
||||
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
|
||||
Command: killCommand,
|
||||
})
|
||||
flags := killCommand.Flags()
|
||||
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 utils.IsRemote() {
|
||||
_ = flags.MarkHidden("latest")
|
||||
}
|
||||
}
|
||||
|
||||
func kill(cmd *cobra.Command, args []string) error {
|
||||
var (
|
||||
err error
|
||||
errs utils.OutputErrors
|
||||
)
|
||||
// Check if the signalString provided by the user is valid
|
||||
// Invalid signals will return err
|
||||
if _, err = signal.ParseSignalNameOrNumber(killOptions.Signal); err != nil {
|
||||
return err
|
||||
}
|
||||
responses, err := registry.ContainerEngine().ContainerKill(context.Background(), args, killOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, r := range responses {
|
||||
if r.Err == nil {
|
||||
fmt.Println(r.Id)
|
||||
} else {
|
||||
errs = append(errs, r.Err)
|
||||
}
|
||||
}
|
||||
return errs.PrintErrors()
|
||||
}
|
63
cmd/podmanV2/containers/pause.go
Normal file
63
cmd/podmanV2/containers/pause.go
Normal file
@ -0,0 +1,63 @@
|
||||
package containers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/libpod/cmd/podmanV2/registry"
|
||||
"github.com/containers/libpod/cmd/podmanV2/utils"
|
||||
"github.com/containers/libpod/pkg/domain/entities"
|
||||
"github.com/containers/libpod/pkg/rootless"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
pauseDescription = `Pauses one or more running containers. The container name or ID can be used.`
|
||||
pauseCommand = &cobra.Command{
|
||||
Use: "pause [flags] CONTAINER [CONTAINER...]",
|
||||
Short: "Pause all the processes in one or more containers",
|
||||
Long: pauseDescription,
|
||||
RunE: pause,
|
||||
Example: `podman pause mywebserver
|
||||
podman pause 860a4b23
|
||||
podman pause -a`,
|
||||
}
|
||||
|
||||
pauseOpts = entities.PauseUnPauseOptions{}
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.Commands = append(registry.Commands, registry.CliCommand{
|
||||
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
|
||||
Command: pauseCommand,
|
||||
})
|
||||
flags := pauseCommand.Flags()
|
||||
flags.BoolVarP(&pauseOpts.All, "all", "a", false, "Pause all running containers")
|
||||
pauseCommand.SetHelpTemplate(registry.HelpTemplate())
|
||||
pauseCommand.SetUsageTemplate(registry.UsageTemplate())
|
||||
}
|
||||
|
||||
func pause(cmd *cobra.Command, args []string) error {
|
||||
var (
|
||||
errs utils.OutputErrors
|
||||
)
|
||||
if rootless.IsRootless() && !utils.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")
|
||||
}
|
||||
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)
|
||||
} else {
|
||||
errs = append(errs, r.Err)
|
||||
}
|
||||
}
|
||||
return errs.PrintErrors()
|
||||
}
|
78
cmd/podmanV2/containers/restart.go
Normal file
78
cmd/podmanV2/containers/restart.go
Normal file
@ -0,0 +1,78 @@
|
||||
package containers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/libpod/cmd/podmanV2/parse"
|
||||
"github.com/containers/libpod/cmd/podmanV2/registry"
|
||||
"github.com/containers/libpod/cmd/podmanV2/utils"
|
||||
"github.com/containers/libpod/libpod/define"
|
||||
"github.com/containers/libpod/pkg/domain/entities"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
restartDescription = `Restarts one or more running containers. The container ID or name can be used.
|
||||
|
||||
A timeout before forcibly stopping can be set, but defaults to 10 seconds.`
|
||||
restartCommand = &cobra.Command{
|
||||
Use: "restart [flags] CONTAINER [CONTAINER...]",
|
||||
Short: "Restart one or more containers",
|
||||
Long: restartDescription,
|
||||
RunE: restart,
|
||||
Args: func(cmd *cobra.Command, args []string) error {
|
||||
return parse.CheckAllLatestAndCIDFile(cmd, args, false, false)
|
||||
},
|
||||
Example: `podman restart ctrID
|
||||
podman restart --latest
|
||||
podman restart ctrID1 ctrID2`,
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
restartOptions = entities.RestartOptions{}
|
||||
restartTimeout uint
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.Commands = append(registry.Commands, registry.CliCommand{
|
||||
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
|
||||
Command: restartCommand,
|
||||
})
|
||||
flags := restartCommand.Flags()
|
||||
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, "timeout", "t", define.CtrRemoveTimeout, "Seconds to wait for stop before killing the container")
|
||||
flags.UintVar(&restartTimeout, "time", define.CtrRemoveTimeout, "Seconds to wait for stop before killing the container")
|
||||
if utils.IsRemote() {
|
||||
_ = flags.MarkHidden("latest")
|
||||
}
|
||||
}
|
||||
|
||||
func restart(cmd *cobra.Command, args []string) error {
|
||||
var (
|
||||
errs utils.OutputErrors
|
||||
)
|
||||
if len(args) < 1 && !restartOptions.Latest && !restartOptions.All {
|
||||
return errors.Wrapf(define.ErrInvalidArg, "you must provide at least one container name or ID")
|
||||
}
|
||||
|
||||
if cmd.Flag("timeout").Changed || cmd.Flag("time").Changed {
|
||||
restartOptions.Timeout = &restartTimeout
|
||||
}
|
||||
responses, err := registry.ContainerEngine().ContainerRestart(context.Background(), args, restartOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, r := range responses {
|
||||
if r.Err == nil {
|
||||
fmt.Println(r.Id)
|
||||
} else {
|
||||
errs = append(errs, r.Err)
|
||||
}
|
||||
}
|
||||
return errs.PrintErrors()
|
||||
}
|
93
cmd/podmanV2/containers/rm.go
Normal file
93
cmd/podmanV2/containers/rm.go
Normal file
@ -0,0 +1,93 @@
|
||||
package containers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/libpod/cmd/podmanV2/parse"
|
||||
"github.com/containers/libpod/cmd/podmanV2/registry"
|
||||
"github.com/containers/libpod/cmd/podmanV2/utils"
|
||||
"github.com/containers/libpod/libpod/define"
|
||||
"github.com/containers/libpod/pkg/domain/entities"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
rmDescription = `Removes one or more containers from the host. The container name or ID can be used.
|
||||
|
||||
Command does not remove images. Running or unusable containers will not be removed without the -f option.`
|
||||
rmCommand = &cobra.Command{
|
||||
Use: "rm [flags] CONTAINER [CONTAINER...]",
|
||||
Short: "Remove one or more containers",
|
||||
Long: rmDescription,
|
||||
RunE: rm,
|
||||
Args: func(cmd *cobra.Command, args []string) error {
|
||||
return parse.CheckAllLatestAndCIDFile(cmd, args, false, true)
|
||||
},
|
||||
Example: `podman rm imageID
|
||||
podman rm mywebserver myflaskserver 860a4b23
|
||||
podman rm --force --all
|
||||
podman rm -f c684f0d469f2`,
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
rmOptions = entities.RmOptions{}
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.Commands = append(registry.Commands, registry.CliCommand{
|
||||
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
|
||||
Command: rmCommand,
|
||||
})
|
||||
flags := rmCommand.Flags()
|
||||
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 utils.IsRemote() {
|
||||
_ = flags.MarkHidden("latest")
|
||||
_ = flags.MarkHidden("ignore")
|
||||
_ = flags.MarkHidden("cidfile")
|
||||
_ = flags.MarkHidden("storage")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func rm(cmd *cobra.Command, args []string) error {
|
||||
var (
|
||||
errs utils.OutputErrors
|
||||
)
|
||||
// Storage conflicts with --all/--latest/--volumes/--cidfile/--ignore
|
||||
if rmOptions.Storage {
|
||||
if rmOptions.All || rmOptions.Ignore || rmOptions.Latest || rmOptions.Volumes || rmOptions.CIDFiles != nil {
|
||||
return errors.Errorf("--storage conflicts with --volumes, --all, --latest, --ignore and --cidfile")
|
||||
}
|
||||
}
|
||||
responses, err := registry.ContainerEngine().ContainerRm(context.Background(), args, rmOptions)
|
||||
if err != nil {
|
||||
// TODO exitcode is a global main variable to track exit codes.
|
||||
// we need this enabled
|
||||
//if len(c.InputArgs) < 2 {
|
||||
// exitCode = setExitCode(err)
|
||||
//}
|
||||
return err
|
||||
}
|
||||
for _, r := range responses {
|
||||
if r.Err != nil {
|
||||
// TODO this will not work with the remote client
|
||||
if errors.Cause(err) == define.ErrWillDeadlock {
|
||||
logrus.Errorf("Potential deadlock detected - please run 'podman system renumber' to resolve")
|
||||
}
|
||||
errs = append(errs, r.Err)
|
||||
} else {
|
||||
fmt.Println(r.Id)
|
||||
}
|
||||
}
|
||||
return errs.PrintErrors()
|
||||
}
|
87
cmd/podmanV2/containers/stop.go
Normal file
87
cmd/podmanV2/containers/stop.go
Normal file
@ -0,0 +1,87 @@
|
||||
package containers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/libpod/cmd/podmanV2/parse"
|
||||
"github.com/containers/libpod/cmd/podmanV2/registry"
|
||||
"github.com/containers/libpod/cmd/podmanV2/utils"
|
||||
"github.com/containers/libpod/libpod/define"
|
||||
"github.com/containers/libpod/pkg/domain/entities"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
stopDescription = `Stops one or more running containers. The container name or ID can be used.
|
||||
|
||||
A timeout to forcibly stop the container can also be set but defaults to 10 seconds otherwise.`
|
||||
stopCommand = &cobra.Command{
|
||||
Use: "stop [flags] CONTAINER [CONTAINER...]",
|
||||
Short: "Stop one or more containers",
|
||||
Long: stopDescription,
|
||||
RunE: stop,
|
||||
Args: func(cmd *cobra.Command, args []string) error {
|
||||
return parse.CheckAllLatestAndCIDFile(cmd, args, false, true)
|
||||
},
|
||||
Example: `podman stop ctrID
|
||||
podman stop --latest
|
||||
podman stop --timeout 2 mywebserver 6e534f14da9d`,
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
stopOptions = entities.StopOptions{}
|
||||
stopTimeout uint
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.Commands = append(registry.Commands, registry.CliCommand{
|
||||
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
|
||||
Command: stopCommand,
|
||||
})
|
||||
flags := stopCommand.Flags()
|
||||
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.UintVar(&stopTimeout, "time", define.CtrRemoveTimeout, "Seconds to wait for stop before killing the container")
|
||||
flags.UintVarP(&stopTimeout, "timeout", "t", define.CtrRemoveTimeout, "Seconds to wait for stop before killing the container")
|
||||
if registry.EngineOpts.EngineMode == entities.ABIMode {
|
||||
_ = flags.MarkHidden("latest")
|
||||
_ = flags.MarkHidden("cidfile")
|
||||
_ = flags.MarkHidden("ignore")
|
||||
}
|
||||
}
|
||||
|
||||
func stop(cmd *cobra.Command, args []string) error {
|
||||
var (
|
||||
errs utils.OutputErrors
|
||||
)
|
||||
if cmd.Flag("timeout").Changed && cmd.Flag("time").Changed {
|
||||
return errors.New("the --timeout and --time flags are mutually exclusive")
|
||||
}
|
||||
stopOptions.Timeout = define.CtrRemoveTimeout
|
||||
if cmd.Flag("timeout").Changed || cmd.Flag("time").Changed {
|
||||
stopOptions.Timeout = stopTimeout
|
||||
}
|
||||
|
||||
// TODO How do we access global attributes?
|
||||
//if c.Bool("trace") {
|
||||
// span, _ := opentracing.StartSpanFromContext(Ctx, "stopCmd")
|
||||
// defer span.Finish()
|
||||
//}
|
||||
responses, err := registry.ContainerEngine().ContainerStop(context.Background(), args, stopOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, r := range responses {
|
||||
if r.Err == nil {
|
||||
fmt.Println(r.Id)
|
||||
} else {
|
||||
errs = append(errs, r.Err)
|
||||
}
|
||||
}
|
||||
return errs.PrintErrors()
|
||||
}
|
60
cmd/podmanV2/containers/unpause.go
Normal file
60
cmd/podmanV2/containers/unpause.go
Normal file
@ -0,0 +1,60 @@
|
||||
package containers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/containers/libpod/cmd/podmanV2/registry"
|
||||
"github.com/containers/libpod/cmd/podmanV2/utils"
|
||||
"github.com/containers/libpod/pkg/domain/entities"
|
||||
"github.com/containers/libpod/pkg/rootless"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
unpauseDescription = `Unpauses one or more previously paused containers. The container name or ID can be used.`
|
||||
unpauseCommand = &cobra.Command{
|
||||
Use: "unpause [flags] CONTAINER [CONTAINER...]",
|
||||
Short: "Unpause the processes in one or more containers",
|
||||
Long: unpauseDescription,
|
||||
RunE: unpause,
|
||||
Example: `podman unpause ctrID
|
||||
podman unpause --all`,
|
||||
}
|
||||
unPauseOptions = entities.PauseUnPauseOptions{}
|
||||
)
|
||||
|
||||
func init() {
|
||||
registry.Commands = append(registry.Commands, registry.CliCommand{
|
||||
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
|
||||
Command: unpauseCommand,
|
||||
Parent: containerCmd,
|
||||
})
|
||||
flags := unpauseCommand.Flags()
|
||||
flags.BoolVarP(&unPauseOptions.All, "all", "a", false, "Pause all running containers")
|
||||
}
|
||||
|
||||
func unpause(cmd *cobra.Command, args []string) error {
|
||||
var (
|
||||
errs utils.OutputErrors
|
||||
)
|
||||
if rootless.IsRootless() && !utils.IsRemote() {
|
||||
return errors.New("unpause is not supported for rootless containers")
|
||||
}
|
||||
if len(args) < 1 && !unPauseOptions.All {
|
||||
return errors.Errorf("you must provide at least one container name or id")
|
||||
}
|
||||
responses, err := registry.ContainerEngine().ContainerUnpause(context.Background(), args, unPauseOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, r := range responses {
|
||||
if r.Err == nil {
|
||||
fmt.Println(r.Id)
|
||||
} else {
|
||||
errs = append(errs, r.Err)
|
||||
}
|
||||
}
|
||||
return errs.PrintErrors()
|
||||
}
|
1
cmd/podmanV2/containers/utils.go
Normal file
1
cmd/podmanV2/containers/utils.go
Normal file
@ -0,0 +1 @@
|
||||
package containers
|
@ -5,7 +5,9 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/containers/libpod/cmd/podmanV2/parse"
|
||||
"github.com/containers/libpod/cmd/podmanV2/registry"
|
||||
"github.com/containers/libpod/cmd/podmanV2/utils"
|
||||
"github.com/containers/libpod/libpod/define"
|
||||
"github.com/containers/libpod/pkg/domain/entities"
|
||||
"github.com/pkg/errors"
|
||||
@ -20,6 +22,9 @@ var (
|
||||
Short: "Block on one or more containers",
|
||||
Long: waitDescription,
|
||||
RunE: wait,
|
||||
Args: func(cmd *cobra.Command, args []string) error {
|
||||
return parse.CheckAllLatestAndCIDFile(cmd, args, false, false)
|
||||
},
|
||||
Example: `podman wait --latest
|
||||
podman wait --interval 5000 ctrID
|
||||
podman wait ctrID1 ctrID2`,
|
||||
@ -27,7 +32,7 @@ var (
|
||||
)
|
||||
|
||||
var (
|
||||
waitFlags = entities.WaitOptions{}
|
||||
waitOptions = entities.WaitOptions{}
|
||||
waitCondition string
|
||||
)
|
||||
|
||||
@ -35,12 +40,11 @@ func init() {
|
||||
registry.Commands = append(registry.Commands, registry.CliCommand{
|
||||
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
|
||||
Command: waitCommand,
|
||||
Parent: containerCmd,
|
||||
})
|
||||
|
||||
flags := waitCommand.Flags()
|
||||
flags.DurationVarP(&waitFlags.Interval, "interval", "i", time.Duration(250), "Milliseconds to wait before polling for completion")
|
||||
flags.BoolVarP(&waitFlags.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
|
||||
flags.DurationVarP(&waitOptions.Interval, "interval", "i", time.Duration(250), "Milliseconds to wait before polling for completion")
|
||||
flags.BoolVarP(&waitOptions.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
|
||||
flags.StringVar(&waitCondition, "condition", "stopped", "Condition to wait on")
|
||||
if registry.EngineOpts.EngineMode == entities.ABIMode {
|
||||
// TODO: This is the same as V1. We could skip creating the flag altogether in V2...
|
||||
@ -50,33 +54,28 @@ func init() {
|
||||
|
||||
func wait(cmd *cobra.Command, args []string) error {
|
||||
var (
|
||||
err error
|
||||
err error
|
||||
errs utils.OutputErrors
|
||||
)
|
||||
if waitFlags.Latest && len(args) > 0 {
|
||||
return errors.New("cannot combine latest flag and arguments")
|
||||
}
|
||||
if waitFlags.Interval == 0 {
|
||||
if waitOptions.Interval == 0 {
|
||||
return errors.New("interval must be greater then 0")
|
||||
}
|
||||
|
||||
waitFlags.Condition, err = define.StringToContainerStatus(waitCondition)
|
||||
waitOptions.Condition, err = define.StringToContainerStatus(waitCondition)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
responses, err := registry.ContainerEngine().ContainerWait(context.Background(), args, waitFlags)
|
||||
responses, err := registry.ContainerEngine().ContainerWait(context.Background(), args, waitOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, r := range responses {
|
||||
if r.Error == nil {
|
||||
fmt.Println(r.Id)
|
||||
} else {
|
||||
errs = append(errs, r.Error)
|
||||
}
|
||||
}
|
||||
for _, r := range responses {
|
||||
if r.Error != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return errs.PrintErrors()
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -186,3 +187,47 @@ func ValidURL(urlStr string) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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 ignoreArgLen {
|
||||
return nil
|
||||
}
|
||||
if (argLen > 0) && (specifiedAll || specifiedLatest) {
|
||||
return errors.Errorf("no arguments are needed with --all or --latest")
|
||||
} else if cidfile && (argLen > 0) && (specifiedAll || specifiedLatest || specifiedCIDFile) {
|
||||
return errors.Errorf("no arguments are needed with --all, --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
|
||||
}
|
||||
|
@ -23,8 +23,9 @@ var rootCmd = &cobra.Command{
|
||||
func init() {
|
||||
// Override default --help information of `--version` global flag}
|
||||
var dummyVersion bool
|
||||
rootCmd.PersistentFlags().BoolVarP(&dummyVersion, "version", "v", false, "Version of podman")
|
||||
rootCmd.PersistentFlags().StringVarP(®istry.EngineOpts.Uri, "remote", "r", "", "URL to access podman service")
|
||||
// TODO had to disable shorthand -v for version due to -v rm with volume
|
||||
rootCmd.PersistentFlags().BoolVar(&dummyVersion, "version", false, "Version of Podman")
|
||||
rootCmd.PersistentFlags().StringVarP(®istry.EngineOpts.Uri, "remote", "r", "", "URL to access Podman service")
|
||||
rootCmd.PersistentFlags().StringSliceVar(®istry.EngineOpts.Identities, "identity", []string{}, "path to SSH identity file")
|
||||
}
|
||||
|
||||
|
16
cmd/podmanV2/utils/error.go
Normal file
16
cmd/podmanV2/utils/error.go
Normal file
@ -0,0 +1,16 @@
|
||||
package utils
|
||||
|
||||
import "fmt"
|
||||
|
||||
type OutputErrors []error
|
||||
|
||||
func (o OutputErrors) PrintErrors() (lastError error) {
|
||||
if len(o) == 0 {
|
||||
return
|
||||
}
|
||||
lastError = o[len(o)-1]
|
||||
for e := 0; e < len(o)-1; e++ {
|
||||
fmt.Println(o[e])
|
||||
}
|
||||
return
|
||||
}
|
10
cmd/podmanV2/utils/remote.go
Normal file
10
cmd/podmanV2/utils/remote.go
Normal file
@ -0,0 +1,10 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"github.com/containers/libpod/cmd/podmanV2/registry"
|
||||
"github.com/containers/libpod/pkg/domain/entities"
|
||||
)
|
||||
|
||||
func IsRemote() bool {
|
||||
return registry.EngineOpts.EngineMode == entities.TunnelMode
|
||||
}
|
@ -7,7 +7,6 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/containers/libpod/libpod"
|
||||
@ -15,6 +14,7 @@ import (
|
||||
"github.com/containers/libpod/libpod/logs"
|
||||
"github.com/containers/libpod/pkg/api/handlers"
|
||||
"github.com/containers/libpod/pkg/api/handlers/utils"
|
||||
"github.com/containers/libpod/pkg/signal"
|
||||
"github.com/containers/libpod/pkg/util"
|
||||
"github.com/gorilla/schema"
|
||||
"github.com/pkg/errors"
|
||||
@ -145,14 +145,20 @@ func KillContainer(w http.ResponseWriter, r *http.Request) {
|
||||
runtime := r.Context().Value("runtime").(*libpod.Runtime)
|
||||
decoder := r.Context().Value("decoder").(*schema.Decoder)
|
||||
query := struct {
|
||||
Signal syscall.Signal `schema:"signal"`
|
||||
Signal string `schema:"signal"`
|
||||
}{
|
||||
Signal: syscall.SIGKILL,
|
||||
Signal: "KILL",
|
||||
}
|
||||
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
|
||||
utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String()))
|
||||
return
|
||||
}
|
||||
|
||||
sig, err := signal.ParseSignalNameOrNumber(query.Signal)
|
||||
if err != nil {
|
||||
utils.InternalServerError(w, err)
|
||||
return
|
||||
}
|
||||
name := utils.GetName(r)
|
||||
con, err := runtime.LookupContainer(name)
|
||||
if err != nil {
|
||||
@ -172,7 +178,7 @@ func KillContainer(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
err = con.Kill(uint(query.Signal))
|
||||
err = con.Kill(uint(sig))
|
||||
if err != nil {
|
||||
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrapf(err, "unable to kill Container %s", name))
|
||||
}
|
||||
|
@ -1,11 +1,9 @@
|
||||
package compat
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/containers/libpod/libpod/define"
|
||||
"github.com/containers/libpod/pkg/api/handlers/utils"
|
||||
"github.com/gorilla/schema"
|
||||
"github.com/pkg/errors"
|
||||
@ -32,20 +30,6 @@ func RestartContainer(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
state, err := con.State()
|
||||
if err != nil {
|
||||
utils.InternalServerError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
// FIXME: This is not in the swagger.yml...
|
||||
// If the Container is stopped already, send a 409
|
||||
if state == define.ContainerStateStopped || state == define.ContainerStateExited {
|
||||
msg := fmt.Sprintf("Container %s is not running", name)
|
||||
utils.Error(w, msg, http.StatusConflict, errors.New(msg))
|
||||
return
|
||||
}
|
||||
|
||||
timeout := con.StopTimeout()
|
||||
if _, found := r.URL.Query()["t"]; found {
|
||||
timeout = uint(query.Timeout)
|
||||
|
@ -126,13 +126,13 @@ func Inspect(ctx context.Context, nameOrID string, size *bool) (*libpod.InspectC
|
||||
// Kill sends a given signal to a given container. The signal should be the string
|
||||
// representation of a signal like 'SIGKILL'. The nameOrID can be a container name
|
||||
// or a partial/full ID
|
||||
func Kill(ctx context.Context, nameOrID string, signal string) error {
|
||||
func Kill(ctx context.Context, nameOrID string, sig string) error {
|
||||
conn, err := bindings.GetClient(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
params := url.Values{}
|
||||
params.Set("signal", signal)
|
||||
params.Set("signal", sig)
|
||||
response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/kill", params, nameOrID)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -247,14 +247,14 @@ func Exists(ctx context.Context, nameOrID string) (bool, error) {
|
||||
|
||||
// Stop stops a running container. The timeout is optional. The nameOrID can be a container name
|
||||
// or a partial/full ID
|
||||
func Stop(ctx context.Context, nameOrID string, timeout *int) error {
|
||||
func Stop(ctx context.Context, nameOrID string, timeout *uint) error {
|
||||
params := url.Values{}
|
||||
conn, err := bindings.GetClient(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if timeout != nil {
|
||||
params.Set("t", strconv.Itoa(*timeout))
|
||||
params.Set("t", strconv.Itoa(int(*timeout)))
|
||||
}
|
||||
response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/stop", params, nameOrID)
|
||||
if err != nil {
|
||||
|
@ -102,7 +102,7 @@ var _ = Describe("Podman volumes", func() {
|
||||
Expect(code).To(BeNumerically("==", http.StatusConflict))
|
||||
|
||||
// Removing with a volume in use with force should work with a stopped container
|
||||
zero := 0
|
||||
zero := uint(0)
|
||||
err = containers.Stop(connText, "vtest", &zero)
|
||||
Expect(err).To(BeNil())
|
||||
err = volumes.Remove(connText, vol.Name, &bindings.PTrue)
|
||||
|
@ -21,3 +21,63 @@ type WaitReport struct {
|
||||
type BoolReport struct {
|
||||
Value bool
|
||||
}
|
||||
|
||||
type PauseUnPauseOptions struct {
|
||||
All bool
|
||||
}
|
||||
|
||||
type PauseUnpauseReport struct {
|
||||
Err error
|
||||
Id string
|
||||
}
|
||||
|
||||
type StopOptions struct {
|
||||
All bool
|
||||
CIDFiles []string
|
||||
Ignore bool
|
||||
Latest bool
|
||||
Timeout uint
|
||||
}
|
||||
|
||||
type StopReport struct {
|
||||
Err error
|
||||
Id string
|
||||
}
|
||||
|
||||
type KillOptions struct {
|
||||
All bool
|
||||
Latest bool
|
||||
Signal string
|
||||
}
|
||||
|
||||
type KillReport struct {
|
||||
Err error
|
||||
Id string
|
||||
}
|
||||
|
||||
type RestartOptions struct {
|
||||
All bool
|
||||
Latest bool
|
||||
Running bool
|
||||
Timeout *uint
|
||||
}
|
||||
|
||||
type RestartReport struct {
|
||||
Err error
|
||||
Id string
|
||||
}
|
||||
|
||||
type RmOptions struct {
|
||||
All bool
|
||||
CIDFiles []string
|
||||
Force bool
|
||||
Ignore bool
|
||||
Latest bool
|
||||
Storage bool
|
||||
Volumes bool
|
||||
}
|
||||
|
||||
type RmReport struct {
|
||||
Err error
|
||||
Id string
|
||||
}
|
||||
|
@ -5,9 +5,14 @@ import (
|
||||
)
|
||||
|
||||
type ContainerEngine interface {
|
||||
ContainerDelete(ctx context.Context, opts ContainerDeleteOptions) (*ContainerDeleteReport, error)
|
||||
ContainerPrune(ctx context.Context) (*ContainerPruneReport, error)
|
||||
ContainerExists(ctx context.Context, nameOrId string) (*BoolReport, error)
|
||||
ContainerKill(ctx context.Context, namesOrIds []string, options KillOptions) ([]*KillReport, error)
|
||||
ContainerPause(ctx context.Context, namesOrIds []string, options PauseUnPauseOptions) ([]*PauseUnpauseReport, error)
|
||||
ContainerRestart(ctx context.Context, namesOrIds []string, options RestartOptions) ([]*RestartReport, error)
|
||||
ContainerRm(ctx context.Context, namesOrIds []string, options RmOptions) ([]*RmReport, error)
|
||||
ContainerUnpause(ctx context.Context, namesOrIds []string, options PauseUnPauseOptions) ([]*PauseUnpauseReport, error)
|
||||
ContainerStop(ctx context.Context, namesOrIds []string, options StopOptions) ([]*StopReport, error)
|
||||
ContainerWait(ctx context.Context, namesOrIds []string, options WaitOptions) ([]WaitReport, error)
|
||||
PodDelete(ctx context.Context, opts PodPruneOptions) (*PodDeleteReport, error)
|
||||
PodExists(ctx context.Context, nameOrId string) (*BoolReport, error)
|
||||
|
@ -4,11 +4,16 @@ package abi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/containers/libpod/libpod/define"
|
||||
"github.com/containers/libpod/pkg/adapter/shortcuts"
|
||||
"github.com/containers/libpod/pkg/domain/entities"
|
||||
"github.com/containers/libpod/pkg/signal"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// TODO: Should return *entities.ContainerExistsReport, error
|
||||
@ -41,8 +46,198 @@ func (ic *ContainerEngine) ContainerWait(ctx context.Context, namesOrIds []strin
|
||||
return responses, nil
|
||||
}
|
||||
|
||||
func (ic *ContainerEngine) ContainerDelete(ctx context.Context, opts entities.ContainerDeleteOptions) (*entities.ContainerDeleteReport, error) {
|
||||
panic("implement me")
|
||||
func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []string, options entities.PauseUnPauseOptions) ([]*entities.PauseUnpauseReport, error) {
|
||||
var (
|
||||
ctrs []*libpod.Container
|
||||
err error
|
||||
report []*entities.PauseUnpauseReport
|
||||
)
|
||||
if options.All {
|
||||
ctrs, err = ic.Libpod.GetAllContainers()
|
||||
} else {
|
||||
ctrs, err = shortcuts.GetContainersByContext(false, false, namesOrIds, ic.Libpod)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, c := range ctrs {
|
||||
err := c.Pause()
|
||||
report = append(report, &entities.PauseUnpauseReport{Id: c.ID(), Err: err})
|
||||
}
|
||||
return report, nil
|
||||
}
|
||||
|
||||
func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []string, options entities.PauseUnPauseOptions) ([]*entities.PauseUnpauseReport, error) {
|
||||
var (
|
||||
ctrs []*libpod.Container
|
||||
err error
|
||||
report []*entities.PauseUnpauseReport
|
||||
)
|
||||
if options.All {
|
||||
ctrs, err = ic.Libpod.GetAllContainers()
|
||||
} else {
|
||||
ctrs, err = shortcuts.GetContainersByContext(false, false, namesOrIds, ic.Libpod)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, c := range ctrs {
|
||||
err := c.Unpause()
|
||||
report = append(report, &entities.PauseUnpauseReport{Id: c.ID(), Err: err})
|
||||
}
|
||||
return report, nil
|
||||
}
|
||||
func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []string, options entities.StopOptions) ([]*entities.StopReport, error) {
|
||||
var (
|
||||
reports []*entities.StopReport
|
||||
)
|
||||
names := namesOrIds
|
||||
for _, cidFile := range options.CIDFiles {
|
||||
content, err := ioutil.ReadFile(cidFile)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error reading CIDFile")
|
||||
}
|
||||
id := strings.Split(string(content), "\n")[0]
|
||||
names = append(names, id)
|
||||
}
|
||||
ctrs, err := shortcuts.GetContainersByContext(options.All, options.Latest, names, ic.Libpod)
|
||||
if err != nil && !(options.Ignore && errors.Cause(err) == define.ErrNoSuchCtr) {
|
||||
return nil, err
|
||||
}
|
||||
for _, con := range ctrs {
|
||||
report := entities.StopReport{Id: con.ID()}
|
||||
err = con.StopWithTimeout(options.Timeout)
|
||||
if err != nil {
|
||||
// These first two are considered non-fatal under the right conditions
|
||||
if errors.Cause(err) == define.ErrCtrStopped {
|
||||
logrus.Debugf("Container %s is already stopped", con.ID())
|
||||
reports = append(reports, &report)
|
||||
continue
|
||||
|
||||
} else if options.All && errors.Cause(err) == define.ErrCtrStateInvalid {
|
||||
logrus.Debugf("Container %s is not running, could not stop", con.ID())
|
||||
reports = append(reports, &report)
|
||||
continue
|
||||
}
|
||||
report.Err = err
|
||||
reports = append(reports, &report)
|
||||
continue
|
||||
}
|
||||
reports = append(reports, &report)
|
||||
}
|
||||
return reports, nil
|
||||
}
|
||||
|
||||
func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []string, options entities.KillOptions) ([]*entities.KillReport, error) {
|
||||
var (
|
||||
reports []*entities.KillReport
|
||||
)
|
||||
sig, err := signal.ParseSignalNameOrNumber(options.Signal)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ctrs, err := shortcuts.GetContainersByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, con := range ctrs {
|
||||
reports = append(reports, &entities.KillReport{
|
||||
Id: con.ID(),
|
||||
Err: con.Kill(uint(sig)),
|
||||
})
|
||||
}
|
||||
return reports, nil
|
||||
}
|
||||
func (ic *ContainerEngine) ContainerRestart(ctx context.Context, namesOrIds []string, options entities.RestartOptions) ([]*entities.RestartReport, error) {
|
||||
var (
|
||||
reports []*entities.RestartReport
|
||||
)
|
||||
ctrs, err := shortcuts.GetContainersByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, con := range ctrs {
|
||||
timeout := con.StopTimeout()
|
||||
if options.Timeout != nil {
|
||||
timeout = *options.Timeout
|
||||
}
|
||||
reports = append(reports, &entities.RestartReport{
|
||||
Id: con.ID(),
|
||||
Err: con.RestartWithTimeout(ctx, timeout),
|
||||
})
|
||||
}
|
||||
return reports, nil
|
||||
}
|
||||
|
||||
func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string, options entities.RmOptions) ([]*entities.RmReport, error) {
|
||||
var (
|
||||
reports []*entities.RmReport
|
||||
)
|
||||
if options.Storage {
|
||||
for _, ctr := range namesOrIds {
|
||||
report := entities.RmReport{Id: ctr}
|
||||
if err := ic.Libpod.RemoveStorageContainer(ctr, options.Force); err != nil {
|
||||
report.Err = err
|
||||
}
|
||||
reports = append(reports, &report)
|
||||
}
|
||||
return reports, nil
|
||||
}
|
||||
|
||||
names := namesOrIds
|
||||
for _, cidFile := range options.CIDFiles {
|
||||
content, err := ioutil.ReadFile(cidFile)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error reading CIDFile")
|
||||
}
|
||||
id := strings.Split(string(content), "\n")[0]
|
||||
names = append(names, id)
|
||||
}
|
||||
|
||||
ctrs, err := shortcuts.GetContainersByContext(options.All, options.Latest, names, ic.Libpod)
|
||||
if err != nil && !(options.Ignore && errors.Cause(err) == define.ErrNoSuchCtr) {
|
||||
// Failed to get containers. If force is specified, get the containers ID
|
||||
// and evict them
|
||||
if !options.Force {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, ctr := range namesOrIds {
|
||||
logrus.Debugf("Evicting container %q", ctr)
|
||||
report := entities.RmReport{Id: ctr}
|
||||
id, err := ic.Libpod.EvictContainer(ctx, ctr, options.Volumes)
|
||||
if err != nil {
|
||||
if options.Ignore && errors.Cause(err) == define.ErrNoSuchCtr {
|
||||
logrus.Debugf("Ignoring error (--allow-missing): %v", err)
|
||||
reports = append(reports, &report)
|
||||
continue
|
||||
}
|
||||
report.Err = errors.Wrapf(err, "Failed to evict container: %q", id)
|
||||
reports = append(reports, &report)
|
||||
continue
|
||||
}
|
||||
reports = append(reports, &report)
|
||||
}
|
||||
return reports, nil
|
||||
}
|
||||
|
||||
for _, c := range ctrs {
|
||||
report := entities.RmReport{Id: c.ID()}
|
||||
err := ic.Libpod.RemoveContainer(ctx, c, options.Force, options.Volumes)
|
||||
if err != nil {
|
||||
if options.Ignore && errors.Cause(err) == define.ErrNoSuchCtr {
|
||||
logrus.Debugf("Ignoring error (--allow-missing): %v", err)
|
||||
reports = append(reports, &report)
|
||||
continue
|
||||
}
|
||||
logrus.Debugf("Failed to remove container %s: %s", c.ID(), err.Error())
|
||||
report.Err = err
|
||||
reports = append(reports, &report)
|
||||
continue
|
||||
}
|
||||
reports = append(reports, &report)
|
||||
}
|
||||
return reports, nil
|
||||
}
|
||||
|
||||
func (ic *ContainerEngine) ContainerPrune(ctx context.Context) (*entities.ContainerPruneReport, error) {
|
||||
|
@ -40,3 +40,108 @@ func (r *ContainerEngine) ContainerDelete(ctx context.Context, opts entities.Con
|
||||
func (r *ContainerEngine) ContainerPrune(ctx context.Context) (*entities.ContainerPruneReport, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
func (ic *ContainerEngine) ContainerPause(ctx context.Context, namesOrIds []string, options entities.PauseUnPauseOptions) ([]*entities.PauseUnpauseReport, error) {
|
||||
var (
|
||||
reports []*entities.PauseUnpauseReport
|
||||
)
|
||||
ctrs, err := getContainersByContext(ic.ClientCxt, options.All, namesOrIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, c := range ctrs {
|
||||
err := containers.Pause(ic.ClientCxt, c.ID)
|
||||
reports = append(reports, &entities.PauseUnpauseReport{Id: c.ID, Err: err})
|
||||
}
|
||||
return reports, nil
|
||||
}
|
||||
|
||||
func (ic *ContainerEngine) ContainerUnpause(ctx context.Context, namesOrIds []string, options entities.PauseUnPauseOptions) ([]*entities.PauseUnpauseReport, error) {
|
||||
var (
|
||||
reports []*entities.PauseUnpauseReport
|
||||
)
|
||||
ctrs, err := getContainersByContext(ic.ClientCxt, options.All, namesOrIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, c := range ctrs {
|
||||
err := containers.Unpause(ic.ClientCxt, c.ID)
|
||||
reports = append(reports, &entities.PauseUnpauseReport{Id: c.ID, Err: err})
|
||||
}
|
||||
return reports, nil
|
||||
}
|
||||
|
||||
func (ic *ContainerEngine) ContainerStop(ctx context.Context, namesOrIds []string, options entities.StopOptions) ([]*entities.StopReport, error) {
|
||||
var (
|
||||
reports []*entities.StopReport
|
||||
)
|
||||
ctrs, err := getContainersByContext(ic.ClientCxt, options.All, namesOrIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, c := range ctrs {
|
||||
report := entities.StopReport{Id: c.ID}
|
||||
report.Err = containers.Stop(ic.ClientCxt, c.ID, &options.Timeout)
|
||||
// TODO we need to associate errors returned by http with common
|
||||
// define.errors so that we can equity tests. this will allow output
|
||||
// to be the same as the native client
|
||||
reports = append(reports, &report)
|
||||
}
|
||||
return reports, nil
|
||||
}
|
||||
|
||||
func (ic *ContainerEngine) ContainerKill(ctx context.Context, namesOrIds []string, options entities.KillOptions) ([]*entities.KillReport, error) {
|
||||
var (
|
||||
reports []*entities.KillReport
|
||||
)
|
||||
ctrs, err := getContainersByContext(ic.ClientCxt, options.All, namesOrIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, c := range ctrs {
|
||||
reports = append(reports, &entities.KillReport{
|
||||
Id: c.ID,
|
||||
Err: containers.Kill(ic.ClientCxt, c.ID, options.Signal),
|
||||
})
|
||||
}
|
||||
return reports, nil
|
||||
}
|
||||
|
||||
func (ic *ContainerEngine) ContainerRestart(ctx context.Context, namesOrIds []string, options entities.RestartOptions) ([]*entities.RestartReport, error) {
|
||||
var (
|
||||
reports []*entities.RestartReport
|
||||
timeout *int
|
||||
)
|
||||
if options.Timeout != nil {
|
||||
t := int(*options.Timeout)
|
||||
timeout = &t
|
||||
}
|
||||
ctrs, err := getContainersByContext(ic.ClientCxt, options.All, namesOrIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, c := range ctrs {
|
||||
reports = append(reports, &entities.RestartReport{
|
||||
Id: c.ID,
|
||||
Err: containers.Restart(ic.ClientCxt, c.ID, timeout),
|
||||
})
|
||||
}
|
||||
return reports, nil
|
||||
}
|
||||
|
||||
func (ic *ContainerEngine) ContainerRm(ctx context.Context, namesOrIds []string, options entities.RmOptions) ([]*entities.RmReport, error) {
|
||||
var (
|
||||
reports []*entities.RmReport
|
||||
)
|
||||
ctrs, err := getContainersByContext(ic.ClientCxt, options.All, namesOrIds)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// TODO there is no endpoint for container eviction. Need to discuss
|
||||
for _, c := range ctrs {
|
||||
reports = append(reports, &entities.RmReport{
|
||||
Id: c.ID,
|
||||
Err: containers.Remove(ic.ClientCxt, c.ID, &options.Force, &options.Volumes),
|
||||
})
|
||||
}
|
||||
return reports, nil
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package tunnel
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/libpod/pkg/api/handlers/libpod"
|
||||
"github.com/containers/libpod/pkg/bindings"
|
||||
@ -27,7 +28,7 @@ func getContainersByContext(contextWithConnection context.Context, all bool, nam
|
||||
for _, id := range namesOrIds {
|
||||
var found bool
|
||||
for _, con := range c {
|
||||
if id == con.ID || util.StringInSlice(id, con.Names) {
|
||||
if id == con.ID || strings.HasPrefix(con.ID, id) || util.StringInSlice(id, con.Names) {
|
||||
cons = append(cons, con)
|
||||
found = true
|
||||
break
|
||||
|
@ -104,11 +104,11 @@ func ParseSignal(rawSignal string) (syscall.Signal, error) {
|
||||
}
|
||||
return syscall.Signal(s), nil
|
||||
}
|
||||
signal, ok := signalMap[strings.TrimPrefix(strings.ToUpper(rawSignal), "SIG")]
|
||||
sig, ok := signalMap[strings.TrimPrefix(strings.ToUpper(rawSignal), "SIG")]
|
||||
if !ok {
|
||||
return -1, fmt.Errorf("invalid signal: %s", rawSignal)
|
||||
}
|
||||
return signal, nil
|
||||
return sig, nil
|
||||
}
|
||||
|
||||
// CatchAll catches all signals and relays them to the specified channel.
|
||||
@ -125,3 +125,18 @@ func StopCatch(sigc chan os.Signal) {
|
||||
signal.Stop(sigc)
|
||||
close(sigc)
|
||||
}
|
||||
|
||||
// ParseSignalNameOrNumber translates a string to a valid syscall signal. Input
|
||||
// can be a name or number representation i.e. "KILL" "9"
|
||||
func ParseSignalNameOrNumber(rawSignal string) (syscall.Signal, error) {
|
||||
s, err := ParseSignal(rawSignal)
|
||||
if err == nil {
|
||||
return s, nil
|
||||
}
|
||||
for k, v := range signalMap {
|
||||
if k == strings.ToUpper(rawSignal) {
|
||||
return v, nil
|
||||
}
|
||||
}
|
||||
return -1, fmt.Errorf("invalid signal: %s", rawSignal)
|
||||
}
|
||||
|
@ -26,3 +26,9 @@ func CatchAll(sigc chan os.Signal) {
|
||||
func StopCatch(sigc chan os.Signal) {
|
||||
panic("Unsupported on non-linux platforms")
|
||||
}
|
||||
|
||||
// ParseSignalNameOrNumber translates a string to a valid syscall signal. Input
|
||||
// can be a name or number representation i.e. "KILL" "9"
|
||||
func ParseSignalNameOrNumber(rawSignal string) (syscall.Signal, error) {
|
||||
return 0, fmt.Errorf("unsupported on non-linux platforms")
|
||||
}
|
||||
|
@ -309,15 +309,15 @@ func ParseSignal(rawSignal string) (syscall.Signal, error) {
|
||||
// Strip off leading dash, to allow -1 or -HUP
|
||||
basename := strings.TrimPrefix(rawSignal, "-")
|
||||
|
||||
signal, err := signal.ParseSignal(basename)
|
||||
sig, err := signal.ParseSignal(basename)
|
||||
if err != nil {
|
||||
return -1, err
|
||||
}
|
||||
// 64 is SIGRTMAX; wish we could get this from a standard Go library
|
||||
if signal < 1 || signal > 64 {
|
||||
if sig < 1 || sig > 64 {
|
||||
return -1, errors.Errorf("valid signals are 1 through 64")
|
||||
}
|
||||
return signal, nil
|
||||
return sig, nil
|
||||
}
|
||||
|
||||
// ParseIDMapping takes idmappings and subuid and subgid maps and returns a storage mapping
|
||||
|
Reference in New Issue
Block a user