Merge pull request #5625 from baude/v2pods

podmanv2 pod subcommands
This commit is contained in:
OpenShift Merge Robot
2020-03-26 21:36:36 +01:00
committed by GitHub
21 changed files with 1278 additions and 110 deletions

68
cmd/podmanV2/pods/kill.go Normal file
View File

@ -0,0 +1,68 @@
package pods
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/spf13/cobra"
)
var (
podKillDescription = `Signals are sent to the main process of each container inside the specified pod.
The default signal is SIGKILL, or any signal specified with option --signal.`
killCommand = &cobra.Command{
Use: "kill [flags] POD [POD...]",
Short: "Send the specified signal or SIGKILL to containers in pod",
Long: podKillDescription,
RunE: kill,
Args: func(cmd *cobra.Command, args []string) error {
return parse.CheckAllLatestAndCIDFile(cmd, args, false, false)
},
Example: `podman pod kill podID
podman pod kill --signal TERM mywebserver
podman pod kill --latest`,
}
)
var (
killOpts entities.PodKillOptions
)
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
Command: killCommand,
Parent: podCmd,
})
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")
}
}
func kill(cmd *cobra.Command, args []string) error {
var (
errs utils.OutputErrors
)
responses, err := registry.ContainerEngine().PodKill(context.Background(), args, killOpts)
if err != nil {
return err
}
// in the cli, first we print out all the successful attempts
for _, r := range responses {
if len(r.Errs) == 0 {
fmt.Println(r.Id)
} else {
errs = append(errs, r.Errs...)
}
}
return errs.PrintErrors()
}

View File

@ -0,0 +1,66 @@
package pods
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/spf13/cobra"
)
var (
podPauseDescription = `The pod name or ID can be used.
All running containers within each specified pod will then be paused.`
pauseCommand = &cobra.Command{
Use: "pause [flags] POD [POD...]",
Short: "Pause one or more pods",
Long: podPauseDescription,
RunE: pause,
Args: func(cmd *cobra.Command, args []string) error {
return parse.CheckAllLatestAndCIDFile(cmd, args, false, false)
},
Example: `podman pod pause podID1 podID2
podman pod pause --latest
podman pod pause --all`,
}
)
var (
pauseOptions entities.PodPauseOptions
)
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
Command: pauseCommand,
Parent: podCmd,
})
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")
}
}
func pause(cmd *cobra.Command, args []string) error {
var (
errs utils.OutputErrors
)
responses, err := registry.ContainerEngine().PodPause(context.Background(), args, pauseOptions)
if err != nil {
return err
}
// in the cli, first we print out all the successful attempts
for _, r := range responses {
if len(r.Errs) == 0 {
fmt.Println(r.Id)
} else {
errs = append(errs, r.Errs...)
}
}
return errs.PrintErrors()
}

View File

@ -0,0 +1,68 @@
package pods
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/spf13/cobra"
)
var (
podRestartDescription = `The pod ID or name can be used.
All of the containers within each of the specified pods will be restarted. If a container in a pod is not currently running it will be started.`
restartCommand = &cobra.Command{
Use: "restart [flags] POD [POD...]",
Short: "Restart one or more pods",
Long: podRestartDescription,
RunE: restart,
Args: func(cmd *cobra.Command, args []string) error {
return parse.CheckAllLatestAndCIDFile(cmd, args, false, false)
},
Example: `podman pod restart podID1 podID2
podman pod restart --latest
podman pod restart --all`,
}
)
var (
restartOptions = entities.PodRestartOptions{}
)
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
Command: restartCommand,
Parent: podCmd,
})
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")
}
}
func restart(cmd *cobra.Command, args []string) error {
var (
errs utils.OutputErrors
)
responses, err := registry.ContainerEngine().PodRestart(context.Background(), args, restartOptions)
if err != nil {
return err
}
// in the cli, first we print out all the successful attempts
for _, r := range responses {
if len(r.Errs) == 0 {
fmt.Println(r.Id)
} else {
errs = append(errs, r.Errs...)
}
}
return errs.PrintErrors()
}

71
cmd/podmanV2/pods/rm.go Normal file
View File

@ -0,0 +1,71 @@
package pods
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/spf13/cobra"
)
var (
podRmDescription = fmt.Sprintf(`podman rm will remove one or more stopped pods and their containers from the host.
The pod name or ID can be used. A pod with containers will not be removed without --force. If --force is specified, all containers will be stopped, then removed.`)
rmCommand = &cobra.Command{
Use: "rm [flags] POD [POD...]",
Short: "Remove one or more pods",
Long: podRmDescription,
RunE: rm,
Args: func(cmd *cobra.Command, args []string) error {
return parse.CheckAllLatestAndCIDFile(cmd, args, false, false)
},
Example: `podman pod rm mywebserverpod
podman pod rm -f 860a4b23
podman pod rm -f -a`,
}
)
var (
rmOptions = entities.PodRmOptions{}
)
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
Command: rmCommand,
Parent: podCmd,
})
flags := rmCommand.Flags()
flags.BoolVarP(&rmOptions.All, "all", "a", false, "Restart 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, "Restart the latest pod podman is aware of")
if registry.IsRemote() {
_ = flags.MarkHidden("latest")
_ = flags.MarkHidden("ignore")
}
}
func rm(cmd *cobra.Command, args []string) error {
var (
errs utils.OutputErrors
)
responses, err := registry.ContainerEngine().PodRm(context.Background(), args, rmOptions)
if err != nil {
return err
}
// in the cli, first we print out all the successful attempts
for _, r := range responses {
if r.Err == nil {
fmt.Println(r.Id)
} else {
errs = append(errs, r.Err)
}
}
return errs.PrintErrors()
}

View File

@ -0,0 +1,68 @@
package pods
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/spf13/cobra"
)
var (
podStartDescription = `The pod name or ID can be used.
All containers defined in the pod will be started.`
startCommand = &cobra.Command{
Use: "start [flags] POD [POD...]",
Short: "Start one or more pods",
Long: podStartDescription,
RunE: start,
Args: func(cmd *cobra.Command, args []string) error {
return parse.CheckAllLatestAndCIDFile(cmd, args, false, false)
},
Example: `podman pod start podID
podman pod start --latest
podman pod start --all`,
}
)
var (
startOptions = entities.PodStartOptions{}
)
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
Command: startCommand,
Parent: podCmd,
})
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")
if registry.IsRemote() {
_ = flags.MarkHidden("latest")
}
}
func start(cmd *cobra.Command, args []string) error {
var (
errs utils.OutputErrors
)
responses, err := registry.ContainerEngine().PodStart(context.Background(), args, startOptions)
if err != nil {
return err
}
// in the cli, first we print out all the successful attempts
for _, r := range responses {
if len(r.Errs) == 0 {
fmt.Println(r.Id)
} else {
errs = append(errs, r.Errs...)
}
}
return errs.PrintErrors()
}

