github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/pkg/api/handlers/libpod/volumes.go (about)

     1  package libpod
     2  
     3  import (
     4  	"encoding/json"
     5  	"net/http"
     6  
     7  	"github.com/containers/libpod/cmd/podman/shared"
     8  	"github.com/containers/libpod/libpod"
     9  	"github.com/containers/libpod/libpod/define"
    10  	"github.com/containers/libpod/pkg/api/handlers/utils"
    11  	"github.com/containers/libpod/pkg/domain/entities"
    12  	"github.com/containers/libpod/pkg/domain/filters"
    13  	"github.com/gorilla/schema"
    14  	"github.com/pkg/errors"
    15  )
    16  
    17  func CreateVolume(w http.ResponseWriter, r *http.Request) {
    18  	var (
    19  		volumeOptions []libpod.VolumeCreateOption
    20  		runtime       = r.Context().Value("runtime").(*libpod.Runtime)
    21  		decoder       = r.Context().Value("decoder").(*schema.Decoder)
    22  	)
    23  	query := struct {
    24  	}{
    25  		// override any golang type defaults
    26  	}
    27  	input := entities.VolumeCreateOptions{}
    28  	if err := decoder.Decode(&query, r.URL.Query()); err != nil {
    29  		utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
    30  			errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String()))
    31  		return
    32  	}
    33  	// decode params from body
    34  	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
    35  		utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
    36  		return
    37  	}
    38  
    39  	if len(input.Name) > 0 {
    40  		volumeOptions = append(volumeOptions, libpod.WithVolumeName(input.Name))
    41  	}
    42  	if len(input.Driver) > 0 {
    43  		volumeOptions = append(volumeOptions, libpod.WithVolumeDriver(input.Driver))
    44  	}
    45  	if len(input.Label) > 0 {
    46  		volumeOptions = append(volumeOptions, libpod.WithVolumeLabels(input.Label))
    47  	}
    48  	if len(input.Options) > 0 {
    49  		parsedOptions, err := shared.ParseVolumeOptions(input.Options)
    50  		if err != nil {
    51  			utils.InternalServerError(w, err)
    52  			return
    53  		}
    54  		volumeOptions = append(volumeOptions, parsedOptions...)
    55  	}
    56  	vol, err := runtime.NewVolume(r.Context(), volumeOptions...)
    57  	if err != nil {
    58  		utils.InternalServerError(w, err)
    59  		return
    60  	}
    61  	config, err := vol.Config()
    62  	if err != nil {
    63  		utils.InternalServerError(w, err)
    64  		return
    65  	}
    66  	volResponse := entities.VolumeConfigResponse{
    67  		Name:       config.Name,
    68  		Driver:     config.Driver,
    69  		Mountpoint: config.MountPoint,
    70  		CreatedAt:  config.CreatedTime,
    71  		Labels:     config.Labels,
    72  		Options:    config.Options,
    73  		UID:        config.UID,
    74  		GID:        config.GID,
    75  	}
    76  	utils.WriteResponse(w, http.StatusOK, volResponse)
    77  }
    78  
    79  func InspectVolume(w http.ResponseWriter, r *http.Request) {
    80  	var (
    81  		runtime = r.Context().Value("runtime").(*libpod.Runtime)
    82  	)
    83  	name := utils.GetName(r)
    84  	vol, err := runtime.GetVolume(name)
    85  	if err != nil {
    86  		utils.VolumeNotFound(w, name, err)
    87  		return
    88  	}
    89  	volResponse := entities.VolumeConfigResponse{
    90  		Name:       vol.Name(),
    91  		Driver:     vol.Driver(),
    92  		Mountpoint: vol.MountPoint(),
    93  		CreatedAt:  vol.CreatedTime(),
    94  		Labels:     vol.Labels(),
    95  		Scope:      vol.Scope(),
    96  		Options:    vol.Options(),
    97  		UID:        vol.UID(),
    98  		GID:        vol.GID(),
    99  	}
   100  	utils.WriteResponse(w, http.StatusOK, volResponse)
   101  }
   102  
   103  func ListVolumes(w http.ResponseWriter, r *http.Request) {
   104  	var (
   105  		decoder       = r.Context().Value("decoder").(*schema.Decoder)
   106  		runtime       = r.Context().Value("runtime").(*libpod.Runtime)
   107  		volumeConfigs []*entities.VolumeListReport
   108  	)
   109  	query := struct {
   110  		Filters map[string][]string `schema:"filters"`
   111  	}{
   112  		// override any golang type defaults
   113  	}
   114  
   115  	if err := decoder.Decode(&query, r.URL.Query()); err != nil {
   116  		utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
   117  			errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String()))
   118  		return
   119  	}
   120  
   121  	volumeFilters, err := filters.GenerateVolumeFilters(query.Filters)
   122  	if err != nil {
   123  		utils.InternalServerError(w, err)
   124  		return
   125  	}
   126  
   127  	vols, err := runtime.Volumes(volumeFilters...)
   128  	if err != nil {
   129  		utils.InternalServerError(w, err)
   130  		return
   131  	}
   132  	for _, v := range vols {
   133  		config := entities.VolumeConfigResponse{
   134  			Name:       v.Name(),
   135  			Driver:     v.Driver(),
   136  			Mountpoint: v.MountPoint(),
   137  			CreatedAt:  v.CreatedTime(),
   138  			Labels:     v.Labels(),
   139  			Scope:      v.Scope(),
   140  			Options:    v.Options(),
   141  			UID:        v.UID(),
   142  			GID:        v.GID(),
   143  		}
   144  		volumeConfigs = append(volumeConfigs, &entities.VolumeListReport{VolumeConfigResponse: config})
   145  	}
   146  	utils.WriteResponse(w, http.StatusOK, volumeConfigs)
   147  }
   148  
   149  func PruneVolumes(w http.ResponseWriter, r *http.Request) {
   150  	var (
   151  		runtime = r.Context().Value("runtime").(*libpod.Runtime)
   152  		reports []*entities.VolumePruneReport
   153  	)
   154  	pruned, err := runtime.PruneVolumes(r.Context())
   155  	if err != nil {
   156  		utils.InternalServerError(w, err)
   157  		return
   158  	}
   159  	for k, v := range pruned {
   160  		reports = append(reports, &entities.VolumePruneReport{
   161  			Err: v,
   162  			Id:  k,
   163  		})
   164  	}
   165  	utils.WriteResponse(w, http.StatusOK, reports)
   166  }
   167  
   168  func RemoveVolume(w http.ResponseWriter, r *http.Request) {
   169  	var (
   170  		runtime = r.Context().Value("runtime").(*libpod.Runtime)
   171  		decoder = r.Context().Value("decoder").(*schema.Decoder)
   172  	)
   173  	query := struct {
   174  		Force bool `schema:"force"`
   175  	}{
   176  		// override any golang type defaults
   177  	}
   178  
   179  	if err := decoder.Decode(&query, r.URL.Query()); err != nil {
   180  		utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
   181  			errors.Wrapf(err, "Failed to parse parameters for %s", r.URL.String()))
   182  		return
   183  	}
   184  	name := utils.GetName(r)
   185  	vol, err := runtime.LookupVolume(name)
   186  	if err != nil {
   187  		utils.VolumeNotFound(w, name, err)
   188  		return
   189  	}
   190  	if err := runtime.RemoveVolume(r.Context(), vol, query.Force); err != nil {
   191  		if errors.Cause(err) == define.ErrVolumeBeingUsed {
   192  			utils.Error(w, "volumes being used", http.StatusConflict, err)
   193  			return
   194  		}
   195  		utils.InternalServerError(w, err)
   196  		return
   197  	}
   198  	utils.WriteResponse(w, http.StatusNoContent, "")
   199  }