summaryrefslogtreecommitdiff
path: root/pkg/api/handlers/compat
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/api/handlers/compat')
-rw-r--r--pkg/api/handlers/compat/containers_create.go13
-rw-r--r--pkg/api/handlers/compat/containers_export.go42
-rw-r--r--pkg/api/handlers/compat/exec.go107
-rw-r--r--pkg/api/handlers/compat/images.go7
-rw-r--r--pkg/api/handlers/compat/images_push.go80
-rw-r--r--pkg/api/handlers/compat/images_remove.go22
-rw-r--r--pkg/api/handlers/compat/info.go8
7 files changed, 260 insertions, 19 deletions
diff --git a/pkg/api/handlers/compat/containers_create.go b/pkg/api/handlers/compat/containers_create.go
index 6b8440fc2..12af40876 100644
--- a/pkg/api/handlers/compat/containers_create.go
+++ b/pkg/api/handlers/compat/containers_create.go
@@ -6,8 +6,8 @@ import (
"net/http"
"strings"
+ "github.com/containers/common/pkg/config"
"github.com/containers/libpod/libpod"
- "github.com/containers/libpod/libpod/define"
image2 "github.com/containers/libpod/libpod/image"
"github.com/containers/libpod/pkg/api/handlers"
"github.com/containers/libpod/pkg/api/handlers/utils"
@@ -46,7 +46,12 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "NewFromLocal()"))
return
}
- cc, err := makeCreateConfig(input, newImage)
+ defaultContainerConfig, err := runtime.GetConfig()
+ if err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "GetConfig()"))
+ return
+ }
+ cc, err := makeCreateConfig(defaultContainerConfig, input, newImage)
if err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "makeCreatConfig()"))
return
@@ -55,7 +60,7 @@ func CreateContainer(w http.ResponseWriter, r *http.Request) {
utils.CreateContainer(r.Context(), w, runtime, &cc)
}
-func makeCreateConfig(input handlers.CreateContainerConfig, newImage *image2.Image) (createconfig.CreateConfig, error) {
+func makeCreateConfig(defaultContainerConfig *config.Config, input handlers.CreateContainerConfig, newImage *image2.Image) (createconfig.CreateConfig, error) {
var (
err error
init bool
@@ -76,7 +81,7 @@ func makeCreateConfig(input handlers.CreateContainerConfig, newImage *image2.Ima
workDir = input.WorkingDir
}
- stopTimeout := uint(define.CtrRemoveTimeout)
+ stopTimeout := defaultContainerConfig.Engine.StopTimeout
if input.StopTimeout != nil {
stopTimeout = uint(*input.StopTimeout)
}
diff --git a/pkg/api/handlers/compat/containers_export.go b/pkg/api/handlers/compat/containers_export.go
new file mode 100644
index 000000000..37b9fbf2b
--- /dev/null
+++ b/pkg/api/handlers/compat/containers_export.go
@@ -0,0 +1,42 @@
+package compat
+
+import (
+ "io/ioutil"
+ "net/http"
+ "os"
+
+ "github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/pkg/api/handlers/utils"
+ "github.com/pkg/errors"
+)
+
+func ExportContainer(w http.ResponseWriter, r *http.Request) {
+ runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ name := utils.GetName(r)
+ con, err := runtime.LookupContainer(name)
+ if err != nil {
+ utils.ContainerNotFound(w, name, err)
+ return
+ }
+ tmpfile, err := ioutil.TempFile("", "api.tar")
+ if err != nil {
+ utils.Error(w, "unable to create tarball tempfile", http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
+ return
+ }
+ defer os.Remove(tmpfile.Name())
+ if err := tmpfile.Close(); err != nil {
+ utils.Error(w, "unable to close tempfile", http.StatusInternalServerError, errors.Wrap(err, "unable to close tempfile"))
+ return
+ }
+ if err := con.Export(tmpfile.Name()); err != nil {
+ utils.Error(w, "failed to save the image", http.StatusInternalServerError, errors.Wrap(err, "failed to save image"))
+ return
+ }
+ rdr, err := os.Open(tmpfile.Name())
+ if err != nil {
+ utils.Error(w, "failed to read temp tarball", http.StatusInternalServerError, errors.Wrap(err, "failed to read the exported tarfile"))
+ return
+ }
+ defer rdr.Close()
+ utils.WriteResponse(w, http.StatusOK, rdr)
+}
diff --git a/pkg/api/handlers/compat/exec.go b/pkg/api/handlers/compat/exec.go
new file mode 100644
index 000000000..ec1a8ac96
--- /dev/null
+++ b/pkg/api/handlers/compat/exec.go
@@ -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)
+}
diff --git a/pkg/api/handlers/compat/images.go b/pkg/api/handlers/compat/images.go
index cce718f54..ea9cbd691 100644
--- a/pkg/api/handlers/compat/images.go
+++ b/pkg/api/handlers/compat/images.go
@@ -64,6 +64,7 @@ func PruneImages(w http.ResponseWriter, r *http.Request) {
runtime := r.Context().Value("runtime").(*libpod.Runtime)
query := struct {
+ All bool
Filters map[string][]string `schema:"filters"`
}{
// This is where you can override the golang default value for one of fields
@@ -80,7 +81,7 @@ func PruneImages(w http.ResponseWriter, r *http.Request) {
filters = append(filters, fmt.Sprintf("%s=%s", k, val))
}
}
- pruneCids, err := runtime.ImageRuntime().PruneImages(r.Context(), false, filters)
+ pruneCids, err := runtime.ImageRuntime().PruneImages(r.Context(), query.All, filters)
if err != nil {
utils.InternalServerError(w, err)
return
@@ -128,13 +129,13 @@ func CommitContainer(w http.ResponseWriter, r *http.Request) {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
return
}
- sc := image2.GetSystemContext(rtc.SignaturePolicyPath, "", false)
+ sc := image2.GetSystemContext(rtc.Engine.SignaturePolicyPath, "", false)
tag := "latest"
options := libpod.ContainerCommitOptions{
Pause: true,
}
options.CommitOptions = buildah.CommitOptions{
- SignaturePolicyPath: rtc.SignaturePolicyPath,
+ SignaturePolicyPath: rtc.Engine.SignaturePolicyPath,
ReportWriter: os.Stderr,
SystemContext: sc,
PreferredManifestType: manifest.DockerV2Schema2MediaType,
diff --git a/pkg/api/handlers/compat/images_push.go b/pkg/api/handlers/compat/images_push.go
new file mode 100644
index 000000000..2260d5557
--- /dev/null
+++ b/pkg/api/handlers/compat/images_push.go
@@ -0,0 +1,80 @@
+package compat
+
+import (
+ "context"
+ "net/http"
+ "os"
+ "strings"
+
+ "github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/libpod/image"
+ "github.com/containers/libpod/pkg/api/handlers/utils"
+ "github.com/gorilla/schema"
+ "github.com/pkg/errors"
+)
+
+// PushImage is the handler for the compat http endpoint for pushing images.
+func PushImage(w http.ResponseWriter, r *http.Request) {
+ decoder := r.Context().Value("decoder").(*schema.Decoder)
+ runtime := r.Context().Value("runtime").(*libpod.Runtime)
+
+ query := struct {
+ Tag string `schema:"tag"`
+ }{
+ // This is where you can override the golang default value for one of fields
+ }
+
+ if err := decoder.Decode(&query, r.URL.Query()); err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String()))
+ return
+ }
+
+ // Note that Docker's docs state "Image name or ID" to be in the path
+ // parameter but it really must be a name as Docker does not allow for
+ // pushing an image by ID.
+ imageName := strings.TrimSuffix(utils.GetName(r), "/push") // GetName returns the entire path
+ if query.Tag != "" {
+ imageName += ":" + query.Tag
+ }
+ if _, err := utils.ParseStorageReference(imageName); err != nil {
+ utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ errors.Wrapf(err, "image source %q is not a containers-storage-transport reference", imageName))
+ return
+ }
+
+ newImage, err := runtime.ImageRuntime().NewFromLocal(imageName)
+ if err != nil {
+ utils.ImageNotFound(w, imageName, errors.Wrapf(err, "Failed to find image %s", imageName))
+ return
+ }
+
+ // TODO: the X-Registry-Auth header is not checked yet here nor in any other
+ // endpoint. Pushing does NOT work with authentication at the moment.
+ dockerRegistryOptions := &image.DockerRegistryOptions{}
+ authfile := ""
+ if sys := runtime.SystemContext(); sys != nil {
+ dockerRegistryOptions.DockerCertPath = sys.DockerCertPath
+ authfile = sys.AuthFilePath
+ }
+
+ err = newImage.PushImageToHeuristicDestination(
+ context.Background(),
+ imageName,
+ "", // manifest type
+ authfile,
+ "", // digest file
+ "", // signature policy
+ os.Stderr,
+ false, // force compression
+ image.SigningOptions{},
+ dockerRegistryOptions,
+ nil, // additional tags
+ )
+ if err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "Error pushing image %q", imageName))
+ return
+ }
+
+ utils.WriteResponse(w, http.StatusOK, "")
+
+}
diff --git a/pkg/api/handlers/compat/images_remove.go b/pkg/api/handlers/compat/images_remove.go
index 3d346543e..ed0153529 100644
--- a/pkg/api/handlers/compat/images_remove.go
+++ b/pkg/api/handlers/compat/images_remove.go
@@ -36,17 +36,23 @@ func RemoveImage(w http.ResponseWriter, r *http.Request) {
return
}
- _, err = runtime.RemoveImage(r.Context(), newImage, query.Force)
+ results, err := runtime.RemoveImage(r.Context(), newImage, query.Force)
if err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
return
}
- // TODO
- // This will need to be fixed for proper response, like Deleted: and Untagged:
- m := make(map[string]string)
- m["Deleted"] = newImage.ID()
- foo := []map[string]string{}
- foo = append(foo, m)
- utils.WriteResponse(w, http.StatusOK, foo)
+
+ response := make([]map[string]string, 0, len(results.Untagged)+1)
+ deleted := make(map[string]string, 1)
+ deleted["Deleted"] = results.Deleted
+ response = append(response, deleted)
+
+ for _, u := range results.Untagged {
+ untagged := make(map[string]string, 1)
+ untagged["Untagged"] = u
+ response = append(response, untagged)
+ }
+
+ utils.WriteResponse(w, http.StatusOK, response)
}
diff --git a/pkg/api/handlers/compat/info.go b/pkg/api/handlers/compat/info.go
index 30b49948d..104d0793b 100644
--- a/pkg/api/handlers/compat/info.go
+++ b/pkg/api/handlers/compat/info.go
@@ -9,8 +9,8 @@ import (
"strings"
"time"
+ "github.com/containers/common/pkg/config"
"github.com/containers/libpod/libpod"
- "github.com/containers/libpod/libpod/config"
"github.com/containers/libpod/libpod/define"
"github.com/containers/libpod/pkg/api/handlers"
"github.com/containers/libpod/pkg/api/handlers/utils"
@@ -60,7 +60,7 @@ func GetInfo(w http.ResponseWriter, r *http.Request) {
CPUCfsQuota: sysInfo.CPUCfsQuota,
CPUSet: sysInfo.Cpuset,
CPUShares: sysInfo.CPUShares,
- CgroupDriver: configInfo.CgroupManager,
+ CgroupDriver: configInfo.Engine.CgroupManager,
ClusterAdvertise: "",
ClusterStore: "",
ContainerdCommit: docker.Commit{},
@@ -69,7 +69,7 @@ func GetInfo(w http.ResponseWriter, r *http.Request) {
ContainersRunning: stateInfo[define.ContainerStateRunning],
ContainersStopped: stateInfo[define.ContainerStateStopped] + stateInfo[define.ContainerStateExited],
Debug: log.IsLevelEnabled(log.DebugLevel),
- DefaultRuntime: configInfo.OCIRuntime,
+ DefaultRuntime: configInfo.Engine.OCIRuntime,
DockerRootDir: storeInfo["GraphRoot"].(string),
Driver: storeInfo["GraphDriverName"].(string),
DriverStatus: getGraphStatus(storeInfo),
@@ -152,7 +152,7 @@ func getSecOpts(sysInfo *sysinfo.SysInfo) []string {
func getRuntimes(configInfo *config.Config) map[string]docker.Runtime {
var runtimes = map[string]docker.Runtime{}
- for name, paths := range configInfo.OCIRuntimes {
+ for name, paths := range configInfo.Engine.OCIRuntimes {
runtimes[name] = docker.Runtime{
Path: paths[0],
Args: nil,