78
cmd/podmanV2/pods/stop.go Normal file
View File

@ -0,0 +1,78 @@
package pods
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/spf13/cobra"
)
var (
podStopDescription = `The pod name or ID can be used.
This command will stop all running containers in each of the specified pods.`
stopCommand = &cobra.Command{
Use: "stop [flags] POD [POD...]",
Short: "Stop one or more pods",
Long: podStopDescription,
RunE: stop,
Args: func(cmd *cobra.Command, args []string) error {
return parse.CheckAllLatestAndCIDFile(cmd, args, false, false)
},
Example: `podman pod stop mywebserverpod
podman pod stop --latest
podman pod stop --timeout 0 490eb 3557fb`,
}
)
var (
stopOptions = entities.PodStopOptions{
Timeout: -1,
}
timeout uint
)
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
Command: stopCommand,
Parent: podCmd,
})
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(&timeout, "timeout", "t", 0, "Seconds to wait for pod stop before killing the container")
if registry.IsRemote() {
_ = flags.MarkHidden("latest")
_ = flags.MarkHidden("ignore")
}
}
func stop(cmd *cobra.Command, args []string) error {
var (
errs utils.OutputErrors
)
if cmd.Flag("timeout").Changed {
stopOptions.Timeout = int(timeout)
}
responses, err := registry.ContainerEngine().PodStop(context.Background(), args, stopOptions)
if err != nil {
return err
}
// in the cli, first we print out all the successful attempts
for _, r := range responses {
if len(r.Errs) == 0 {
fmt.Println(r.Id)
} else {
errs = append(errs, r.Errs...)
}
}
return errs.PrintErrors()
}

View File

@ -0,0 +1,66 @@
package pods
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/spf13/cobra"
)
var (
podUnpauseDescription = `The podman unpause command will unpause all "paused" containers assigned to the pod.
The pod name or ID can be used.`
unpauseCommand = &cobra.Command{
Use: "unpause [flags] POD [POD...]",
Short: "Unpause one or more pods",
Long: podUnpauseDescription,
RunE: unpause,
Args: func(cmd *cobra.Command, args []string) error {
return parse.CheckAllLatestAndCIDFile(cmd, args, false, false)
},
Example: `podman pod unpause podID1 podID2
podman pod unpause --all
podman pod unpause --latest`,
}
)
var (
unpauseOptions entities.PodunpauseOptions
)
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
Command: unpauseCommand,
Parent: podCmd,
})
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")
}
}
func unpause(cmd *cobra.Command, args []string) error {
var (
errs utils.OutputErrors
)
responses, err := registry.ContainerEngine().PodUnpause(context.Background(), args, unpauseOptions)
if err != nil {
return err
}
// in the cli, first we print out all the successful attempts
for _, r := range responses {
if len(r.Errs) == 0 {
fmt.Println(r.Id)
} else {
errs = append(errs, r.Errs...)
}
}
return errs.PrintErrors()
}

View File

