mirror of
https://github.com/containers/podman.git
synced 2025-06-15 22:04:32 +08:00
podmanv2 enable remote wait
enable remote container wait with condition Signed-off-by: Brent Baude <bbaude@redhat.com>
This commit is contained in:
@ -10,7 +10,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
containerExistsCommand = &cobra.Command{
|
containerExistsDescription = `If the named container exists in local storage, podman container exists exits with 0, otherwise the exit code will be 1.`
|
||||||
|
|
||||||
|
existsCommand = &cobra.Command{
|
||||||
Use: "exists CONTAINER",
|
Use: "exists CONTAINER",
|
||||||
Short: "Check if a container exists in local storage",
|
Short: "Check if a container exists in local storage",
|
||||||
Long: containerExistsDescription,
|
Long: containerExistsDescription,
|
||||||
@ -23,7 +25,7 @@ var (
|
|||||||
func init() {
|
func init() {
|
||||||
registry.Commands = append(registry.Commands, registry.CliCommand{
|
registry.Commands = append(registry.Commands, registry.CliCommand{
|
||||||
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
|
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
|
||||||
Command: containerExistsCommand,
|
Command: existsCommand,
|
||||||
Parent: containerCmd,
|
Parent: containerCmd,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -7,8 +7,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
containerExistsDescription = `If the named container exists in local storage, podman container exists exits with 0, otherwise the exit code will be 1.`
|
|
||||||
|
|
||||||
// podman container _inspect_
|
// podman container _inspect_
|
||||||
inspectCmd = &cobra.Command{
|
inspectCmd = &cobra.Command{
|
||||||
Use: "inspect [flags] CONTAINER",
|
Use: "inspect [flags] CONTAINER",
|
||||||
|
@ -6,6 +6,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containers/libpod/cmd/podmanV2/registry"
|
"github.com/containers/libpod/cmd/podmanV2/registry"
|
||||||
|
"github.com/containers/libpod/libpod/define"
|
||||||
"github.com/containers/libpod/pkg/domain/entities"
|
"github.com/containers/libpod/pkg/domain/entities"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
@ -25,7 +26,10 @@ var (
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
var waitFlags = entities.WaitOptions{}
|
var (
|
||||||
|
waitFlags = entities.WaitOptions{}
|
||||||
|
waitCondition string
|
||||||
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
registry.Commands = append(registry.Commands, registry.CliCommand{
|
registry.Commands = append(registry.Commands, registry.CliCommand{
|
||||||
@ -34,15 +38,20 @@ func init() {
|
|||||||
Parent: containerCmd,
|
Parent: containerCmd,
|
||||||
})
|
})
|
||||||
|
|
||||||
waitCommand.SetHelpTemplate(registry.HelpTemplate())
|
|
||||||
waitCommand.SetUsageTemplate(registry.UsageTemplate())
|
|
||||||
flags := waitCommand.Flags()
|
flags := waitCommand.Flags()
|
||||||
flags.DurationVarP(&waitFlags.Interval, "interval", "i", time.Duration(250), "Milliseconds to wait before polling for completion")
|
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.BoolVarP(&waitFlags.Latest, "latest", "l", false, "Act on the latest container podman is aware of")
|
||||||
flags.StringVar(&waitFlags.Condition, "condition", "stopped", "Condition to wait on")
|
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...
|
||||||
|
_ = flags.MarkHidden("latest")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func wait(cmd *cobra.Command, args []string) error {
|
func wait(cmd *cobra.Command, args []string) error {
|
||||||
|
var (
|
||||||
|
err error
|
||||||
|
)
|
||||||
if waitFlags.Latest && len(args) > 0 {
|
if waitFlags.Latest && len(args) > 0 {
|
||||||
return errors.New("cannot combine latest flag and arguments")
|
return errors.New("cannot combine latest flag and arguments")
|
||||||
}
|
}
|
||||||
@ -50,6 +59,11 @@ func wait(cmd *cobra.Command, args []string) error {
|
|||||||
return errors.New("interval must be greater then 0")
|
return errors.New("interval must be greater then 0")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
waitFlags.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, waitFlags)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -25,7 +25,7 @@ func init() {
|
|||||||
var dummyVersion bool
|
var dummyVersion bool
|
||||||
rootCmd.PersistentFlags().BoolVarP(&dummyVersion, "version", "v", false, "Version of podman")
|
rootCmd.PersistentFlags().BoolVarP(&dummyVersion, "version", "v", false, "Version of podman")
|
||||||
rootCmd.PersistentFlags().StringVarP(®istry.EngineOpts.Uri, "remote", "r", "", "URL to access podman service")
|
rootCmd.PersistentFlags().StringVarP(®istry.EngineOpts.Uri, "remote", "r", "", "URL to access podman service")
|
||||||
rootCmd.PersistentFlags().StringSliceVarP(®istry.EngineOpts.Identities, "identity", "i", []string{}, "path to SSH identity file")
|
rootCmd.PersistentFlags().StringSliceVar(®istry.EngineOpts.Identities, "identity", []string{}, "path to SSH identity file")
|
||||||
}
|
}
|
||||||
|
|
||||||
func Execute() {
|
func Execute() {
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/containers/libpod/libpod"
|
"github.com/containers/libpod/libpod"
|
||||||
|
"github.com/containers/libpod/libpod/define"
|
||||||
lpapiv2 "github.com/containers/libpod/pkg/api/handlers/libpod"
|
lpapiv2 "github.com/containers/libpod/pkg/api/handlers/libpod"
|
||||||
"github.com/containers/libpod/pkg/bindings"
|
"github.com/containers/libpod/pkg/bindings"
|
||||||
)
|
)
|
||||||
@ -212,7 +213,7 @@ func Unpause(ctx context.Context, nameOrID string) error {
|
|||||||
// Wait blocks until the given container reaches a condition. If not provided, the condition will
|
// Wait blocks until the given container reaches a condition. If not provided, the condition will
|
||||||
// default to stopped. If the condition is stopped, an exit code for the container will be provided. The
|
// default to stopped. If the condition is stopped, an exit code for the container will be provided. The
|
||||||
// nameOrID can be a container name or a partial/full ID.
|
// nameOrID can be a container name or a partial/full ID.
|
||||||
func Wait(ctx context.Context, nameOrID string, condition *string) (int32, error) {
|
func Wait(ctx context.Context, nameOrID string, condition *define.ContainerStatus) (int32, error) { //nolint
|
||||||
var exitCode int32
|
var exitCode int32
|
||||||
conn, err := bindings.GetClient(ctx)
|
conn, err := bindings.GetClient(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -220,7 +221,7 @@ func Wait(ctx context.Context, nameOrID string, condition *string) (int32, error
|
|||||||
}
|
}
|
||||||
params := url.Values{}
|
params := url.Values{}
|
||||||
if condition != nil {
|
if condition != nil {
|
||||||
params.Set("condition", *condition)
|
params.Set("condition", condition.String())
|
||||||
}
|
}
|
||||||
response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/wait", params, nameOrID)
|
response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/wait", params, nameOrID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -3,6 +3,7 @@ package test_bindings
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/containers/libpod/libpod/define"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@ -205,8 +206,8 @@ func (b *bindingTest) RunTopContainer(containerName *string, insidePod *bool, po
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
waiting := "running"
|
wait := define.ContainerStateRunning
|
||||||
_, err = containers.Wait(b.conn, ctr.ID, &waiting)
|
_, err = containers.Wait(b.conn, ctr.ID, &wait)
|
||||||
return ctr.ID, err
|
return ctr.ID, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package test_bindings
|
package test_bindings
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/containers/libpod/libpod/define"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -282,8 +283,8 @@ var _ = Describe("Podman containers ", func() {
|
|||||||
var (
|
var (
|
||||||
name = "top"
|
name = "top"
|
||||||
exitCode int32 = -1
|
exitCode int32 = -1
|
||||||
pause = "paused"
|
pause = define.ContainerStatePaused
|
||||||
unpause = "running"
|
running = define.ContainerStateRunning
|
||||||
)
|
)
|
||||||
errChan := make(chan error)
|
errChan := make(chan error)
|
||||||
_, err := bt.RunTopContainer(&name, nil, nil)
|
_, err := bt.RunTopContainer(&name, nil, nil)
|
||||||
@ -301,7 +302,7 @@ var _ = Describe("Podman containers ", func() {
|
|||||||
|
|
||||||
errChan = make(chan error)
|
errChan = make(chan error)
|
||||||
go func() {
|
go func() {
|
||||||
_, waitErr := containers.Wait(bt.conn, name, &unpause)
|
_, waitErr := containers.Wait(bt.conn, name, &running)
|
||||||
errChan <- waitErr
|
errChan <- waitErr
|
||||||
close(errChan)
|
close(errChan)
|
||||||
}()
|
}()
|
||||||
|
@ -81,7 +81,7 @@ var _ = Describe("Podman pods", func() {
|
|||||||
It("List pods with filters", func() {
|
It("List pods with filters", func() {
|
||||||
var newpod2 string = "newpod2"
|
var newpod2 string = "newpod2"
|
||||||
bt.Podcreate(&newpod2)
|
bt.Podcreate(&newpod2)
|
||||||
_, err = bt.RunTopContainer(nil, &trueFlag, &newpod)
|
_, err = bt.RunTopContainer(nil, &bindings.PTrue, &newpod)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
|
|
||||||
// Expected err with invalid filter params
|
// Expected err with invalid filter params
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
package entities
|
package entities
|
||||||
|
|
||||||
import "time"
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/containers/libpod/libpod/define"
|
||||||
|
)
|
||||||
|
|
||||||
type WaitOptions struct {
|
type WaitOptions struct {
|
||||||
Condition string
|
Condition define.ContainerStatus
|
||||||
Interval time.Duration
|
Interval time.Duration
|
||||||
Latest bool
|
Latest bool
|
||||||
}
|
}
|
||||||
|
@ -24,18 +24,13 @@ func (ic *ContainerEngine) ContainerWait(ctx context.Context, namesOrIds []strin
|
|||||||
var (
|
var (
|
||||||
responses []entities.WaitReport
|
responses []entities.WaitReport
|
||||||
)
|
)
|
||||||
condition, err := define.StringToContainerStatus(options.Condition)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
ctrs, err := shortcuts.GetContainersByContext(false, options.Latest, namesOrIds, ic.Libpod)
|
ctrs, err := shortcuts.GetContainersByContext(false, options.Latest, namesOrIds, ic.Libpod)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, c := range ctrs {
|
for _, c := range ctrs {
|
||||||
response := entities.WaitReport{Id: c.ID()}
|
response := entities.WaitReport{Id: c.ID()}
|
||||||
exitCode, err := c.WaitForConditionWithInterval(options.Interval, condition)
|
exitCode, err := c.WaitForConditionWithInterval(options.Interval, options.Condition)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
response.Error = err
|
response.Error = err
|
||||||
} else {
|
} else {
|
||||||
|
@ -13,7 +13,24 @@ func (ic *ContainerEngine) ContainerExists(ctx context.Context, nameOrId string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ic *ContainerEngine) ContainerWait(ctx context.Context, namesOrIds []string, options entities.WaitOptions) ([]entities.WaitReport, error) {
|
func (ic *ContainerEngine) ContainerWait(ctx context.Context, namesOrIds []string, options entities.WaitOptions) ([]entities.WaitReport, error) {
|
||||||
return nil, nil
|
var (
|
||||||
|
responses []entities.WaitReport
|
||||||
|
)
|
||||||
|
cons, err := getContainersByContext(ic.ClientCxt, false, namesOrIds)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
for _, c := range cons {
|
||||||
|
response := entities.WaitReport{Id: c.ID}
|
||||||
|
exitCode, err := containers.Wait(ic.ClientCxt, c.ID, &options.Condition)
|
||||||
|
if err != nil {
|
||||||
|
response.Error = err
|
||||||
|
} else {
|
||||||
|
response.ExitCode = exitCode
|
||||||
|
}
|
||||||
|
responses = append(responses, response)
|
||||||
|
}
|
||||||
|
return responses, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ContainerEngine) ContainerDelete(ctx context.Context, opts entities.ContainerDeleteOptions) (*entities.ContainerDeleteReport, error) {
|
func (r *ContainerEngine) ContainerDelete(ctx context.Context, opts entities.ContainerDeleteOptions) (*entities.ContainerDeleteReport, error) {
|
||||||
|
41
pkg/domain/infra/tunnel/helpers.go
Normal file
41
pkg/domain/infra/tunnel/helpers.go
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
package tunnel
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"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/util"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func getContainersByContext(contextWithConnection context.Context, all bool, namesOrIds []string) ([]libpod.ListContainer, error) {
|
||||||
|
var (
|
||||||
|
cons []libpod.ListContainer
|
||||||
|
)
|
||||||
|
if all && len(namesOrIds) > 0 {
|
||||||
|
return nil, errors.New("cannot lookup containers and all")
|
||||||
|
}
|
||||||
|
c, err := containers.List(contextWithConnection, nil, &bindings.PTrue, nil, nil, nil, &bindings.PTrue)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if all {
|
||||||
|
return c, err
|
||||||
|
}
|
||||||
|
for _, id := range namesOrIds {
|
||||||
|
var found bool
|
||||||
|
for _, con := range c {
|
||||||
|
if id == con.ID || util.StringInSlice(id, con.Names) {
|
||||||
|
cons = append(cons, con)
|
||||||
|
found = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !found {
|
||||||
|
return nil, errors.Errorf("unable to find container %q", id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cons, nil
|
||||||
|
}
|
Reference in New Issue
Block a user