aboutsummaryrefslogtreecommitdiff
path: root/pkg/api/handlers/libpod
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/api/handlers/libpod')
-rw-r--r--pkg/api/handlers/libpod/containers_create.go29
-rw-r--r--pkg/api/handlers/libpod/images.go39
-rw-r--r--pkg/api/handlers/libpod/pods.go6
-rw-r--r--pkg/api/handlers/libpod/volumes.go137
4 files changed, 174 insertions, 37 deletions
diff --git a/pkg/api/handlers/libpod/containers_create.go b/pkg/api/handlers/libpod/containers_create.go
new file mode 100644
index 000000000..ebca41151
--- /dev/null
+++ b/pkg/api/handlers/libpod/containers_create.go
@@ -0,0 +1,29 @@
+package libpod
+
+import (
+ "encoding/json"
+ "net/http"
+
+ "github.com/containers/libpod/libpod"
+ "github.com/containers/libpod/pkg/api/handlers/utils"
+ "github.com/containers/libpod/pkg/specgen"
+ "github.com/pkg/errors"
+)
+
+// CreateContainer takes a specgenerator and makes a container. It returns
+// the new container ID on success along with any warnings.
+func CreateContainer(w http.ResponseWriter, r *http.Request) {
+ runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ var sg specgen.SpecGenerator
+ if err := json.NewDecoder(r.Body).Decode(&sg); err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
+ return
+ }
+ ctr, err := sg.MakeContainer(runtime)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ response := utils.ContainerCreateResponse{ID: ctr.ID()}
+ utils.WriteJSON(w, http.StatusCreated, response)
+}
diff --git a/pkg/api/handlers/libpod/images.go b/pkg/api/handlers/libpod/images.go
index eac0e4dad..71603e6cc 100644
--- a/pkg/api/handlers/libpod/images.go
+++ b/pkg/api/handlers/libpod/images.go
@@ -8,6 +8,7 @@ import (
"net/http"
"os"
"strconv"
+ "strings"
"github.com/containers/image/v5/docker"
"github.com/containers/image/v5/docker/reference"
@@ -133,11 +134,16 @@ func PruneImages(w http.ResponseWriter, r *http.Request) {
var libpodFilters = []string{}
if _, found := r.URL.Query()["filters"]; found {
- all, err = strconv.ParseBool(query.Filters["all"][0])
- if err != nil {
- utils.InternalServerError(w, err)
- return
+ dangling := query.Filters["all"]
+ if len(dangling) > 0 {
+ all, err = strconv.ParseBool(query.Filters["all"][0])
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
}
+ // dangling is special and not implemented in the libpod side of things
+ delete(query.Filters, "dangling")
for k, v := range query.Filters {
libpodFilters = append(libpodFilters, fmt.Sprintf("%s=%s", k, v[0]))
}
@@ -157,7 +163,7 @@ func ExportImage(w http.ResponseWriter, r *http.Request) {
Compress bool `schema:"compress"`
Format string `schema:"format"`
}{
- // override any golang type defaults
+ Format: "docker-archive",
}
if err := decoder.Decode(&query, r.URL.Query()); err != nil {
@@ -166,11 +172,6 @@ func ExportImage(w http.ResponseWriter, r *http.Request) {
return
}
- if len(query.Format) < 1 {
- utils.InternalServerError(w, errors.New("format parameter cannot be empty."))
- return
- }
-
tmpfile, err := ioutil.TempFile("", "api.tar")
if err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to create tempfile"))
@@ -186,6 +187,7 @@ func ExportImage(w http.ResponseWriter, r *http.Request) {
utils.ImageNotFound(w, name, err)
return
}
+
if err := newImage.Save(r.Context(), name, query.Format, tmpfile.Name(), []string{}, false, query.Compress); err != nil {
utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest, err)
return
@@ -234,8 +236,20 @@ func ImagesLoad(w http.ResponseWriter, r *http.Request) {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to load image"))
return
}
-
- utils.WriteResponse(w, http.StatusOK, []handlers.LibpodImagesLoadReport{{ID: loadedImage}})
+ split := strings.Split(loadedImage, ",")
+ newImage, err := runtime.ImageRuntime().NewFromLocal(split[0])
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ // TODO this should go into libpod proper at some point.
+ if len(query.Reference) > 0 {
+ if err := newImage.TagImage(query.Reference); err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ }
+ utils.WriteResponse(w, http.StatusOK, handlers.LibpodImagesLoadReport{ID: loadedImage})
}
func ImagesImport(w http.ResponseWriter, r *http.Request) {
@@ -275,7 +289,6 @@ func ImagesImport(w http.ResponseWriter, r *http.Request) {
tmpfile.Close()
source = tmpfile.Name()
}
-
importedImage, err := runtime.Import(context.Background(), source, query.Reference, query.Changes, query.Message, true)
if err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "unable to import image"))
diff --git a/pkg/api/handlers/libpod/pods.go b/pkg/api/handlers/libpod/pods.go
index d043b1204..f5700579b 100644
--- a/pkg/api/handlers/libpod/pods.go
+++ b/pkg/api/handlers/libpod/pods.go
@@ -99,12 +99,10 @@ func PodCreate(w http.ResponseWriter, r *http.Request) {
utils.Error(w, "Something went wrong.", http_code, err)
return
}
- utils.WriteResponse(w, http.StatusCreated, handlers.IDResponse{ID: pod.CgroupParent()})
+ utils.WriteResponse(w, http.StatusCreated, handlers.IDResponse{ID: pod.ID()})
}
func Pods(w http.ResponseWriter, r *http.Request) {
- // 200 ok
- // 500 internal
var (
runtime = r.Context().Value("runtime").(*libpod.Runtime)
podInspectData []*libpod.PodInspect
@@ -121,7 +119,7 @@ func Pods(w http.ResponseWriter, r *http.Request) {
return
}
- if _, found := r.URL.Query()["filters"]; found {
+ if len(query.Filters) > 0 {
utils.Error(w, "filters are not implemented yet", http.StatusInternalServerError, define.ErrNotImplemented)
return
}
diff --git a/pkg/api/handlers/libpod/volumes.go b/pkg/api/handlers/libpod/volumes.go
index 7e7e46718..9b10ee890 100644
--- a/pkg/api/handlers/libpod/volumes.go
+++ b/pkg/api/handlers/libpod/volumes.go
@@ -3,9 +3,11 @@ package libpod
import (
"encoding/json"
"net/http"
+ "strings"
"github.com/containers/libpod/cmd/podman/shared"
"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/schema"
@@ -29,7 +31,6 @@ func CreateVolume(w http.ResponseWriter, r *http.Request) {
errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String()))
return
}
-
// decode params from body
if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
@@ -49,14 +50,21 @@ func CreateVolume(w http.ResponseWriter, r *http.Request) {
parsedOptions, err := shared.ParseVolumeOptions(input.Opts)
if err != nil {
utils.InternalServerError(w, err)
+ return
}
volumeOptions = append(volumeOptions, parsedOptions...)
}
vol, err := runtime.NewVolume(r.Context(), volumeOptions...)
if err != nil {
utils.InternalServerError(w, err)
+ return
+ }
+ config, err := vol.Config()
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
}
- utils.WriteResponse(w, http.StatusOK, vol.Name())
+ utils.WriteResponse(w, http.StatusOK, config)
}
func InspectVolume(w http.ResponseWriter, r *http.Request) {
@@ -76,25 +84,46 @@ func InspectVolume(w http.ResponseWriter, r *http.Request) {
}
func ListVolumes(w http.ResponseWriter, r *http.Request) {
- //var (
- // runtime = r.Context().Value("runtime").(*libpod.Runtime)
- // decoder = r.Context().Value("decoder").(*schema.Decoder)
- //)
- //query := struct {
- // Filter string `json:"filter"`
- //}{
- // // override any golang type defaults
- //}
- //
- //if err := decoder.Decode(&query, r.URL.Query()); err != nil {
- // utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
- // errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String()))
- // return
- //}
- /*
- This is all in main in cmd and needs to be extracted from there first.
- */
+ var (
+ decoder = r.Context().Value("decoder").(*schema.Decoder)
+ err error
+ runtime = r.Context().Value("runtime").(*libpod.Runtime)
+ volumeConfigs []*libpod.VolumeConfig
+ volumeFilters []libpod.VolumeFilter
+ )
+ query := struct {
+ Filters map[string][]string `schema:"filters"`
+ }{
+ // override any golang type defaults
+ }
+
+ if err := decoder.Decode(&query, r.URL.Query()); err != nil {
+ utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
+ errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String()))
+ return
+ }
+ if len(query.Filters) > 0 {
+ volumeFilters, err = generateVolumeFilters(query.Filters)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ }
+ vols, err := runtime.Volumes(volumeFilters...)
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ for _, v := range vols {
+ config, err := v.Config()
+ if err != nil {
+ utils.InternalServerError(w, err)
+ return
+ }
+ volumeConfigs = append(volumeConfigs, config)
+ }
+ utils.WriteResponse(w, http.StatusOK, volumeConfigs)
}
func PruneVolumes(w http.ResponseWriter, r *http.Request) {
@@ -133,9 +162,77 @@ func RemoveVolume(w http.ResponseWriter, r *http.Request) {
vol, err := runtime.LookupVolume(name)
if err != nil {
utils.VolumeNotFound(w, name, err)
+ return
}
if err := runtime.RemoveVolume(r.Context(), vol, query.Force); err != nil {
+ if errors.Cause(err) == define.ErrVolumeBeingUsed {
+ utils.Error(w, "volumes being used", http.StatusConflict, err)
+ return
+ }
utils.InternalServerError(w, err)
+ return
}
utils.WriteResponse(w, http.StatusNoContent, "")
}
+
+func generateVolumeFilters(filters map[string][]string) ([]libpod.VolumeFilter, error) {
+ var vf []libpod.VolumeFilter
+ for filter, v := range filters {
+ for _, val := range v {
+ switch filter {
+ case "name":
+ nameVal := val
+ vf = append(vf, func(v *libpod.Volume) bool {
+ return nameVal == v.Name()
+ })
+ case "driver":
+ driverVal := val
+ vf = append(vf, func(v *libpod.Volume) bool {
+ return v.Driver() == driverVal
+ })
+ case "scope":
+ scopeVal := val
+ vf = append(vf, func(v *libpod.Volume) bool {
+ return v.Scope() == scopeVal
+ })
+ case "label":
+ filterArray := strings.SplitN(val, "=", 2)
+ filterKey := filterArray[0]
+ var filterVal string
+ if len(filterArray) > 1 {
+ filterVal = filterArray[1]
+ } else {
+ filterVal = ""
+ }
+ vf = append(vf, func(v *libpod.Volume) bool {
+ for labelKey, labelValue := range v.Labels() {
+ if labelKey == filterKey && ("" == filterVal || labelValue == filterVal) {
+ return true
+ }
+ }
+ return false
+ })
+ case "opt":
+ filterArray := strings.SplitN(val, "=", 2)
+ filterKey := filterArray[0]
+ var filterVal string
+ if len(filterArray) > 1 {
+ filterVal = filterArray[1]
+ } else {
+ filterVal = ""
+ }
+ vf = append(vf, func(v *libpod.Volume) bool {
+ for labelKey, labelValue := range v.Options() {
+ if labelKey == filterKey && ("" == filterVal || labelValue == filterVal) {
+ return true
+ }
+ }
+ return false
+ })
+ default:
+ return nil, errors.Errorf("%q is in an invalid volume filter", filter)
+ }
+ }
+ }
+ return vf, nil
+}