@ -12,6 +12,7 @@ import (
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/api/handlers"
"github.com/containers/libpod/pkg/api/handlers/utils"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/util"
"github.com/gorilla/schema"
"github.com/pkg/errors"
@ -102,9 +103,6 @@ func PodCreate(w http.ResponseWriter, r *http.Request) {
}
func Pods(w http.ResponseWriter, r *http.Request) {
var (
podInspectData []*libpod.PodInspect
)
decoder := r.Context().Value("decoder").(*schema.Decoder)
query := struct {
Filters map[string][]string `schema:"filters"`
@ -118,20 +116,11 @@ func Pods(w http.ResponseWriter, r *http.Request) {
}
pods, err := utils.GetPods(w, r)
if err != nil {
utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
return
}
for _, pod := range pods {
data, err := pod.Inspect()
if err != nil {
utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
return
}
podInspectData = append(podInspectData, data)
}
utils.WriteResponse(w, http.StatusOK, podInspectData)
utils.WriteResponse(w, http.StatusOK, pods)
}
func PodInspect(w http.ResponseWriter, r *http.Request) {
@ -155,6 +144,8 @@ func PodStop(w http.ResponseWriter, r *http.Request) {
stopError error
runtime = r.Context().Value("runtime").(*libpod.Runtime)
decoder = r.Context().Value("decoder").(*schema.Decoder)
responses map[string]error
errs []error
)
query := struct {
Timeout int `schema:"t"`
@ -185,18 +176,28 @@ func PodStop(w http.ResponseWriter, r *http.Request) {
}
if query.Timeout > 0 {
_, stopError = pod.StopWithTimeout(r.Context(), false, query.Timeout)
responses, stopError = pod.StopWithTimeout(r.Context(), false, query.Timeout)
} else {
_, stopError = pod.Stop(r.Context(), false)
responses, stopError = pod.Stop(r.Context(), false)
}
if stopError != nil {
utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
return
}
utils.WriteResponse(w, http.StatusOK, "")
for _, err := range responses {
errs = append(errs, err)
}
report := entities.PodStopReport{
Errs: errs,
Id: pod.ID(),
}
utils.WriteResponse(w, http.StatusOK, report)
}
func PodStart(w http.ResponseWriter, r *http.Request) {
var (
errs []error
)
runtime := r.Context().Value("runtime").(*libpod.Runtime)
name := utils.GetName(r)
pod, err := runtime.LookupPod(name)
@ -213,11 +214,19 @@ func PodStart(w http.ResponseWriter, r *http.Request) {
utils.WriteResponse(w, http.StatusNotModified, "")
return
}
if _, err := pod.Start(r.Context()); err != nil {
responses, err := pod.Start(r.Context())
if err != nil {
utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
return
}
utils.WriteResponse(w, http.StatusOK, "")
for _, err := range responses {
errs = append(errs, err)
}
report := entities.PodStartReport{
Errs: errs,
Id: pod.ID(),
}
utils.WriteResponse(w, http.StatusOK, report)
}
func PodDelete(w http.ResponseWriter, r *http.Request) {
@ -246,10 +255,16 @@ func PodDelete(w http.ResponseWriter, r *http.Request) {
utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
return
}
utils.WriteResponse(w, http.StatusNoContent, "")
report := entities.PodRmReport{
Id: pod.ID(),
}
utils.WriteResponse(w, http.StatusOK, report)
}
func PodRestart(w http.ResponseWriter, r *http.Request) {
var (
errs []error
)
runtime := r.Context().Value("runtime").(*libpod.Runtime)
name := utils.GetName(r)
pod, err := runtime.LookupPod(name)
@ -257,12 +272,19 @@ func PodRestart(w http.ResponseWriter, r *http.Request) {
utils.PodNotFound(w, name, err)
return
}
_, err = pod.Restart(r.Context())
responses, err := pod.Restart(r.Context())
if err != nil {
utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
return
}
utils.WriteResponse(w, http.StatusOK, "")
for _, err := range responses {
errs = append(errs, err)
}
report := entities.PodRestartReport{
Errs: errs,
Id: pod.ID(),
}
utils.WriteResponse(w, http.StatusOK, report)
}
func PodPrune(w http.ResponseWriter, r *http.Request) {
@ -278,6 +300,9 @@ func PodPrune(w http.ResponseWriter, r *http.Request) {
}
func PodPause(w http.ResponseWriter, r *http.Request) {
var (
errs []error
)
runtime := r.Context().Value("runtime").(*libpod.Runtime)
name := utils.GetName(r)
pod, err := runtime.LookupPod(name)
@ -285,15 +310,25 @@ func PodPause(w http.ResponseWriter, r *http.Request) {
utils.PodNotFound(w, name, err)
return
}
_, err = pod.Pause()
responses, err := pod.Pause()
if err != nil {
utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
return
}
utils.WriteResponse(w, http.StatusNoContent, "")
for _, v := range responses {
errs = append(errs, v)
}
report := entities.PodPauseReport{
Errs: errs,
Id: pod.ID(),
}
utils.WriteResponse(w, http.StatusOK, report)
}
func PodUnpause(w http.ResponseWriter, r *http.Request) {
var (
errs []error
)
runtime := r.Context().Value("runtime").(*libpod.Runtime)
name := utils.GetName(r)
pod, err := runtime.LookupPod(name)
@ -301,12 +336,19 @@ func PodUnpause(w http.ResponseWriter, r *http.Request) {
utils.PodNotFound(w, name, err)
return
}
_, err = pod.Unpause()
responses, err := pod.Unpause()
if err != nil {
utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
utils.Error(w, "failed to pause pod", http.StatusInternalServerError, err)
return
}
utils.WriteResponse(w, http.StatusOK, "")
for _, v := range responses {
errs = append(errs, v)
}
report := entities.PodUnpauseReport{
Errs: errs,
Id: pod.ID(),
}
utils.WriteResponse(w, http.StatusOK, &report)
}
func PodKill(w http.ResponseWriter, r *http.Request) {
@ -314,6 +356,7 @@ func PodKill(w http.ResponseWriter, r *http.Request) {
runtime = r.Context().Value("runtime").(*libpod.Runtime)
decoder = r.Context().Value("decoder").(*schema.Decoder)
signal = "SIGKILL"
errs []error
)
query := struct {
Signal string `schema:"signal"`
@ -356,12 +399,23 @@ func PodKill(w http.ResponseWriter, r *http.Request) {
utils.Error(w, msg, http.StatusConflict, errors.Errorf("cannot kill a pod with no running containers: %s", pod.ID()))
return
}
_, err = pod.Kill(uint(sig))
responses, err := pod.Kill(uint(sig))
if err != nil {
utils.Error(w, "Something went wrong", http.StatusInternalServerError, err)
utils.Error(w, "failed to kill pod", http.StatusInternalServerError, err)
return
}
utils.WriteResponse(w, http.StatusOK, "")
for _, v := range responses {
if v != nil {
errs = append(errs, v)
}
}
report := &entities.PodKillReport{
Errs: errs,
Id: pod.ID(),
}
utils.WriteResponse(w, http.StatusOK, report)
}
func PodExists(w http.ResponseWriter, r *http.Request) {

View File

@ -6,6 +6,7 @@ import (
"github.com/containers/image/v5/manifest"
"github.com/containers/libpod/pkg/api/handlers/utils"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/pkg/errors"
)
@ -26,6 +27,55 @@ type swagInspectManifestResponse struct {
Body manifest.List
}
// Kill Pod
// swagger:response PodKillReport
type swagKillPodResponse struct {
// in:body
Body entities.PodKillReport
}
// Pause pod
// swagger:response PodPauseReport
type swagPausePodResponse struct {
// in:body
Body entities.PodPauseReport
}
// Unpause pod
// swagger:response PodUnpauseReport
type swagUnpausePodResponse struct {
// in:body
Body entities.PodUnpauseReport
}
// Stop pod
// swagger:response PodStopReport
type swagStopPodResponse struct {
// in:body
Body entities.PodStopReport
}
// Restart pod
// swagger:response PodRestartReport
type swagRestartPodResponse struct {
// in:body
Body entities.PodRestartReport
}
// Start pod
// swagger:response PodStartReport
type swagStartPodResponse struct {
// in:body
Body entities.PodStartReport
}
// Rm pod
// swagger:response PodRmReport
type swagRmPodResponse struct {
// in:body
Body entities.PodRmReport
}
func ServeSwagger(w http.ResponseWriter, r *http.Request) {
path := DefaultPodmanSwaggerSpec
if p, found := os.LookupEnv("PODMAN_SWAGGER_SPEC"); found {

View File

@ -3,6 +3,7 @@ package handlers
import (
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/inspect"
"github.com/docker/docker/api/types"
)
@ -116,7 +117,7 @@ type swagLibpodInspectContainerResponse struct {
// swagger:response ListPodsResponse
type swagListPodsResponse struct {
// in:body
Body []libpod.PodInspect
Body []entities.ListPodsReport
}
// Inspect pod

View File

@ -6,10 +6,16 @@ import (
"github.com/containers/libpod/cmd/podman/shared"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/gorilla/schema"
)
func GetPods(w http.ResponseWriter, r *http.Request) ([]*libpod.Pod, error) {
func GetPods(w http.ResponseWriter, r *http.Request) ([]*entities.ListPodsReport, error) {
var (
lps []*entities.ListPodsReport
pods []*libpod.Pod
podErr error
)
runtime := r.Context().Value("runtime").(*libpod.Runtime)
decoder := r.Context().Value("decoder").(*schema.Decoder)
@ -37,9 +43,42 @@ func GetPods(w http.ResponseWriter, r *http.Request) ([]*libpod.Pod, error) {
if err != nil {
return nil, err
}
return shared.FilterAllPodsWithFilterFunc(runtime, filterFuncs...)
pods, podErr = shared.FilterAllPodsWithFilterFunc(runtime, filterFuncs...)
} else {
pods, podErr = runtime.GetAllPods()
}
return runtime.GetAllPods()
if podErr != nil {
return nil, podErr
}
for _, pod := range pods {
status, err := pod.GetPodStatus()
if err != nil {
return nil, err
}
ctrs, err := pod.AllContainers()
if err != nil {
return nil, err
}
lp := entities.ListPodsReport{
Cgroup: pod.CgroupParent(),
Created: pod.CreatedTime(),
Id: pod.ID(),
Name: pod.Name(),
Namespace: pod.Namespace(),
Status: status,
}
for _, ctr := range ctrs {
state, err := ctr.State()
if err != nil {
return nil, err
}
lp.Containers = append(lp.Containers, &entities.ListPodContainer{
Id: ctr.ID(),
Names: ctr.Name(),
Status: state.String(),
})
}
lps = append(lps, &lp)
}
return lps, nil
}

View File

@ -81,8 +81,8 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// type: boolean
// description : force removal of a running pod by first stopping all containers, then removing all containers in the pod
// responses:
// 204:
// description: no error
// 200:
// $ref: '#/responses/PodRmReport'
// 400:
// $ref: "#/responses/BadParamError"
// 404:
@ -146,8 +146,8 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// description: signal to be sent to pod
// default: SIGKILL
// responses:
// 204:
// description: no error
// 200:
// $ref: "#/responses/PodKillReport"
// 400:
// $ref: "#/responses/BadParamError"
// 404:
@ -170,8 +170,8 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// required: true
// description: the name or ID of the pod
// responses:
// 204:
// description: no error
// 200:
// $ref: '#/responses/PodPauseReport'
// 404:
// $ref: "#/responses/NoSuchPod"
// 500:
@ -189,8 +189,8 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// required: true
// description: the name or ID of the pod
// responses:
// 204:
// description: no error
// 200:
// $ref: '#/responses/PodRestartReport'
// 404:
// $ref: "#/responses/NoSuchPod"
// 500:
@ -208,8 +208,8 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// required: true
// description: the name or ID of the pod
// responses:
// 204:
// description: no error
// 200:
// $ref: '#/responses/PodStartReport'
// 304:
// $ref: "#/responses/PodAlreadyStartedError"
// 404:
@ -233,8 +233,8 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// type: integer
// description: timeout
// responses:
// 204:
// description: no error
// 200:
// $ref: '#/responses/PodStopReport'
// 304:
// $ref: "#/responses/PodAlreadyStoppedError"
// 400:
@ -256,8 +256,8 @@ func (s *APIServer) registerPodsHandlers(r *mux.Router) error {
// required: true
// description: the name or ID of the pod
// responses:
// 204:
// description: no error
// 200:
// $ref: '#/responses/PodUnpauseReport'
// 404:
// $ref: "#/responses/NoSuchPod"
// 500:

View File

@ -8,6 +8,7 @@ import (
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/bindings"
"github.com/containers/libpod/pkg/domain/entities"
)
func CreatePod() error {
@ -44,10 +45,13 @@ func Inspect(ctx context.Context, nameOrID string) (*libpod.PodInspect, error) {
// Kill sends a SIGTERM to all the containers in a pod. The optional signal parameter
// can be used to override SIGTERM.
func Kill(ctx context.Context, nameOrID string, signal *string) error {
func Kill(ctx context.Context, nameOrID string, signal *string) (*entities.PodKillReport, error) {
var (
report entities.PodKillReport
)
conn, err := bindings.GetClient(ctx)
if err != nil {
return err
return nil, err
}
params := url.Values{}
if signal != nil {
@ -55,22 +59,23 @@ func Kill(ctx context.Context, nameOrID string, signal *string) error {
}
response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/kill", params, nameOrID)
if err != nil {
return err
return nil, err
}
return response.Process(nil)
return &report, response.Process(&report)
}
// Pause pauses all running containers in a given pod.
func Pause(ctx context.Context, nameOrID string) error {
func Pause(ctx context.Context, nameOrID string) (*entities.PodPauseReport, error) {
var report entities.PodPauseReport
conn, err := bindings.GetClient(ctx)
if err != nil {
return err
return nil, err
}
response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/pause", nil, nameOrID)
if err != nil {
return err
return nil, err
}
return response.Process(nil)
return &report, response.Process(&report)
}
// Prune removes all non-running pods in local storage.
@ -88,9 +93,9 @@ func Prune(ctx context.Context) error {
// List returns all pods in local storage. The optional filters parameter can
// be used to refine which pods should be listed.
func List(ctx context.Context, filters map[string][]string) ([]*libpod.PodInspect, error) {
func List(ctx context.Context, filters map[string][]string) ([]*entities.ListPodsReport, error) {
var (
inspect []*libpod.PodInspect
podsReports []*entities.ListPodsReport
)
conn, err := bindings.GetClient(ctx)
if err != nil {
@ -106,30 +111,32 @@ func List(ctx context.Context, filters map[string][]string) ([]*libpod.PodInspec
}
response, err := conn.DoRequest(nil, http.MethodGet, "/pods/json", params)
if err != nil {
return inspect, err
return podsReports, err
}
return inspect, response.Process(&inspect)
return podsReports, response.Process(&podsReports)
}
// Restart restarts all containers in a pod.
func Restart(ctx context.Context, nameOrID string) error {
func Restart(ctx context.Context, nameOrID string) (*entities.PodRestartReport, error) {
var report entities.PodRestartReport
conn, err := bindings.GetClient(ctx)
if err != nil {
return err
return nil, err
}
response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/restart", nil, nameOrID)
if err != nil {
return err
return nil, err
}
return response.Process(nil)
return &report, response.Process(&report)
}
// Remove deletes a Pod from from local storage. The optional force parameter denotes
// that the Pod can be removed even if in a running state.
func Remove(ctx context.Context, nameOrID string, force *bool) error {
func Remove(ctx context.Context, nameOrID string, force *bool) (*entities.PodRmReport, error) {
var report entities.PodRmReport
conn, err := bindings.GetClient(ctx)
if err != nil {
return err
return nil, err
}
params := url.Values{}
if force != nil {
@ -137,22 +144,27 @@ func Remove(ctx context.Context, nameOrID string, force *bool) error {
}
response, err := conn.DoRequest(nil, http.MethodDelete, "/pods/%s", params, nameOrID)
if err != nil {
return err
return nil, err
}
return response.Process(nil)
return &report, response.Process(&report)
}
// Start starts all containers in a pod.
func Start(ctx context.Context, nameOrID string) error {
func Start(ctx context.Context, nameOrID string) (*entities.PodStartReport, error) {
var report entities.PodStartReport
conn, err := bindings.GetClient(ctx)
if err != nil {
return err
return nil, err
}
response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/start", nil, nameOrID)
if err != nil {
return err
return nil, err
}
return response.Process(nil)
if response.StatusCode == http.StatusNotModified {
report.Id = nameOrID
return &report, nil
}
return &report, response.Process(&report)
}
func Stats() error {
@ -162,10 +174,11 @@ func Stats() error {
// Stop stops all containers in a Pod. The optional timeout parameter can be
// used to override the timeout before the container is killed.
func Stop(ctx context.Context, nameOrID string, timeout *int) error {
func Stop(ctx context.Context, nameOrID string, timeout *int) (*entities.PodStopReport, error) {
var report entities.PodStopReport
conn, err := bindings.GetClient(ctx)
if err != nil {
return err
return nil, err
}
params := url.Values{}
if timeout != nil {
@ -173,9 +186,13 @@ func Stop(ctx context.Context, nameOrID string, timeout *int) error {
}
response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/stop", params, nameOrID)
if err != nil {
return err
return nil, err
}
return response.Process(nil)
if response.StatusCode == http.StatusNotModified {
report.Id = nameOrID
return &report, nil
}
return &report, response.Process(&report)
}
func Top() error {
@ -184,14 +201,15 @@ func Top() error {
}
// Unpause unpauses all paused containers in a Pod.
func Unpause(ctx context.Context, nameOrID string) error {
func Unpause(ctx context.Context, nameOrID string) (*entities.PodUnpauseReport, error) {
var report entities.PodUnpauseReport
conn, err := bindings.GetClient(ctx)
if err != nil {
return err
return nil, err
}
response, err := conn.DoRequest(nil, http.MethodPost, "/pods/%s/unpause", nil, nameOrID)
if err != nil {
return err
return nil, err
}
return response.Process(nil)
return &report, response.Process(&report)
}

View File

@ -71,7 +71,7 @@ var _ = Describe("Podman pods", func() {
Expect(len(podSummary)).To(Equal(2))
var names []string
for _, i := range podSummary {
names = append(names, i.Config.Name)
names = append(names, i.Name)
}
Expect(StringInSlice(newpod, names)).To(BeTrue())
Expect(StringInSlice("newpod2", names)).To(BeTrue())
@ -107,13 +107,14 @@ var _ = Describe("Podman pods", func() {
Expect(len(filteredPods)).To(BeNumerically("==", 1))
var names []string
for _, i := range filteredPods {
names = append(names, i.Config.Name)
names = append(names, i.Name)
}
Expect(StringInSlice("newpod2", names)).To(BeTrue())
// Validate list pod with id filter
filters = make(map[string][]string)
response, err := pods.Inspect(bt.conn, newpod)
Expect(err).To(BeNil())
id := response.Config.ID
filters["id"] = []string{id}
filteredPods, err = pods.List(bt.conn, filters)
@ -121,7 +122,7 @@ var _ = Describe("Podman pods", func() {
Expect(len(filteredPods)).To(BeNumerically("==", 1))
names = names[:0]
for _, i := range filteredPods {
names = append(names, i.Config.Name)
names = append(names, i.Name)
}
Expect(StringInSlice("newpod", names)).To(BeTrue())
@ -132,7 +133,7 @@ var _ = Describe("Podman pods", func() {
Expect(len(filteredPods)).To(BeNumerically("==", 1))
names = names[:0]
for _, i := range filteredPods {
names = append(names, i.Config.Name)
names = append(names, i.Name)
}
Expect(StringInSlice("newpod", names)).To(BeTrue())
})
@ -155,7 +156,7 @@ var _ = Describe("Podman pods", func() {
// TODO fix this
Skip("Pod behavior is jacked right now.")
// Pause invalid container
err := pods.Pause(bt.conn, "dummyName")
_, err := pods.Pause(bt.conn, "dummyName")
Expect(err).ToNot(BeNil())
code, _ := bindings.CheckResponseCode(err)
Expect(code).To(BeNumerically("==", http.StatusNotFound))
@ -167,9 +168,10 @@ var _ = Describe("Podman pods", func() {
// Binding needs to be modified to inspect the pod state.
// Since we don't have a pod state we inspect the states of the containers within the pod.
// Pause a valid container
err = pods.Pause(bt.conn, newpod)
_, err = pods.Pause(bt.conn, newpod)
Expect(err).To(BeNil())
response, err := pods.Inspect(bt.conn, newpod)
Expect(err).To(BeNil())
Expect(response.State.Status).To(Equal(define.PodStatePaused))
for _, i := range response.Containers {
Expect(define.StringToContainerStatus(i.State)).
@ -177,9 +179,10 @@ var _ = Describe("Podman pods", func() {
}
// Unpause a valid container
err = pods.Unpause(bt.conn, newpod)
_, err = pods.Unpause(bt.conn, newpod)
Expect(err).To(BeNil())
response, err = pods.Inspect(bt.conn, newpod)
Expect(err).To(BeNil())
Expect(response.State.Status).To(Equal(define.PodStateRunning))
for _, i := range response.Containers {
Expect(define.StringToContainerStatus(i.State)).
@ -189,28 +192,29 @@ var _ = Describe("Podman pods", func() {
It("start stop restart pod", func() {
// Start an invalid pod
err = pods.Start(bt.conn, "dummyName")
_, err = pods.Start(bt.conn, "dummyName")
Expect(err).ToNot(BeNil())
code, _ := bindings.CheckResponseCode(err)
Expect(code).To(BeNumerically("==", http.StatusNotFound))
// Stop an invalid pod
err = pods.Stop(bt.conn, "dummyName", nil)
_, err = pods.Stop(bt.conn, "dummyName", nil)
Expect(err).ToNot(BeNil())
code, _ = bindings.CheckResponseCode(err)
Expect(code).To(BeNumerically("==", http.StatusNotFound))
// Restart an invalid pod
err = pods.Restart(bt.conn, "dummyName")
_, err = pods.Restart(bt.conn, "dummyName")
Expect(err).ToNot(BeNil())
code, _ = bindings.CheckResponseCode(err)
Expect(code).To(BeNumerically("==", http.StatusNotFound))
// Start a valid pod and inspect status of each container
err = pods.Start(bt.conn, newpod)
_, err = pods.Start(bt.conn, newpod)
Expect(err).To(BeNil())
response, err := pods.Inspect(bt.conn, newpod)
Expect(err).To(BeNil())
Expect(response.State.Status).To(Equal(define.PodStateRunning))
for _, i := range response.Containers {
Expect(define.StringToContainerStatus(i.State)).
@ -218,11 +222,11 @@ var _ = Describe("Podman pods", func() {
}
// Start an already running pod
err = pods.Start(bt.conn, newpod)
_, err = pods.Start(bt.conn, newpod)
Expect(err).To(BeNil())
// Stop the running pods
err = pods.Stop(bt.conn, newpod, nil)
_, err = pods.Stop(bt.conn, newpod, nil)
Expect(err).To(BeNil())
response, _ = pods.Inspect(bt.conn, newpod)
Expect(response.State.Status).To(Equal(define.PodStateExited))
@ -232,10 +236,10 @@ var _ = Describe("Podman pods", func() {
}
// Stop an already stopped pod
err = pods.Stop(bt.conn, newpod, nil)
_, err = pods.Stop(bt.conn, newpod, nil)
Expect(err).To(BeNil())
err = pods.Restart(bt.conn, newpod)
_, err = pods.Restart(bt.conn, newpod)
Expect(err).To(BeNil())
response, _ = pods.Inspect(bt.conn, newpod)
Expect(response.State.Status).To(Equal(define.PodStateRunning))
@ -260,11 +264,12 @@ var _ = Describe("Podman pods", func() {
// Prune only one pod which is in exited state.
// Start then stop a pod.
// pod moves to exited state one pod should be pruned now.
err = pods.Start(bt.conn, newpod)
_, err = pods.Start(bt.conn, newpod)
Expect(err).To(BeNil())
err = pods.Stop(bt.conn, newpod, nil)
_, err = pods.Stop(bt.conn, newpod, nil)
Expect(err).To(BeNil())
response, err := pods.Inspect(bt.conn, newpod)
Expect(err).To(BeNil())
Expect(response.State.Status).To(Equal(define.PodStateExited))
err = pods.Prune(bt.conn)
Expect(err).To(BeNil())
@ -274,21 +279,23 @@ var _ = Describe("Podman pods", func() {
// Test prune all pods in exited state.
bt.Podcreate(&newpod)
err = pods.Start(bt.conn, newpod)
_, err = pods.Start(bt.conn, newpod)
Expect(err).To(BeNil())
err = pods.Start(bt.conn, newpod2)
_, err = pods.Start(bt.conn, newpod2)
Expect(err).To(BeNil())
err = pods.Stop(bt.conn, newpod, nil)
_, err = pods.Stop(bt.conn, newpod, nil)
Expect(err).To(BeNil())
response, err = pods.Inspect(bt.conn, newpod)
Expect(err).To(BeNil())
Expect(response.State.Status).To(Equal(define.PodStateExited))
for _, i := range response.Containers {
Expect(define.StringToContainerStatus(i.State)).
To(Equal(define.ContainerStateStopped))
}
err = pods.Stop(bt.conn, newpod2, nil)
_, err = pods.Stop(bt.conn, newpod2, nil)
Expect(err).To(BeNil())
response, err = pods.Inspect(bt.conn, newpod2)
Expect(err).To(BeNil())
Expect(response.State.Status).To(Equal(define.PodStateExited))
for _, i := range response.Containers {
Expect(define.StringToContainerStatus(i.State)).

View File

@ -14,6 +14,13 @@ type ContainerEngine interface {
ContainerStop(ctx context.Context, namesOrIds []string, options StopOptions) ([]*StopReport, error)
ContainerWait(ctx context.Context, namesOrIds []string, options WaitOptions) ([]WaitReport, error)
PodExists(ctx context.Context, nameOrId string) (*BoolReport, error)
PodKill(ctx context.Context, namesOrIds []string, options PodKillOptions) ([]*PodKillReport, error)
PodPause(ctx context.Context, namesOrIds []string, options PodPauseOptions) ([]*PodPauseReport, error)
PodRestart(ctx context.Context, namesOrIds []string, options PodRestartOptions) ([]*PodRestartReport, error)
PodStart(ctx context.Context, namesOrIds []string, options PodStartOptions) ([]*PodStartReport, error)
PodStop(ctx context.Context, namesOrIds []string, options PodStopOptions) ([]*PodStopReport, error)
PodRm(ctx context.Context, namesOrIds []string, options PodRmOptions) ([]*PodRmReport, error)
PodUnpause(ctx context.Context, namesOrIds []string, options PodunpauseOptions) ([]*PodUnpauseReport, error)
VolumeCreate(ctx context.Context, opts VolumeCreateOptions) (*IdOrNameResponse, error)
VolumeInspect(ctx context.Context, namesOrIds []string, opts VolumeInspectOptions) ([]*VolumeInspectReport, error)
VolumeRm(ctx context.Context, namesOrIds []string, opts VolumeRmOptions) ([]*VolumeRmReport, error)

View File

@ -0,0 +1,94 @@
package entities
import "time"
type PodKillOptions struct {
All bool
Latest bool
Signal string
}
type PodKillReport struct {
Errs []error
Id string
}
type ListPodsReport struct {
Cgroup string
Containers []*ListPodContainer
Created time.Time
Id string
Name string
Namespace string
Status string
}
type ListPodContainer struct {
Id string
Names string
Status string
}
type PodPauseOptions struct {
All bool
Latest bool
}
type PodPauseReport struct {
Errs []error
Id string
}
type PodunpauseOptions struct {
All bool
Latest bool
}
type PodUnpauseReport struct {
Errs []error
Id string
}
type PodStopOptions struct {
All bool
Ignore bool
Latest bool
Timeout int
}
type PodStopReport struct {
Errs []error
Id string
}
type PodRestartOptions struct {
All bool
Latest bool
}
type PodRestartReport struct {
Errs []error
Id string
}
type PodStartOptions struct {
All bool
Latest bool
}
type PodStartReport struct {
Errs []error
Id string
}
type PodRmOptions struct {
All bool
Force bool
Ignore bool
Latest bool
}
type PodRmReport struct {
Err error
Id string
}

View File

@ -46,7 +46,7 @@ func (ir *ImageEngine) Delete(ctx context.Context, nameOrId []string, opts entit
err = ir.deleteImage(ctx, img, opts, report)
report.Errors = append(report.Errors, err)
}
if len(targets) >= 0 || len(previousTargets) != 1 {
if len(previousTargets) != 1 {
goto repeatRun
}
return &report, nil
@ -83,9 +83,7 @@ func (ir *ImageEngine) deleteImage(ctx context.Context, img *libpodImage.Image,
}
report.Deleted = append(report.Deleted, results.Deleted)
for _, e := range results.Untagged {
report.Untagged = append(report.Untagged, e)
}
report.Untagged = append(report.Untagged, results.Untagged...)
return nil
}

View File

@ -5,11 +5,45 @@ package abi
import (
"context"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/signal"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
// getPodsByContext returns a slice of pods. Note that all, latest and pods are
// mutually exclusive arguments.
func getPodsByContext(all, latest bool, pods []string, runtime *libpod.Runtime) ([]*libpod.Pod, error) {
var outpods []*libpod.Pod
if all {
return runtime.GetAllPods()
}
if latest {
p, err := runtime.GetLatestPod()
if err != nil {
return nil, err
}
outpods = append(outpods, p)
return outpods, nil
}
var err error
for _, p := range pods {
pod, e := runtime.LookupPod(p)
if e != nil {
// Log all errors here, so callers don't need to.
logrus.Debugf("Error looking up pod %q: %v", p, e)
if err == nil {
err = e
}
} else {
outpods = append(outpods, pod)
}
}
return outpods, err
}
func (ic *ContainerEngine) PodExists(ctx context.Context, nameOrId string) (*entities.BoolReport, error) {
_, err := ic.Libpod.LookupPod(nameOrId)
if err != nil && errors.Cause(err) != define.ErrNoSuchPod {
@ -17,3 +51,191 @@ func (ic *ContainerEngine) PodExists(ctx context.Context, nameOrId string) (*ent
}
return &entities.BoolReport{Value: err == nil}, nil
}
func (ic *ContainerEngine) PodKill(ctx context.Context, namesOrIds []string, options entities.PodKillOptions) ([]*entities.PodKillReport, error) {
var (
reports []*entities.PodKillReport
)
sig, err := signal.ParseSignalNameOrNumber(options.Signal)
if err != nil {
return nil, err
}
pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
if err != nil {
return nil, err
}
for _, p := range pods {
report := entities.PodKillReport{Id: p.ID()}
conErrs, err := p.Kill(uint(sig))
if err != nil {
report.Errs = []error{err}
reports = append(reports, &report)
continue
}
if len(conErrs) > 0 {
for _, err := range conErrs {
report.Errs = append(report.Errs, err)
}
reports = append(reports, &report)
continue
}
reports = append(reports, &report)
}
return reports, nil
}
func (ic *ContainerEngine) PodPause(ctx context.Context, namesOrIds []string, options entities.PodPauseOptions) ([]*entities.PodPauseReport, error) {
var (
reports []*entities.PodPauseReport
)
pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
if err != nil {
return nil, err
}
for _, p := range pods {
report := entities.PodPauseReport{Id: p.ID()}
errs, err := p.Pause()
if err != nil {
report.Errs = []error{err}
continue
}
if len(errs) > 0 {
for _, v := range errs {
report.Errs = append(report.Errs, v)
}
reports = append(reports, &report)
continue
}
reports = append(reports, &report)
}
return reports, nil
}
func (ic *ContainerEngine) PodUnpause(ctx context.Context, namesOrIds []string, options entities.PodunpauseOptions) ([]*entities.PodUnpauseReport, error) {
var (
reports []*entities.PodUnpauseReport
)
pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
if err != nil {
return nil, err
}
for _, p := range pods {
report := entities.PodUnpauseReport{Id: p.ID()}
errs, err := p.Unpause()
if err != nil {
report.Errs = []error{err}
continue
}
if len(errs) > 0 {
for _, v := range errs {
report.Errs = append(report.Errs, v)
}
reports = append(reports, &report)
continue
}
reports = append(reports, &report)
}
return reports, nil
}
func (ic *ContainerEngine) PodStop(ctx context.Context, namesOrIds []string, options entities.PodStopOptions) ([]*entities.PodStopReport, error) {
var (
reports []*entities.PodStopReport
)
pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
if err != nil {
return nil, err
}
for _, p := range pods {
report := entities.PodStopReport{Id: p.ID()}
errs, err := p.StopWithTimeout(ctx, false, options.Timeout)
if err != nil {
report.Errs = []error{err}
continue
}
if len(errs) > 0 {
for _, v := range errs {
report.Errs = append(report.Errs, v)
}
reports = append(reports, &report)
continue
}
reports = append(reports, &report)
}
return reports, nil
}
func (ic *ContainerEngine) PodRestart(ctx context.Context, namesOrIds []string, options entities.PodRestartOptions) ([]*entities.PodRestartReport, error) {
var (
reports []*entities.PodRestartReport
)
pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
if err != nil {
return nil, err
}
for _, p := range pods {
report := entities.PodRestartReport{Id: p.ID()}
errs, err := p.Restart(ctx)
if err != nil {
report.Errs = []error{err}
continue
}
if len(errs) > 0 {
for _, v := range errs {
report.Errs = append(report.Errs, v)
}
reports = append(reports, &report)
continue
}
reports = append(reports, &report)
}
return reports, nil
}
func (ic *ContainerEngine) PodStart(ctx context.Context, namesOrIds []string, options entities.PodStartOptions) ([]*entities.PodStartReport, error) {
var (
reports []*entities.PodStartReport
)
pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
if err != nil {
return nil, err
}
for _, p := range pods {
report := entities.PodStartReport{Id: p.ID()}
errs, err := p.Start(ctx)
if err != nil {
report.Errs = []error{err}
continue
}
if len(errs) > 0 {
for _, v := range errs {
report.Errs = append(report.Errs, v)
}
reports = append(reports, &report)
continue
}
reports = append(reports, &report)
}
return reports, nil
}
func (ic *ContainerEngine) PodRm(ctx context.Context, namesOrIds []string, options entities.PodRmOptions) ([]*entities.PodRmReport, error) {
var (
reports []*entities.PodRmReport
)
pods, err := getPodsByContext(options.All, options.Latest, namesOrIds, ic.Libpod)
if err != nil {
return nil, err
}
for _, p := range pods {
report := entities.PodRmReport{Id: p.ID()}
err := ic.Libpod.RemovePod(ctx, p, true, options.Force)
if err != nil {
report.Err = err
continue
}
reports = append(reports, &report)
}
return reports, nil
}

View File

@ -4,9 +4,12 @@ import (
"context"
"strings"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/api/handlers/libpod"
"github.com/containers/libpod/pkg/bindings"
"github.com/containers/libpod/pkg/bindings/containers"
"github.com/containers/libpod/pkg/bindings/pods"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/util"
"github.com/pkg/errors"
)
@ -40,3 +43,34 @@ func getContainersByContext(contextWithConnection context.Context, all bool, nam
}
return cons, nil
}
func getPodsByContext(contextWithConnection context.Context, all bool, namesOrIds []string) ([]*entities.ListPodsReport, error) {
var (
sPods []*entities.ListPodsReport
)
if all && len(namesOrIds) > 0 {
return nil, errors.New("cannot lookup specific pods and all")
}
fPods, err := pods.List(contextWithConnection, nil)
if err != nil {
return nil, err
}
if all {
return fPods, nil
}
for _, nameOrId := range namesOrIds {
var found bool
for _, f := range fPods {
if f.Name == nameOrId || strings.HasPrefix(f.Id, nameOrId) {
sPods = append(sPods, f)
found = true
break
}
}
if !found {
return nil, errors.Wrapf(define.ErrNoSuchPod, "unable to find pod %q", nameOrId)
}
}
return sPods, nil
}

View File

@ -11,3 +11,162 @@ func (ic *ContainerEngine) PodExists(ctx context.Context, nameOrId string) (*ent
exists, err := pods.Exists(ic.ClientCxt, nameOrId)
return &entities.BoolReport{Value: exists}, err
}
func (ic *ContainerEngine) PodKill(ctx context.Context, namesOrIds []string, options entities.PodKillOptions) ([]*entities.PodKillReport, error) {
var (
reports []*entities.PodKillReport
)
foundPods, err := getPodsByContext(ic.ClientCxt, options.All, namesOrIds)
if err != nil {
return nil, err
}
for _, p := range foundPods {
response, err := pods.Kill(ic.ClientCxt, p.Id, &options.Signal)
if err != nil {
report := entities.PodKillReport{
Errs: []error{err},
Id: p.Id,
}
reports = append(reports, &report)
continue
}
reports = append(reports, response)
}
return reports, nil
}
func (ic *ContainerEngine) PodPause(ctx context.Context, namesOrIds []string, options entities.PodPauseOptions) ([]*entities.PodPauseReport, error) {
var (
reports []*entities.PodPauseReport
)
foundPods, err := getPodsByContext(ic.ClientCxt, options.All, namesOrIds)
if err != nil {
return nil, err
}
for _, p := range foundPods {
response, err := pods.Pause(ic.ClientCxt, p.Id)
if err != nil {
report := entities.PodPauseReport{
Errs: []error{err},
Id: p.Id,
}
reports = append(reports, &report)
continue
}
reports = append(reports, response)
}
return reports, nil
}
func (ic *ContainerEngine) PodUnpause(ctx context.Context, namesOrIds []string, options entities.PodunpauseOptions) ([]*entities.PodUnpauseReport, error) {
var (
reports []*entities.PodUnpauseReport
)
foundPods, err := getPodsByContext(ic.ClientCxt, options.All, namesOrIds)
if err != nil {
return nil, err
}
for _, p := range foundPods {
response, err := pods.Unpause(ic.ClientCxt, p.Id)
if err != nil {
report := entities.PodUnpauseReport{
Errs: []error{err},
Id: p.Id,
}
reports = append(reports, &report)
continue
}
reports = append(reports, response)
}
return reports, nil
}
func (ic *ContainerEngine) PodStop(ctx context.Context, namesOrIds []string, options entities.PodStopOptions) ([]*entities.PodStopReport, error) {
var (
reports []*entities.PodStopReport
timeout int = -1
)
foundPods, err := getPodsByContext(ic.ClientCxt, options.All, namesOrIds)
if err != nil {
return nil, err
}
if options.Timeout != -1 {
timeout = options.Timeout
}
for _, p := range foundPods {
response, err := pods.Stop(ic.ClientCxt, p.Id, &timeout)
if err != nil {
report := entities.PodStopReport{
Errs: []error{err},
Id: p.Id,
}
reports = append(reports, &report)
continue
}
reports = append(reports, response)
}
return reports, nil
}
func (ic *ContainerEngine) PodRestart(ctx context.Context, namesOrIds []string, options entities.PodRestartOptions) ([]*entities.PodRestartReport, error) {
var reports []*entities.PodRestartReport
foundPods, err := getPodsByContext(ic.ClientCxt, options.All, namesOrIds)
if err != nil {
return nil, err
}
for _, p := range foundPods {
response, err := pods.Restart(ic.ClientCxt, p.Id)
if err != nil {
report := entities.PodRestartReport{
Errs: []error{err},
Id: p.Id,
}
reports = append(reports, &report)
continue
}
reports = append(reports, response)
}
return reports, nil
}
func (ic *ContainerEngine) PodStart(ctx context.Context, namesOrIds []string, options entities.PodStartOptions) ([]*entities.PodStartReport, error) {
var reports []*entities.PodStartReport
foundPods, err := getPodsByContext(ic.ClientCxt, options.All, namesOrIds)
if err != nil {
return nil, err
}
for _, p := range foundPods {
response, err := pods.Start(ic.ClientCxt, p.Id)
if err != nil {
report := entities.PodStartReport{
Errs: []error{err},
Id: p.Id,
}
reports = append(reports, &report)
continue
}
reports = append(reports, response)
}
return reports, nil
}
func (ic *ContainerEngine) PodRm(ctx context.Context, namesOrIds []string, options entities.PodRmOptions) ([]*entities.PodRmReport, error) {
var reports []*entities.PodRmReport
foundPods, err := getPodsByContext(ic.ClientCxt, options.All, namesOrIds)
if err != nil {
return nil, err
}
for _, p := range foundPods {
response, err := pods.Remove(ic.ClientCxt, p.Id, &options.Force)
if err != nil {
report := entities.PodRmReport{
Err: err,
Id: p.Id,
}
reports = append(reports, &report)
continue
}
reports = append(reports, response)
}
return reports, nil
}

View File

@ -14,8 +14,8 @@ t GET libpod/pods/foo/json 200 \
.Config.id=$pod_id \
.Containers=null
t GET libpod/pods/json 200 \
.[0].Config.name=foo \
.[0].Config.id=$pod_id \
.[0].Name=foo \
.[0].Id=$pod_id \
.[0].Containers=null
# Cannot create a dup pod with the same name
@ -24,7 +24,7 @@ t POST libpod/pods/create name=foo 409 .cause="pod already exists"
#t POST libpod/pods/create a=b 400 .cause='bad parameter' # FIXME: unimplemented
if root || have_cgroupsv2; then
t POST libpod/pods/foo/pause '' 204
t POST libpod/pods/foo/pause '' 200
else
# Rootless cgroupsv1 : unsupported
t POST libpod/pods/foo/pause '' 500 \
@ -44,7 +44,7 @@ t POST libpod/pods/bar/restart '' 404
#t POST libpod/pods/prune 'a=b' 400 # FIXME: 2020-02-24 returns 200
# Clean up; and try twice, making sure that the second time fails
t DELETE libpod/pods/foo 204
t DELETE libpod/pods/foo 200
t DELETE libpod/pods/foo 404
# vim: filetype=sh