summaryrefslogtreecommitdiff
path: root/pkg/api
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/api')
-rw-r--r--pkg/api/handlers/libpod/volumes.go137
-rw-r--r--pkg/api/handlers/types.go13
-rw-r--r--pkg/api/server/register_volumes.go43
-rw-r--r--pkg/api/server/swagger.go17
4 files changed, 178 insertions, 32 deletions
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
+}
diff --git a/pkg/api/handlers/types.go b/pkg/api/handlers/types.go
index c72b0f817..2930a9567 100644
--- a/pkg/api/handlers/types.go
+++ b/pkg/api/handlers/types.go
@@ -128,11 +128,16 @@ type CreateContainerConfig struct {
NetworkingConfig dockerNetwork.NetworkingConfig
}
+// swagger:model VolumeCreate
type VolumeCreateConfig struct {
- Name string `json:"name"`
- Driver string `schema:"driver"`
- Label map[string]string `schema:"label"`
- Opts map[string]string `schema:"opts"`
+ // New volume's name. Can be left blank
+ Name string `schema:"name"`
+ // Volume driver to use
+ Driver string `schema:"driver"`
+ // User-defined key/value metadata.
+ Label map[string]string `schema:"label"`
+ // Mapping of driver options and values.
+ Opts map[string]string `schema:"opts"`
}
type IDResponse struct {
diff --git a/pkg/api/server/register_volumes.go b/pkg/api/server/register_volumes.go
index efe56a3ad..d1317904b 100644
--- a/pkg/api/server/register_volumes.go
+++ b/pkg/api/server/register_volumes.go
@@ -11,15 +11,42 @@ func (s *APIServer) registerVolumeHandlers(r *mux.Router) error {
// swagger:operation POST /libpod/volumes/create volumes createVolume
// ---
// summary: Create a volume
+ // parameters:
+ // - in: body
+ // name: create
+ // description: attributes for creating a container
+ // schema:
+ // $ref: "#/definitions/VolumeCreate"
+ // produces:
+ // - application/json
+ // responses:
+ // '201':
+ // $ref: "#/responses/VolumeCreateResponse"
+ // '500':
+ // "$ref": "#/responses/InternalError"
+ r.Handle(VersionedPath("/libpod/volumes/create"), s.APIHandler(libpod.CreateVolume)).Methods(http.MethodPost)
+ // swagger:operation POST /libpod/volumes/json volumes listVolumes
+ // ---
+ // summary: List volumes
+ // description: Returns a list of networks
// produces:
// - application/json
+ // parameters:
+ // - in: query
+ // name: filters
+ // type: string
+ // description: |
+ // JSON encoded value of the filters (a map[string][]string) to process on the networks list. Available filters:
+ // - driver=<volume-driver-name> Matches volumes based on their driver.
+ // - label=<key> or label=<key>:<value> Matches volumes based on the presence of a label alone or a label and a value.
+ // - name=<volume-name> Matches all of volume name.
+ // - opt=<driver-option> Matches a storage driver options
// responses:
// '200':
- // description: tbd
+ // "$ref": "#/responses/VolumeList"
// '500':
// "$ref": "#/responses/InternalError"
- r.Handle("/libpod/volumes/create", s.APIHandler(libpod.CreateVolume)).Methods(http.MethodPost)
- r.Handle("/libpod/volumes/json", s.APIHandler(libpod.ListVolumes)).Methods(http.MethodGet)
+ r.Handle(VersionedPath("/libpod/volumes/json"), s.APIHandler(libpod.ListVolumes)).Methods(http.MethodGet)
// swagger:operation POST /libpod/volumes/prune volumes pruneVolumes
// ---
// summary: Prune volumes
@@ -30,7 +57,7 @@ func (s *APIServer) registerVolumeHandlers(r *mux.Router) error {
// description: no error
// '500':
// "$ref": "#/responses/InternalError"
- r.Handle("/libpod/volumes/prune", s.APIHandler(libpod.PruneVolumes)).Methods(http.MethodPost)
+ r.Handle(VersionedPath("/libpod/volumes/prune"), s.APIHandler(libpod.PruneVolumes)).Methods(http.MethodPost)
// swagger:operation GET /libpod/volumes/{name}/json volumes inspectVolume
// ---
// summary: Inspect volume
@@ -49,7 +76,7 @@ func (s *APIServer) registerVolumeHandlers(r *mux.Router) error {
// "$ref": "#/responses/NoSuchVolume"
// '500':
// "$ref": "#/responses/InternalError"
- r.Handle("/libpod/volumes/{name}/json", s.APIHandler(libpod.InspectVolume)).Methods(http.MethodGet)
+ r.Handle(VersionedPath("/libpod/volumes/{name}/json"), s.APIHandler(libpod.InspectVolume)).Methods(http.MethodGet)
// swagger:operation DELETE /libpod/volumes/{name} volumes removeVolume
// ---
// summary: Remove volume
@@ -68,12 +95,12 @@ func (s *APIServer) registerVolumeHandlers(r *mux.Router) error {
// responses:
// 204:
// description: no error
- // 400:
- // $ref: "#/responses/BadParamError"
// 404:
// $ref: "#/responses/NoSuchVolume"
+ // 409:
+ // description: Volume is in use and cannot be removed
// 500:
// $ref: "#/responses/InternalError"
- r.Handle("/libpod/volumes/{name}", s.APIHandler(libpod.RemoveVolume)).Methods(http.MethodDelete)
+ r.Handle(VersionedPath("/libpod/volumes/{name}"), s.APIHandler(libpod.RemoveVolume)).Methods(http.MethodDelete)
return nil
}
diff --git a/pkg/api/server/swagger.go b/pkg/api/server/swagger.go
index fc409d816..011196e5a 100644
--- a/pkg/api/server/swagger.go
+++ b/pkg/api/server/swagger.go
@@ -1,6 +1,7 @@
package server
import (
+ "github.com/containers/libpod/libpod"
"github.com/containers/libpod/pkg/api/handlers"
"github.com/containers/libpod/pkg/api/handlers/utils"
)
@@ -139,3 +140,19 @@ type ok struct {
ok string
}
}
+
+// Volume create response
+// swagger:response VolumeCreateResponse
+type swagVolumeCreateResponse struct {
+ // in:body
+ Body struct {
+ libpod.VolumeConfig
+ }
+}
+
+// Volume list
+// swagger:response VolumeList
+type swagVolumeListResponse struct {
+ // in:body
+ Body []libpod.Volume
+}