Merge pull request #5571 from baude/v2exists

podmanv2 container exists|wait
This commit is contained in:
OpenShift Merge Robot 2020-03-20 22:22:20 +01:00 committed by GitHub
commit 7a095af92a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 370 additions and 117 deletions

1
.gitignore vendored
View file

@ -29,3 +29,4 @@ podman*.tar.gz
contrib/spec/podman.spec
*.rpm
*.coverprofile
/cmd/podmanV2/podmanV2

View file

@ -0,0 +1,42 @@
package containers
import (
"context"
"os"
"github.com/containers/libpod/cmd/podmanV2/registry"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/spf13/cobra"
)
var (
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",
Short: "Check if a container exists in local storage",
Long: containerExistsDescription,
Example: `podman container exists containerID
podman container exists myctr || podman run --name myctr [etc...]`,
RunE: exists,
}
)
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Mode: []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
Command: existsCommand,
Parent: containerCmd,
})
}
func exists(cmd *cobra.Command, args []string) error {
response, err := registry.ContainerEngine().ContainerExists(context.Background(), args[0])
if err != nil {
return err
}
if !response.Value {
os.Exit(1)
}
return nil
}

View file

@ -0,0 +1,82 @@
package containers
import (
"context"
"fmt"
"time"
"github.com/containers/libpod/cmd/podmanV2/registry"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
var (
waitDescription = `Block until one or more containers stop and then print their exit codes.
`
waitCommand = &cobra.Command{
Use: "wait [flags] CONTAINER [CONTAINER...]",
Short: "Block on one or more containers",
Long: waitDescription,
RunE: wait,
Example: `podman wait --latest
podman wait --interval 5000 ctrID
podman wait ctrID1 ctrID2`,
}
)
var (
waitFlags = entities.WaitOptions{}
waitCondition string
)
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.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 {
var (
err error
)
if waitFlags.Latest && len(args) > 0 {
return errors.New("cannot combine latest flag and arguments")
}
if waitFlags.Interval == 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)
if err != nil {
return err
}
for _, r := range responses {
if r.Error == nil {
fmt.Println(r.Id)
}
}
for _, r := range responses {
if r.Error != nil {
fmt.Println(err)
}
}
return nil
}

View file

