mirror of
https://github.com/containers/podman.git
synced 2025-10-19 04:03:23 +08:00
Add bindings for Container Exec Create + Inspect
Also adds some basic tests for these two. More tests are needed but will have to wait for state to be finished. Signed-off-by: Matthew Heon <matthew.heon@pm.me>
This commit is contained in:

committed by
Matthew Heon

parent
0c40b62c77
commit
e42cbdd1b2
@ -231,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]
|
session, ok := c.state.ExecSessions[sessionID]
|
||||||
if !ok {
|
if !ok {
|
||||||
return errors.Wrapf(define.ErrNoSuchExecSession, "container %s has no exec session with ID %s", c.ID(), sessionID)
|
return errors.Wrapf(define.ErrNoSuchExecSession, "container %s has no exec session with ID %s", c.ID(), sessionID)
|
||||||
|
@ -21,6 +21,8 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
// NameRegex is a regular expression to validate container/pod names.
|
// 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_.-]*$")
|
NameRegex = regexp.MustCompile("^[a-zA-Z0-9][a-zA-Z0-9_.-]*$")
|
||||||
// RegexError is thrown in presence of an invalid container/pod name.
|
// 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_.-]*")
|
RegexError = errors.Wrapf(define.ErrInvalidArg, "names must match [a-zA-Z0-9][a-zA-Z0-9_.-]*")
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/containers/libpod/pkg/api/handlers/utils"
|
"github.com/containers/libpod/pkg/api/handlers/utils"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ExecCreateHandler creates an exec session for a given container.
|
// ExecCreateHandler creates an exec session for a given container.
|
||||||
@ -88,6 +89,8 @@ func ExecInspectHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logrus.Debugf("Inspecting exec session %s of container %s", sessionID, sessionCtr.ID())
|
||||||
|
|
||||||
session, err := sessionCtr.ExecSession(sessionID)
|
session, err := sessionCtr.ExecSession(sessionID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.InternalServerError(w, errors.Wrapf(err, "error retrieving exec session %s from container %s", sessionID, sessionCtr.ID()))
|
utils.InternalServerError(w, errors.Wrapf(err, "error retrieving exec session %s from container %s", sessionID, sessionCtr.ID()))
|
||||||
|
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
|
package test_bindings
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/containers/libpod/libpod/define"
|
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/containers/libpod/libpod/define"
|
||||||
"github.com/containers/libpod/pkg/bindings"
|
"github.com/containers/libpod/pkg/bindings"
|
||||||
"github.com/containers/libpod/pkg/bindings/containers"
|
"github.com/containers/libpod/pkg/bindings/containers"
|
||||||
"github.com/containers/libpod/pkg/specgen"
|
"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.
|
// The test validates the list pod endpoint with passing filters as the params.
|
||||||
It("List pods with filters", func() {
|
It("List pods with filters", func() {
|
||||||
var (
|
newpod2 := "newpod2"
|
||||||
newpod2 string = "newpod2"
|
|
||||||
)
|
|
||||||
bt.Podcreate(&newpod2)
|
bt.Podcreate(&newpod2)
|
||||||
_, err = bt.RunTopContainer(nil, &bindings.PTrue, &newpod)
|
_, err = bt.RunTopContainer(nil, &bindings.PTrue, &newpod)
|
||||||
Expect(err).To(BeNil())
|
Expect(err).To(BeNil())
|
||||||
|
Reference in New Issue
Block a user