mirror of
https://github.com/containers/podman.git
synced 2025-06-28 14:29:04 +08:00
Merge pull request #5573 from mheon/add_basic_exec_endpoints
Implement APIv2 Exec Create and Inspect Endpoints
This commit is contained in:
@ -94,67 +94,14 @@ func (e *ExecSession) ContainerID() string {
|
||||
return e.ContainerId
|
||||
}
|
||||
|
||||
// InspectExecSession contains information about a given exec session.
|
||||
type InspectExecSession struct {
|
||||
// CanRemove is legacy and used purely for compatibility reasons.
|
||||
// Will always be set to true, unless the exec session is running.
|
||||
CanRemove bool `json:"CanRemove"`
|
||||
// ContainerID is the ID of the container this exec session is attached
|
||||
// to.
|
||||
ContainerID string `json:"ContainerID"`
|
||||
// DetachKeys are the detach keys used by the exec session.
|
||||
// If set to "" the default keys are being used.
|
||||
// Will show "<none>" if no detach keys are set.
|
||||
DetachKeys string `json:"DetachKeys"`
|
||||
// ExitCode is the exit code of the exec session. Will be set to 0 if
|
||||
// the exec session has not yet exited.
|
||||
ExitCode int `json:"ExitCode"`
|
||||
// ID is the ID of the exec session.
|
||||
ID string `json:"ID"`
|
||||
// OpenStderr is whether the container's STDERR stream will be attached.
|
||||
// Always set to true if the exec session created a TTY.
|
||||
OpenStderr bool `json:"OpenStderr"`
|
||||
// OpenStdin is whether the container's STDIN stream will be attached
|
||||
// to.
|
||||
OpenStdin bool `json:"OpenStdin"`
|
||||
// OpenStdout is whether the container's STDOUT stream will be attached.
|
||||
// Always set to true if the exec session created a TTY.
|
||||
OpenStdout bool `json:"OpenStdout"`
|
||||
// Running is whether the exec session is running.
|
||||
Running bool `json:"Running"`
|
||||
// Pid is the PID of the exec session's process.
|
||||
// Will be set to 0 if the exec session is not running.
|
||||
Pid int `json:"Pid"`
|
||||
// ProcessConfig contains information about the exec session's process.
|
||||
ProcessConfig *InspectExecProcess `json:"ProcessConfig"`
|
||||
}
|
||||
|
||||
// InspectExecProcess contains information about the process in a given exec
|
||||
// session.
|
||||
type InspectExecProcess struct {
|
||||
// Arguments are the arguments to the entrypoint command of the exec
|
||||
// session.
|
||||
Arguments []string `json:"arguments"`
|
||||
// Entrypoint is the entrypoint for the exec session (the command that
|
||||
// will be executed in the container).
|
||||
Entrypoint string `json:"entrypoint"`
|
||||
// Privileged is whether the exec session will be started with elevated
|
||||
// privileges.
|
||||
Privileged bool `json:"privileged"`
|
||||
// Tty is whether the exec session created a terminal.
|
||||
Tty bool `json:"tty"`
|
||||
// User is the user the exec session was started as.
|
||||
User string `json:"user"`
|
||||
}
|
||||
|
||||
// Inspect inspects the given exec session and produces detailed output on its
|
||||
// configuration and current state.
|
||||
func (e *ExecSession) Inspect() (*InspectExecSession, error) {
|
||||
func (e *ExecSession) Inspect() (*define.InspectExecSession, error) {
|
||||
if e.Config == nil {
|
||||
return nil, errors.Wrapf(define.ErrInternal, "given exec session does not have a configuration block")
|
||||
}
|
||||
|
||||
output := new(InspectExecSession)
|
||||
output := new(define.InspectExecSession)
|
||||
output.CanRemove = e.State != define.ExecStateRunning
|
||||
output.ContainerID = e.ContainerId
|
||||
if e.Config.DetachKeys != nil {
|
||||
@ -167,7 +114,7 @@ func (e *ExecSession) Inspect() (*InspectExecSession, error) {
|
||||
output.OpenStdout = e.Config.AttachStdout
|
||||
output.Running = e.State == define.ExecStateRunning
|
||||
output.Pid = e.PID
|
||||
output.ProcessConfig = new(InspectExecProcess)
|
||||
output.ProcessConfig = new(define.InspectExecProcess)
|
||||
if len(e.Config.Command) > 0 {
|
||||
output.ProcessConfig.Entrypoint = e.Config.Command[0]
|
||||
if len(e.Config.Command) > 1 {
|
||||
@ -213,6 +160,11 @@ func (c *Container) ExecCreate(config *ExecConfig) (string, error) {
|
||||
return "", errors.Wrapf(define.ErrInvalidArg, "cannot specify streams to attach to when exec session has a pseudoterminal")
|
||||
}
|
||||
|
||||
// Verify that we are in a good state to continue
|
||||
if !c.ensureState(define.ContainerStateRunning) {
|
||||
return "", errors.Wrapf(define.ErrCtrStateInvalid, "can only create exec sessions on running containers")
|
||||
}
|
||||
|
||||
// Generate an ID for our new exec session
|
||||
sessionID := stringid.GenerateNonCryptoID()
|
||||
found := true
|
||||
@ -279,6 +231,11 @@ func (c *Container) ExecStartAndAttach(sessionID string, streams *AttachStreams)
|
||||
}
|
||||
}
|
||||
|
||||
// Verify that we are in a good state to continue
|
||||
if !c.ensureState(define.ContainerStateRunning) {
|
||||
return errors.Wrapf(define.ErrCtrStateInvalid, "can only start exec sessions when their container is running")
|
||||
}
|
||||
|
||||
session, ok := c.state.ExecSessions[sessionID]
|
||||
if !ok {
|
||||
return errors.Wrapf(define.ErrNoSuchExecSession, "container %s has no exec session with ID %s", c.ID(), sessionID)
|
||||
|
54
libpod/define/inspect.go
Normal file
54
libpod/define/inspect.go
Normal file
@ -0,0 +1,54 @@
|
||||
package define
|
||||
|
||||
// InspectExecSession contains information about a given exec session.
|
||||
type InspectExecSession struct {
|
||||
// CanRemove is legacy and used purely for compatibility reasons.
|
||||
// Will always be set to true, unless the exec session is running.
|
||||
CanRemove bool `json:"CanRemove"`
|
||||
// ContainerID is the ID of the container this exec session is attached
|
||||
// to.
|
||||
ContainerID string `json:"ContainerID"`
|
||||
// DetachKeys are the detach keys used by the exec session.
|
||||
// If set to "" the default keys are being used.
|
||||
// Will show "<none>" if no detach keys are set.
|
||||
DetachKeys string `json:"DetachKeys"`
|
||||
// ExitCode is the exit code of the exec session. Will be set to 0 if
|
||||
// the exec session has not yet exited.
|
||||
ExitCode int `json:"ExitCode"`
|
||||
// ID is the ID of the exec session.
|
||||
ID string `json:"ID"`
|
||||
// OpenStderr is whether the container's STDERR stream will be attached.
|
||||
// Always set to true if the exec session created a TTY.
|
||||
OpenStderr bool `json:"OpenStderr"`
|
||||
// OpenStdin is whether the container's STDIN stream will be attached
|
||||
// to.
|
||||
OpenStdin bool `json:"OpenStdin"`
|
||||
// OpenStdout is whether the container's STDOUT stream will be attached.
|
||||
// Always set to true if the exec session created a TTY.
|
||||
OpenStdout bool `json:"OpenStdout"`
|
||||
// Running is whether the exec session is running.
|
||||
Running bool `json:"Running"`
|
||||
// Pid is the PID of the exec session's process.
|
||||
// Will be set to 0 if the exec session is not running.
|
||||
Pid int `json:"Pid"`
|
||||
// ProcessConfig contains information about the exec session's process.
|
||||
ProcessConfig *InspectExecProcess `json:"ProcessConfig"`
|
||||
}
|
||||
|
||||
// InspectExecProcess contains information about the process in a given exec
|
||||
// session.
|
||||
type InspectExecProcess struct {
|
||||
// Arguments are the arguments to the entrypoint command of the exec
|
||||
// session.
|
||||
Arguments []string `json:"arguments"`
|
||||
// Entrypoint is the entrypoint for the exec session (the command that
|
||||
// will be executed in the container).
|
||||
Entrypoint string `json:"entrypoint"`
|
||||
// Privileged is whether the exec session will be started with elevated
|
||||
// privileges.
|
||||
Privileged bool `json:"privileged"`
|
||||
// Tty is whether the exec session created a terminal.
|
||||
Tty bool `json:"tty"`
|
||||
// User is the user the exec session was started as.
|
||||
User string `json:"user"`
|
||||
}
|
@ -21,6 +21,8 @@ import (
|
||||
|
||||
var (
|
||||
// NameRegex is a regular expression to validate container/pod names.
|
||||
// This must NOT be changed from outside of Libpod. It should be a
|
||||
// constant, but Go won't let us do that.
|
||||
NameRegex = regexp.MustCompile("^[a-zA-Z0-9][a-zA-Z0-9_.-]*$")
|
||||
// RegexError is thrown in presence of an invalid container/pod name.
|
||||
RegexError = errors.Wrapf(define.ErrInvalidArg, "names must match [a-zA-Z0-9][a-zA-Z0-9_.-]*")
|
||||
|
@ -830,6 +830,24 @@ func (r *Runtime) GetLatestContainer() (*Container, error) {
|
||||
return ctrs[lastCreatedIndex], nil
|
||||
}
|
||||
|
||||
// GetExecSessionContainer gets the container that a given exec session ID is
|
||||
// attached to.
|
||||
func (r *Runtime) GetExecSessionContainer(id string) (*Container, error) {
|
||||
r.lock.RLock()
|
||||
defer r.lock.RUnlock()
|
||||
|
||||
if !r.valid {
|
||||
return nil, define.ErrRuntimeStopped
|
||||
}
|
||||
|
||||
ctrID, err := r.state.GetExecSession(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return r.state.Container(ctrID)
|
||||
}
|
||||
|
||||
// PruneContainers removes stopped and exited containers from localstorage. A set of optional filters
|
||||
// can be provided to be more granular.
|
||||
func (r *Runtime) PruneContainers(filterFuncs []ContainerFilter) (map[string]int64, map[string]error, error) {
|
||||
|
107
pkg/api/handlers/compat/exec.go
Normal file
107
pkg/api/handlers/compat/exec.go
Normal file
@ -0,0 +1,107 @@
|
||||
package compat
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/libpod/libpod"
|
||||
"github.com/containers/libpod/libpod/define"
|
||||
"github.com/containers/libpod/pkg/api/handlers"
|
||||
"github.com/containers/libpod/pkg/api/handlers/utils"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// ExecCreateHandler creates an exec session for a given container.
|
||||
func ExecCreateHandler(w http.ResponseWriter, r *http.Request) {
|
||||
runtime := r.Context().Value("runtime").(*libpod.Runtime)
|
||||
|
||||
input := new(handlers.ExecCreateConfig)
|
||||
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
|
||||
utils.InternalServerError(w, errors.Wrapf(err, "error decoding request body as JSON"))
|
||||
return
|
||||
}
|
||||
|
||||
ctrName := utils.GetName(r)
|
||||
ctr, err := runtime.LookupContainer(ctrName)
|
||||
if err != nil {
|
||||
utils.ContainerNotFound(w, ctrName, err)
|
||||
return
|
||||
}
|
||||
|
||||
libpodConfig := new(libpod.ExecConfig)
|
||||
libpodConfig.Command = input.Cmd
|
||||
libpodConfig.Terminal = input.Tty
|
||||
libpodConfig.AttachStdin = input.AttachStdin
|
||||
libpodConfig.AttachStderr = input.AttachStderr
|
||||
libpodConfig.AttachStdout = input.AttachStdout
|
||||
if input.DetachKeys != "" {
|
||||
libpodConfig.DetachKeys = &input.DetachKeys
|
||||
}
|
||||
libpodConfig.Environment = make(map[string]string)
|
||||
for _, envStr := range input.Env {
|
||||
split := strings.SplitN(envStr, "=", 2)
|
||||
if len(split) != 2 {
|
||||
utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, errors.Errorf("environment variable %q badly formed, must be key=value", envStr))
|
||||
return
|
||||
}
|
||||
libpodConfig.Environment[split[0]] = split[1]
|
||||
}
|
||||
libpodConfig.WorkDir = input.WorkingDir
|
||||
libpodConfig.Privileged = input.Privileged
|
||||
libpodConfig.User = input.User
|
||||
|
||||
sessID, err := ctr.ExecCreate(libpodConfig)
|
||||
if err != nil {
|
||||
if errors.Cause(err) == define.ErrCtrStateInvalid {
|
||||
// Check if the container is paused. If so, return a 409
|
||||
state, err := ctr.State()
|
||||
if err == nil {
|
||||
// Ignore the error != nil case. We're already
|
||||
// throwing an InternalServerError below.
|
||||
if state == define.ContainerStatePaused {
|
||||
utils.Error(w, "Container is paused", http.StatusConflict, errors.Errorf("cannot create exec session as container %s is paused", ctr.ID()))
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
utils.InternalServerError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
resp := new(handlers.ExecCreateResponse)
|
||||
resp.ID = sessID
|
||||
|
||||
utils.WriteResponse(w, http.StatusCreated, resp)
|
||||
}
|
||||
|
||||
// ExecInspectHandler inspects a given exec session.
|
||||
func ExecInspectHandler(w http.ResponseWriter, r *http.Request) {
|
||||
runtime := r.Context().Value("runtime").(*libpod.Runtime)
|
||||
|
||||
sessionID := mux.Vars(r)["id"]
|
||||
sessionCtr, err := runtime.GetExecSessionContainer(sessionID)
|
||||
if err != nil {
|
||||
utils.Error(w, fmt.Sprintf("No such exec session: %s", sessionID), http.StatusNotFound, err)
|
||||
return
|
||||
}
|
||||
|
||||
logrus.Debugf("Inspecting exec session %s of container %s", sessionID, sessionCtr.ID())
|
||||
|
||||
session, err := sessionCtr.ExecSession(sessionID)
|
||||
if err != nil {
|
||||
utils.InternalServerError(w, errors.Wrapf(err, "error retrieving exec session %s from container %s", sessionID, sessionCtr.ID()))
|
||||
return
|
||||
}
|
||||
|
||||
inspectOut, err := session.Inspect()
|
||||
if err != nil {
|
||||
utils.InternalServerError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
utils.WriteResponse(w, http.StatusOK, inspectOut)
|
||||
}
|
@ -172,6 +172,14 @@ type ImageTreeResponse struct {
|
||||
Layers []ImageLayer `json:"layers"`
|
||||
}
|
||||
|
||||
type ExecCreateConfig struct {
|
||||
docker.ExecConfig
|
||||
}
|
||||
|
||||
type ExecCreateResponse struct {
|
||||
docker.IDResponse
|
||||
}
|
||||
|
||||
func EventToApiEvent(e *events.Event) *Event {
|
||||
return &Event{dockerEvents.Message{
|
||||
Type: e.Type.String(),
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
)
|
||||
|
||||
func (s *APIServer) registerExecHandlers(r *mux.Router) error {
|
||||
// swagger:operation POST /containers/{name}/create compat createExec
|
||||
// swagger:operation POST /containers/{name}/exec compat createExec
|
||||
// ---
|
||||
// tags:
|
||||
// - exec (compat)
|
||||
@ -74,9 +74,9 @@ func (s *APIServer) registerExecHandlers(r *mux.Router) error {
|
||||
// description: container is paused
|
||||
// 500:
|
||||
// $ref: "#/responses/InternalError"
|
||||
r.Handle(VersionedPath("/containers/{name}/create"), s.APIHandler(compat.UnsupportedHandler)).Methods(http.MethodPost)
|
||||
r.Handle(VersionedPath("/containers/{name}/exec"), s.APIHandler(compat.ExecCreateHandler)).Methods(http.MethodPost)
|
||||
// Added non version path to URI to support docker non versioned paths
|
||||
r.Handle("/containers/{name}/create", s.APIHandler(compat.UnsupportedHandler)).Methods(http.MethodPost)
|
||||
r.Handle("/containers/{name}/exec", s.APIHandler(compat.ExecCreateHandler)).Methods(http.MethodPost)
|
||||
// swagger:operation POST /exec/{id}/start compat startExec
|
||||
// ---
|
||||
// tags:
|
||||
@ -169,15 +169,15 @@ func (s *APIServer) registerExecHandlers(r *mux.Router) error {
|
||||
// $ref: "#/responses/NoSuchExecInstance"
|
||||
// 500:
|
||||
// $ref: "#/responses/InternalError"
|
||||
r.Handle(VersionedPath("/exec/{id}/json"), s.APIHandler(compat.UnsupportedHandler)).Methods(http.MethodGet)
|
||||
r.Handle(VersionedPath("/exec/{id}/json"), s.APIHandler(compat.ExecInspectHandler)).Methods(http.MethodGet)
|
||||
// Added non version path to URI to support docker non versioned paths
|
||||
r.Handle("/exec/{id}/json", s.APIHandler(compat.UnsupportedHandler)).Methods(http.MethodGet)
|
||||
r.Handle("/exec/{id}/json", s.APIHandler(compat.ExecInspectHandler)).Methods(http.MethodGet)
|
||||
|
||||
/*
|
||||
libpod api follows
|
||||
*/
|
||||
|
||||
// swagger:operation POST /libpod/containers/{name}/create libpod libpodCreateExec
|
||||
// swagger:operation POST /libpod/containers/{name}/exec libpod libpodCreateExec
|
||||
// ---
|
||||
// tags:
|
||||
// - exec
|
||||
@ -243,7 +243,7 @@ func (s *APIServer) registerExecHandlers(r *mux.Router) error {
|
||||
// description: container is paused
|
||||
// 500:
|
||||
// $ref: "#/responses/InternalError"
|
||||
r.Handle(VersionedPath("/libpod/containers/{name}/create"), s.APIHandler(compat.UnsupportedHandler)).Methods(http.MethodPost)
|
||||
r.Handle(VersionedPath("/libpod/containers/{name}/exec"), s.APIHandler(compat.ExecCreateHandler)).Methods(http.MethodPost)
|
||||
// swagger:operation POST /libpod/exec/{id}/start libpod libpodStartExec
|
||||
// ---
|
||||
// tags:
|
||||
@ -332,6 +332,6 @@ func (s *APIServer) registerExecHandlers(r *mux.Router) error {
|
||||
// $ref: "#/responses/NoSuchExecInstance"
|
||||
// 500:
|
||||
// $ref: "#/responses/InternalError"
|
||||
r.Handle(VersionedPath("/libpod/exec/{id}/json"), s.APIHandler(compat.UnsupportedHandler)).Methods(http.MethodGet)
|
||||
r.Handle(VersionedPath("/libpod/exec/{id}/json"), s.APIHandler(compat.ExecInspectHandler)).Methods(http.MethodGet)
|
||||
return nil
|
||||
}
|
||||
|
71
pkg/bindings/containers/exec.go
Normal file
71
pkg/bindings/containers/exec.go
Normal file
@ -0,0 +1,71 @@
|
||||
package containers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/libpod/libpod/define"
|
||||
"github.com/containers/libpod/pkg/api/handlers"
|
||||
"github.com/containers/libpod/pkg/bindings"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
||||
|
||||
// ExecCreate creates a new exec session in an existing container.
|
||||
// The exec session will not be started; that is done with ExecStart.
|
||||
// Returns ID of new exec session, or an error if one occurred.
|
||||
func ExecCreate(ctx context.Context, nameOrID string, config *handlers.ExecCreateConfig) (string, error) {
|
||||
conn, err := bindings.GetClient(ctx)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if config == nil {
|
||||
return "", errors.Errorf("must provide a configuration for exec session")
|
||||
}
|
||||
|
||||
requestJSON, err := json.Marshal(config)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "error marshalling exec config to JSON")
|
||||
}
|
||||
jsonReader := strings.NewReader(string(requestJSON))
|
||||
|
||||
resp, err := conn.DoRequest(jsonReader, http.MethodPost, "/containers/%s/exec", nil, nameOrID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
respStruct := new(handlers.ExecCreateResponse)
|
||||
if err := resp.Process(respStruct); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return respStruct.ID, nil
|
||||
}
|
||||
|
||||
// ExecInspect inspects an existing exec session, returning detailed information
|
||||
// about it.
|
||||
func ExecInspect(ctx context.Context, sessionID string) (*define.InspectExecSession, error) {
|
||||
conn, err := bindings.GetClient(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
logrus.Debugf("Inspecting session ID %q", sessionID)
|
||||
|
||||
resp, err := conn.DoRequest(nil, http.MethodGet, "/exec/%s/json", nil, sessionID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
respStruct := new(define.InspectExecSession)
|
||||
if err := resp.Process(respStruct); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return respStruct, nil
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
package test_bindings
|
||||
|
||||
import (
|
||||
"github.com/containers/libpod/libpod/define"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containers/libpod/libpod/define"
|
||||
"github.com/containers/libpod/pkg/bindings"
|
||||
"github.com/containers/libpod/pkg/bindings/containers"
|
||||
"github.com/containers/libpod/pkg/specgen"
|
||||
|
77
pkg/bindings/test/exec_test.go
Normal file
77
pkg/bindings/test/exec_test.go
Normal file
@ -0,0 +1,77 @@
|
||||
package test_bindings
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/containers/libpod/pkg/api/handlers"
|
||||
"github.com/containers/libpod/pkg/bindings"
|
||||
"github.com/containers/libpod/pkg/bindings/containers"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
"github.com/onsi/gomega/gexec"
|
||||
)
|
||||
|
||||
var _ = Describe("Podman containers exec", func() {
|
||||
var (
|
||||
bt *bindingTest
|
||||
s *gexec.Session
|
||||
)
|
||||
|
||||
BeforeEach(func() {
|
||||
bt = newBindingTest()
|
||||
bt.RestoreImagesFromCache()
|
||||
s = bt.startAPIService()
|
||||
time.Sleep(1 * time.Second)
|
||||
err := bt.NewConnection()
|
||||
Expect(err).To(BeNil())
|
||||
})
|
||||
|
||||
AfterEach(func() {
|
||||
s.Kill()
|
||||
bt.cleanup()
|
||||
})
|
||||
|
||||
It("Podman exec create makes an exec session", func() {
|
||||
name := "testCtr"
|
||||
cid, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
execConfig := new(handlers.ExecCreateConfig)
|
||||
execConfig.Cmd = []string{"echo", "hello world"}
|
||||
|
||||
sessionID, err := containers.ExecCreate(bt.conn, name, execConfig)
|
||||
Expect(err).To(BeNil())
|
||||
Expect(sessionID).To(Not(Equal("")))
|
||||
|
||||
inspectOut, err := containers.ExecInspect(bt.conn, sessionID)
|
||||
Expect(err).To(BeNil())
|
||||
Expect(inspectOut.ContainerID).To(Equal(cid))
|
||||
Expect(inspectOut.ProcessConfig.Entrypoint).To(Equal("echo"))
|
||||
Expect(len(inspectOut.ProcessConfig.Arguments)).To(Equal(1))
|
||||
Expect(inspectOut.ProcessConfig.Arguments[0]).To(Equal("hello world"))
|
||||
})
|
||||
|
||||
It("Podman exec create with bad command fails", func() {
|
||||
name := "testCtr"
|
||||
_, err := bt.RunTopContainer(&name, &bindings.PFalse, nil)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
execConfig := new(handlers.ExecCreateConfig)
|
||||
|
||||
_, err = containers.ExecCreate(bt.conn, name, execConfig)
|
||||
Expect(err).To(Not(BeNil()))
|
||||
})
|
||||
|
||||
It("Podman exec create with invalid container fails", func() {
|
||||
execConfig := new(handlers.ExecCreateConfig)
|
||||
execConfig.Cmd = []string{"echo", "hello world"}
|
||||
|
||||
_, err := containers.ExecCreate(bt.conn, "doesnotexist", execConfig)
|
||||
Expect(err).To(Not(BeNil()))
|
||||
})
|
||||
|
||||
It("Podman exec inspect on invalid session fails", func() {
|
||||
_, err := containers.ExecInspect(bt.conn, "0000000000000000000000000000000000000000000000000000000000000000")
|
||||
Expect(err).To(Not(BeNil()))
|
||||
})
|
||||
})
|
@ -79,9 +79,7 @@ var _ = Describe("Podman pods", func() {
|
||||
|
||||
// The test validates the list pod endpoint with passing filters as the params.
|
||||
It("List pods with filters", func() {
|
||||
var (
|
||||
newpod2 string = "newpod2"
|
||||
)
|
||||
newpod2 := "newpod2"
|
||||
bt.Podcreate(&newpod2)
|
||||
_, err = bt.RunTopContainer(nil, &bindings.PTrue, &newpod)
|
||||
Expect(err).To(BeNil())
|
||||
|
Reference in New Issue
Block a user