@ -52,7 +52,7 @@ func init() {
flags.BoolVarP(&inspectOpts.Size, "size", "s", false, "Display total file size")
flags.StringVarP(&inspectOpts.Format, "format", "f", "", "Change the output format to a Go template")
if registry.GlobalFlags.EngineMode == entities.ABIMode {
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")
}

View file

@ -5,6 +5,7 @@ import (
"os"
"reflect"
"runtime"
"strings"
_ "github.com/containers/libpod/cmd/podmanV2/containers"
_ "github.com/containers/libpod/cmd/podmanV2/images"
@ -31,17 +32,19 @@ func initCobra() {
case "darwin":
fallthrough
case "windows":
registry.GlobalFlags.EngineMode = entities.TunnelMode
registry.EngineOpts.EngineMode = entities.TunnelMode
case "linux":
registry.GlobalFlags.EngineMode = entities.ABIMode
registry.EngineOpts.EngineMode = entities.ABIMode
default:
logrus.Errorf("%s is not a supported OS", runtime.GOOS)
os.Exit(1)
}
// TODO: Is there a Cobra way to "peek" at os.Args?
if ok := Contains("--remote", os.Args); ok {
registry.GlobalFlags.EngineMode = entities.TunnelMode
for _, v := range os.Args {
if strings.HasPrefix(v, "--remote") {
registry.EngineOpts.EngineMode = entities.TunnelMode
}
}
cobra.OnInitialize(func() {})
@ -50,7 +53,7 @@ func initCobra() {
func main() {
fmt.Fprintf(os.Stderr, "Number of commands: %d\n", len(registry.Commands))
for _, c := range registry.Commands {
if Contains(registry.GlobalFlags.EngineMode, c.Mode) {
if Contains(registry.EngineOpts.EngineMode, c.Mode) {
parent := rootCmd
if c.Parent != nil {
parent = c.Parent

View file

@ -14,11 +14,13 @@ type CliCommand struct {
}
var (
Commands []CliCommand
GlobalFlags entities.EngineFlags
Commands []CliCommand
imageEngine entities.ImageEngine
containerEngine entities.ContainerEngine
PodmanTunnel bool
EngineOpts entities.EngineOptions
GlobalFlags entities.EngineFlags
)
// HelpTemplate returns the help template for podman commands
@ -63,7 +65,8 @@ func ImageEngine() entities.ImageEngine {
// NewImageEngine is a wrapper for building an ImageEngine to be used for PreRunE functions
func NewImageEngine(cmd *cobra.Command, args []string) (entities.ImageEngine, error) {
if imageEngine == nil {
engine, err := infra.NewImageEngine(GlobalFlags.EngineMode, entities.EngineOptions{})
EngineOpts.FlagSet = cmd.Flags()
engine, err := infra.NewImageEngine(EngineOpts)
if err != nil {
return nil, err
}
@ -79,7 +82,8 @@ func ContainerEngine() entities.ContainerEngine {
// NewContainerEngine is a wrapper for building an ContainerEngine to be used for PreRunE functions
func NewContainerEngine(cmd *cobra.Command, args []string) (entities.ContainerEngine, error) {
if containerEngine == nil {
engine, err := infra.NewContainerEngine(GlobalFlags.EngineMode, entities.EngineOptions{})
EngineOpts.FlagSet = cmd.Flags()
engine, err := infra.NewContainerEngine(EngineOpts)
if err != nil {
return nil, err
}

View file

@ -24,7 +24,8 @@ 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().BoolVarP(&registry.PodmanTunnel, "remote", "r", false, "Access service via SSH tunnel")
rootCmd.PersistentFlags().StringVarP(&registry.EngineOpts.Uri, "remote", "r", "", "URL to access podman service")
rootCmd.PersistentFlags().StringSliceVar(&registry.EngineOpts.Identities, "identity", []string{}, "path to SSH identity file")
}
func Execute() {

View file

@ -21,8 +21,12 @@ func ContainerExists(w http.ResponseWriter, r *http.Request) {
name := utils.GetName(r)
_, err := runtime.LookupContainer(name)
if err != nil {
utils.ContainerNotFound(w, name, err)
if errors.Cause(err) == define.ErrNoSuchCtr {
utils.ContainerNotFound(w, name, err)
}
utils.InternalServerError(w, err)
return
}
utils.WriteResponse(w, http.StatusNoContent, "")
}

View file

@ -165,8 +165,13 @@ func sshClient(_url *url.URL, identity string, secure bool) (*http.Client, error
}
}
port := _url.Port()
if port == "" {
port = "22"
}
bastion, err := ssh.Dial("tcp",
net.JoinHostPort(_url.Hostname(), _url.Port()),
net.JoinHostPort(_url.Hostname(), port),
&ssh.ClientConfig{
User: _url.User.Username(),
Auth: []ssh.AuthMethod{auth},

View file

@ -7,6 +7,7 @@ import (
"strconv"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/libpod/define"
lpapiv2 "github.com/containers/libpod/pkg/api/handlers/libpod"
"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
// 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.
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
conn, err := bindings.GetClient(ctx)
if err != nil {
@ -220,7 +221,7 @@ func Wait(ctx context.Context, nameOrID string, condition *string) (int32, error
}
params := url.Values{}
if condition != nil {
params.Set("condition", *condition)
params.Set("condition", condition.String())
}
response, err := conn.DoRequest(nil, http.MethodPost, "/containers/%s/wait", params, nameOrID)
if err != nil {

View file

@ -3,6 +3,7 @@ package test_bindings
import (
"context"
"fmt"
"github.com/containers/libpod/libpod/define"
"io/ioutil"
"os"
"os/exec"
@ -205,8 +206,8 @@ func (b *bindingTest) RunTopContainer(containerName *string, insidePod *bool, po
if err != nil {
return "", err
}
waiting := "running"
_, err = containers.Wait(b.conn, ctr.ID, &waiting)
wait := define.ContainerStateRunning
_, err = containers.Wait(b.conn, ctr.ID, &wait)
return ctr.ID, err
}

View file

@ -1,6 +1,7 @@
package test_bindings
import (
"github.com/containers/libpod/libpod/define"
"net/http"
"strconv"
"strings"
@ -282,8 +283,8 @@ var _ = Describe("Podman containers ", func() {
var (
name = "top"
exitCode int32 = -1
pause = "paused"
unpause = "running"
pause = define.ContainerStatePaused
running = define.ContainerStateRunning
)
errChan := make(chan error)
_, err := bt.RunTopContainer(&name, nil, nil)
@ -301,7 +302,7 @@ var _ = Describe("Podman containers ", func() {
errChan = make(chan error)
go func() {
_, waitErr := containers.Wait(bt.conn, name, &unpause)
_, waitErr := containers.Wait(bt.conn, name, &running)
errChan <- waitErr
close(errChan)
}()

View file

@ -1 +1,23 @@
package entities
import (
"time"
"github.com/containers/libpod/libpod/define"
)
type WaitOptions struct {
Condition define.ContainerStatus
Interval time.Duration
Latest bool
}
type WaitReport struct {
Id string
Error error
ExitCode int32
}
type BoolReport struct {
Value bool
}

View file

@ -1,7 +1,6 @@
package entities
import (
"net/url"
"os/user"
"path/filepath"
@ -20,11 +19,13 @@ func (m EngineMode) String() string {
return string(m)
}
// FIXME: merge EngineOptions and EngineFlags
type EngineOptions struct {
Uri *url.URL
Uri string
Identities []string
FlagSet pflag.FlagSet
FlagSet *pflag.FlagSet
Flags EngineFlags
EngineMode EngineMode
}
type EngineFlags struct {
@ -58,8 +59,6 @@ type EngineFlags struct {
Port int
IdentityFile string
IgnoreHosts bool
EngineMode EngineMode
}
func NewEngineOptions() (EngineFlags, error) {

View file

@ -5,22 +5,12 @@ import (
)
type ContainerEngine interface {
ContainerRuntime
PodRuntime
VolumeRuntime
}
type ContainerRuntime interface {
ContainerDelete(ctx context.Context, opts ContainerDeleteOptions) (*ContainerDeleteReport, error)
ContainerPrune(ctx context.Context) (*ContainerPruneReport, error)
}
type PodRuntime interface {
ContainerExists(ctx context.Context, nameOrId string) (*BoolReport, error)
ContainerWait(ctx context.Context, namesOrIds []string, options WaitOptions) ([]WaitReport, error)
PodDelete(ctx context.Context, opts PodPruneOptions) (*PodDeleteReport, error)
PodPrune(ctx context.Context) (*PodPruneReport, error)
}
type VolumeRuntime interface {
VolumeDelete(ctx context.Context, opts VolumeDeleteOptions) (*VolumeDeleteReport, error)
VolumePrune(ctx context.Context) (*VolumePruneReport, error)
}

View file

@ -0,0 +1,66 @@
// +build ABISupport
package abi
import (
"context"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/adapter/shortcuts"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/pkg/errors"
)
// TODO: Should return *entities.ContainerExistsReport, error
func (ic *ContainerEngine) ContainerExists(ctx context.Context, nameOrId string) (*entities.BoolReport, error) {
_, err := ic.Libpod.LookupContainer(nameOrId)
if err != nil && errors.Cause(err) != define.ErrNoSuchCtr {
return nil, err
}
return &entities.BoolReport{Value: err == nil}, nil
}
func (ic *ContainerEngine) ContainerWait(ctx context.Context, namesOrIds []string, options entities.WaitOptions) ([]entities.WaitReport, error) {
var (
responses []entities.WaitReport
)
ctrs, err := shortcuts.GetContainersByContext(false, options.Latest, namesOrIds, ic.Libpod)
if err != nil {
return nil, err
}
for _, c := range ctrs {
response := entities.WaitReport{Id: c.ID()}
exitCode, err := c.WaitForConditionWithInterval(options.Interval, options.Condition)
if err != nil {
response.Error = err
} else {
response.ExitCode = exitCode
}
responses = append(responses, response)
}
return responses, nil
}
func (ic *ContainerEngine) ContainerDelete(ctx context.Context, opts entities.ContainerDeleteOptions) (*entities.ContainerDeleteReport, error) {
panic("implement me")
}
func (ic *ContainerEngine) ContainerPrune(ctx context.Context) (*entities.ContainerPruneReport, error) {
panic("implement me")
}
func (ic *ContainerEngine) PodDelete(ctx context.Context, opts entities.PodPruneOptions) (*entities.PodDeleteReport, error) {
panic("implement me")
}
func (ic *ContainerEngine) PodPrune(ctx context.Context) (*entities.PodPruneReport, error) {
panic("implement me")
}
func (ic *ContainerEngine) VolumeDelete(ctx context.Context, opts entities.VolumeDeleteOptions) (*entities.VolumeDeleteReport, error) {
panic("implement me")
}
func (ic *ContainerEngine) VolumePrune(ctx context.Context) (*entities.VolumePruneReport, error) {
panic("implement me")
}

View file

@ -4,7 +4,6 @@ package abi
import (
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/domain/entities"
)
// Image-related runtime linked against libpod library
@ -14,6 +13,5 @@ type ImageEngine struct {
// Container-related runtime linked against libpod library
type ContainerEngine struct {
entities.ContainerEngine
Libpod *libpod.Runtime
}

View file

@ -8,32 +8,31 @@ import (
"github.com/containers/libpod/pkg/bindings"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/domain/infra/abi"
"github.com/containers/libpod/pkg/domain/infra/tunnel"
)
// NewContainerEngine factory provides a libpod runtime for container-related operations
func NewContainerEngine(mode entities.EngineMode, opts entities.EngineOptions) (entities.ContainerEngine, error) {
switch mode {
func NewContainerEngine(opts entities.EngineOptions) (entities.ContainerEngine, error) {
switch opts.EngineMode {
case entities.ABIMode:
r, err := NewLibpodRuntime(opts.FlagSet, opts.Flags)
return &abi.ContainerEngine{ContainerEngine: r}, err
return r, err
case entities.TunnelMode:
ctx, err := bindings.NewConnection(context.Background(), opts.Uri.String(), opts.Identities...)
ctx, err := bindings.NewConnection(context.Background(), opts.Uri, opts.Identities...)
return &tunnel.ContainerEngine{ClientCxt: ctx}, err
}
return nil, fmt.Errorf("runtime mode '%v' is not supported", mode)
return nil, fmt.Errorf("runtime mode '%v' is not supported", opts.EngineMode)
}
// NewContainerEngine factory provides a libpod runtime for image-related operations
func NewImageEngine(mode entities.EngineMode, opts entities.EngineOptions) (entities.ImageEngine, error) {
switch mode {
func NewImageEngine(opts entities.EngineOptions) (entities.ImageEngine, error) {
switch opts.EngineMode {
case entities.ABIMode:
r, err := NewLibpodImageRuntime(opts.FlagSet, opts.Flags)
return r, err
case entities.TunnelMode:
ctx, err := bindings.NewConnection(context.Background(), opts.Uri.String(), opts.Identities...)
ctx, err := bindings.NewConnection(context.Background(), opts.Uri, opts.Identities...)
return &tunnel.ImageEngine{ClientCxt: ctx}, err
}
return nil, fmt.Errorf("runtime mode '%v' is not supported", mode)
return nil, fmt.Errorf("runtime mode '%v' is not supported", opts.EngineMode)
}

View file

@ -12,14 +12,10 @@ import (
// ContainerEngine Image Proxy will be EOL'ed after podmanV2 is separated from libpod repo
func NewLibpodImageRuntime(flags pflag.FlagSet, opts entities.EngineFlags) (entities.ImageEngine, error) {
func NewLibpodImageRuntime(flags *pflag.FlagSet, opts entities.EngineFlags) (entities.ImageEngine, error) {
r, err := GetRuntime(context.Background(), flags, opts)
if err != nil {
return nil, err
}
return &abi.ImageEngine{Libpod: r}, nil
}
func (ir *runtime) ShutdownImageRuntime(force bool) error {
return ir.Libpod.Shutdown(force)
}

View file

@ -26,7 +26,7 @@ type engineOpts struct {
}
// GetRuntimeMigrate gets a libpod runtime that will perform a migration of existing containers
func GetRuntimeMigrate(ctx context.Context, fs flag.FlagSet, ef entities.EngineFlags, newRuntime string) (*libpod.Runtime, error) {
func GetRuntimeMigrate(ctx context.Context, fs *flag.FlagSet, ef entities.EngineFlags, newRuntime string) (*libpod.Runtime, error) {
return getRuntime(ctx, fs, &engineOpts{
name: newRuntime,
renumber: false,
@ -38,7 +38,7 @@ func GetRuntimeMigrate(ctx context.Context, fs flag.FlagSet, ef entities.EngineF
}
// GetRuntimeDisableFDs gets a libpod runtime that will disable sd notify
func GetRuntimeDisableFDs(ctx context.Context, fs flag.FlagSet, ef entities.EngineFlags) (*libpod.Runtime, error) {
func GetRuntimeDisableFDs(ctx context.Context, fs *flag.FlagSet, ef entities.EngineFlags) (*libpod.Runtime, error) {
return getRuntime(ctx, fs, &engineOpts{
renumber: false,
migrate: false,
@ -49,7 +49,7 @@ func GetRuntimeDisableFDs(ctx context.Context, fs flag.FlagSet, ef entities.Engi
}
// GetRuntimeRenumber gets a libpod runtime that will perform a lock renumber
func GetRuntimeRenumber(ctx context.Context, fs flag.FlagSet, ef entities.EngineFlags) (*libpod.Runtime, error) {
func GetRuntimeRenumber(ctx context.Context, fs *flag.FlagSet, ef entities.EngineFlags) (*libpod.Runtime, error) {
return getRuntime(ctx, fs, &engineOpts{
renumber: true,
migrate: false,
@ -60,7 +60,7 @@ func GetRuntimeRenumber(ctx context.Context, fs flag.FlagSet, ef entities.Engine
}
// GetRuntime generates a new libpod runtime configured by command line options
func GetRuntime(ctx context.Context, flags flag.FlagSet, ef entities.EngineFlags) (*libpod.Runtime, error) {
func GetRuntime(ctx context.Context, flags *flag.FlagSet, ef entities.EngineFlags) (*libpod.Runtime, error) {
return getRuntime(ctx, flags, &engineOpts{
renumber: false,
migrate: false,
@ -71,7 +71,7 @@ func GetRuntime(ctx context.Context, flags flag.FlagSet, ef entities.EngineFlags
}
// GetRuntimeNoStore generates a new libpod runtime configured by command line options
func GetRuntimeNoStore(ctx context.Context, fs flag.FlagSet, ef entities.EngineFlags) (*libpod.Runtime, error) {
func GetRuntimeNoStore(ctx context.Context, fs *flag.FlagSet, ef entities.EngineFlags) (*libpod.Runtime, error) {
return getRuntime(ctx, fs, &engineOpts{
renumber: false,
migrate: false,
@ -81,7 +81,7 @@ func GetRuntimeNoStore(ctx context.Context, fs flag.FlagSet, ef entities.EngineF
})
}
func getRuntime(ctx context.Context, fs flag.FlagSet, opts *engineOpts) (*libpod.Runtime, error) {
func getRuntime(ctx context.Context, fs *flag.FlagSet, opts *engineOpts) (*libpod.Runtime, error) {
options := []libpod.RuntimeOption{}
storageOpts := storage.StoreOptions{}
storageSet := false

View file

@ -5,50 +5,17 @@ package infra
import (
"context"
"github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/domain/entities"
"github.com/containers/libpod/pkg/domain/infra/abi"
flag "github.com/spf13/pflag"
)
// ContainerEngine Proxy will be EOL'ed after podmanV2 is separated from libpod repo
type runtime struct {
entities.ContainerEngine
Libpod *libpod.Runtime
}
func NewLibpodRuntime(flags flag.FlagSet, opts entities.EngineFlags) (entities.ContainerEngine, error) {
func NewLibpodRuntime(flags *flag.FlagSet, opts entities.EngineFlags) (entities.ContainerEngine, error) {
r, err := GetRuntime(context.Background(), flags, opts)
if err != nil {
return nil, err
}
return &runtime{Libpod: r}, nil
}
func (r *runtime) ShutdownRuntime(force bool) error {
return r.Libpod.Shutdown(force)
}
func (r *runtime) ContainerDelete(ctx context.Context, opts entities.ContainerDeleteOptions) (*entities.ContainerDeleteReport, error) {
panic("implement me")
}
func (r *runtime) ContainerPrune(ctx context.Context) (*entities.ContainerPruneReport, error) {
panic("implement me")
}
func (r *runtime) PodDelete(ctx context.Context, opts entities.PodPruneOptions) (*entities.PodDeleteReport, error) {
panic("implement me")
}
func (r *runtime) PodPrune(ctx context.Context) (*entities.PodPruneReport, error) {
panic("implement me")
}
func (r *runtime) VolumeDelete(ctx context.Context, opts entities.VolumeDeleteOptions) (*entities.VolumeDeleteReport, error) {
panic("implement me")
}
func (r *runtime) VolumePrune(ctx context.Context) (*entities.VolumePruneReport, error) {
panic("implement me")
return &abi.ContainerEngine{Libpod: r}, nil
}

View file

@ -11,25 +11,25 @@ import (
"github.com/containers/libpod/pkg/domain/infra/tunnel"
)
func NewContainerEngine(mode entities.EngineMode, opts entities.EngineOptions) (entities.ContainerEngine, error) {
switch mode {
func NewContainerEngine(opts entities.EngineOptions) (entities.ContainerEngine, error) {
switch opts.EngineMode {
case entities.ABIMode:
return nil, fmt.Errorf("direct runtime not supported")
case entities.TunnelMode:
ctx, err := bindings.NewConnection(context.Background(), opts.Uri.String(), opts.Identities...)
ctx, err := bindings.NewConnection(context.Background(), opts.Uri, opts.Identities...)
return &tunnel.ContainerEngine{ClientCxt: ctx}, err
}
return nil, fmt.Errorf("runtime mode '%v' is not supported", mode)
return nil, fmt.Errorf("runtime mode '%v' is not supported", opts.EngineMode)
}
// NewImageEngine factory provides a libpod runtime for image-related operations
func NewImageEngine(mode entities.EngineMode, opts entities.EngineOptions) (entities.ImageEngine, error) {
switch mode {
func NewImageEngine(opts entities.EngineOptions) (entities.ImageEngine, error) {
switch opts.EngineMode {
case entities.ABIMode:
return nil, fmt.Errorf("direct image runtime not supported")
case entities.TunnelMode:
ctx, err := bindings.NewConnection(context.Background(), opts.Uri.String(), opts.Identities...)
ctx, err := bindings.NewConnection(context.Background(), opts.Uri, opts.Identities...)
return &tunnel.ImageEngine{ClientCxt: ctx}, err
}
return nil, fmt.Errorf("runtime mode '%v' is not supported", mode)
return nil, fmt.Errorf("runtime mode '%v' is not supported", opts.EngineMode)
}

View file

@ -0,0 +1,42 @@
package tunnel
import (
"context"
"github.com/containers/libpod/pkg/bindings/containers"
"github.com/containers/libpod/pkg/domain/entities"
)
func (ic *ContainerEngine) ContainerExists(ctx context.Context, nameOrId string) (*entities.BoolReport, error) {
exists, err := containers.Exists(ic.ClientCxt, nameOrId)
return &entities.BoolReport{Value: exists}, err
}
func (ic *ContainerEngine) ContainerWait(ctx context.Context, namesOrIds []string, options entities.WaitOptions) ([]entities.WaitReport, error) {
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) {
panic("implement me")
}
func (r *ContainerEngine) ContainerPrune(ctx context.Context) (*entities.ContainerPruneReport, error) {
panic("implement me")
}

View 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
}

View file

@ -16,18 +16,6 @@ type ContainerEngine struct {
ClientCxt context.Context
}
func (r *ContainerEngine) Shutdown(force bool) error {
return nil
}
func (r *ContainerEngine) ContainerDelete(ctx context.Context, opts entities.ContainerDeleteOptions) (*entities.ContainerDeleteReport, error) {
panic("implement me")
}
func (r *ContainerEngine) ContainerPrune(ctx context.Context) (*entities.ContainerPruneReport, error) {
panic("implement me")
}
func (r *ContainerEngine) PodDelete(ctx context.Context, opts entities.PodPruneOptions) (*entities.PodDeleteReport, error) {
panic("implement me")
}