github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/pkg/api/handlers/libpod/volumes.go (about)

     1  package libpod
     2  
     3  import (
     4  	"encoding/json"
     5  	"net/http"
     6  	"net/url"
     7  
     8  	"github.com/hanks177/podman/v4/libpod"
     9  	"github.com/hanks177/podman/v4/libpod/define"
    10  	"github.com/hanks177/podman/v4/pkg/api/handlers/utils"
    11  	api "github.com/hanks177/podman/v4/pkg/api/types"
    12  	"github.com/hanks177/podman/v4/pkg/domain/entities"
    13  	"github.com/hanks177/podman/v4/pkg/domain/entities/reports"
    14  	"github.com/hanks177/podman/v4/pkg/domain/filters"
    15  	"github.com/hanks177/podman/v4/pkg/domain/infra/abi"
    16  	"github.com/hanks177/podman/v4/pkg/domain/infra/abi/parse"
    17  	"github.com/hanks177/podman/v4/pkg/util"
    18  	"github.com/gorilla/schema"
    19  	"github.com/pkg/errors"
    20  )
    21  
    22  func CreateVolume(w http.ResponseWriter, r *http.Request) {
    23  	var (
    24  		volumeOptions []libpod.VolumeCreateOption
    25  		runtime       = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
    26  		decoder       = r.Context().Value(api.DecoderKey).(*schema.Decoder)
    27  	)
    28  	query := struct{}{
    29  		// override any golang type defaults
    30  	}
    31  	if err := decoder.Decode(&query, r.URL.Query()); err != nil {
    32  		utils.Error(w, http.StatusInternalServerError,
    33  			errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
    34  		return
    35  	}
    36  
    37  	input := entities.VolumeCreateOptions{}
    38  	// decode params from body
    39  	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
    40  		utils.Error(w, http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
    41  		return
    42  	}
    43  
    44  	if len(input.Name) > 0 {
    45  		volumeOptions = append(volumeOptions, libpod.WithVolumeName(input.Name))
    46  	}
    47  	if len(input.Driver) > 0 {
    48  		volumeOptions = append(volumeOptions, libpod.WithVolumeDriver(input.Driver))
    49  	}
    50  
    51  	// Label provided for compatibility.
    52  	labels := make(map[string]string, len(input.Label)+len(input.Labels))
    53  	for k, v := range input.Label {
    54  		labels[k] = v
    55  	}
    56  	for k, v := range input.Labels {
    57  		labels[k] = v
    58  	}
    59  	if len(labels) > 0 {
    60  		volumeOptions = append(volumeOptions, libpod.WithVolumeLabels(labels))
    61  	}
    62  
    63  	if len(input.Options) > 0 {
    64  		parsedOptions, err := parse.VolumeOptions(input.Options)
    65  		if err != nil {
    66  			utils.InternalServerError(w, err)
    67  			return
    68  		}
    69  		volumeOptions = append(volumeOptions, parsedOptions...)
    70  	}
    71  	vol, err := runtime.NewVolume(r.Context(), volumeOptions...)
    72  	if err != nil {
    73  		utils.InternalServerError(w, err)
    74  		return
    75  	}
    76  	inspectOut, err := vol.Inspect()
    77  	if err != nil {
    78  		utils.InternalServerError(w, err)
    79  		return
    80  	}
    81  	volResponse := entities.VolumeConfigResponse{
    82  		InspectVolumeData: *inspectOut,
    83  	}
    84  	utils.WriteResponse(w, http.StatusCreated, volResponse)
    85  }
    86  
    87  func InspectVolume(w http.ResponseWriter, r *http.Request) {
    88  	runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
    89  	name := utils.GetName(r)
    90  	vol, err := runtime.GetVolume(name)
    91  	if err != nil {
    92  		utils.VolumeNotFound(w, name, err)
    93  		return
    94  	}
    95  	inspectOut, err := vol.Inspect()
    96  	if err != nil {
    97  		utils.InternalServerError(w, err)
    98  		return
    99  	}
   100  	volResponse := entities.VolumeConfigResponse{
   101  		InspectVolumeData: *inspectOut,
   102  	}
   103  	utils.WriteResponse(w, http.StatusOK, volResponse)
   104  }
   105  
   106  func ListVolumes(w http.ResponseWriter, r *http.Request) {
   107  	runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
   108  	filterMap, err := util.PrepareFilters(r)
   109  	if err != nil {
   110  		utils.Error(w, http.StatusInternalServerError,
   111  			errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
   112  		return
   113  	}
   114  
   115  	volumeFilters, err := filters.GenerateVolumeFilters(*filterMap)
   116  	if err != nil {
   117  		utils.InternalServerError(w, err)
   118  		return
   119  	}
   120  
   121  	vols, err := runtime.Volumes(volumeFilters...)
   122  	if err != nil {
   123  		utils.InternalServerError(w, err)
   124  		return
   125  	}
   126  	volumeConfigs := make([]*entities.VolumeListReport, 0, len(vols))
   127  	for _, v := range vols {
   128  		inspectOut, err := v.Inspect()
   129  		if err != nil {
   130  			utils.InternalServerError(w, err)
   131  			return
   132  		}
   133  		config := entities.VolumeConfigResponse{
   134  			InspectVolumeData: *inspectOut,
   135  		}
   136  		volumeConfigs = append(volumeConfigs, &entities.VolumeListReport{VolumeConfigResponse: config})
   137  	}
   138  	utils.WriteResponse(w, http.StatusOK, volumeConfigs)
   139  }
   140  
   141  func PruneVolumes(w http.ResponseWriter, r *http.Request) {
   142  	reports, err := pruneVolumesHelper(r)
   143  	if err != nil {
   144  		utils.InternalServerError(w, err)
   145  		return
   146  	}
   147  	utils.WriteResponse(w, http.StatusOK, reports)
   148  }
   149  
   150  func pruneVolumesHelper(r *http.Request) ([]*reports.PruneReport, error) {
   151  	runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
   152  	filterMap, err := util.PrepareFilters(r)
   153  	if err != nil {
   154  		return nil, err
   155  	}
   156  
   157  	f := (url.Values)(*filterMap)
   158  	filterFuncs, err := filters.GeneratePruneVolumeFilters(f)
   159  	if err != nil {
   160  		return nil, err
   161  	}
   162  
   163  	reports, err := runtime.PruneVolumes(r.Context(), filterFuncs)
   164  	if err != nil {
   165  		return nil, err
   166  	}
   167  	return reports, nil
   168  }
   169  
   170  func RemoveVolume(w http.ResponseWriter, r *http.Request) {
   171  	var (
   172  		runtime = r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
   173  		decoder = r.Context().Value(api.DecoderKey).(*schema.Decoder)
   174  	)
   175  	query := struct {
   176  		Force   bool  `schema:"force"`
   177  		Timeout *uint `schema:"timeout"`
   178  	}{
   179  		// override any golang type defaults
   180  	}
   181  
   182  	if err := decoder.Decode(&query, r.URL.Query()); err != nil {
   183  		utils.Error(w, http.StatusInternalServerError,
   184  			errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
   185  		return
   186  	}
   187  	name := utils.GetName(r)
   188  	vol, err := runtime.LookupVolume(name)
   189  	if err != nil {
   190  		utils.VolumeNotFound(w, name, err)
   191  		return
   192  	}
   193  	if err := runtime.RemoveVolume(r.Context(), vol, query.Force, query.Timeout); err != nil {
   194  		if errors.Cause(err) == define.ErrVolumeBeingUsed {
   195  			utils.Error(w, http.StatusConflict, err)
   196  			return
   197  		}
   198  		utils.InternalServerError(w, err)
   199  		return
   200  	}
   201  	utils.WriteResponse(w, http.StatusNoContent, "")
   202  }
   203  
   204  // ExistsVolume check if a volume exists
   205  func ExistsVolume(w http.ResponseWriter, r *http.Request) {
   206  	runtime := r.Context().Value(api.RuntimeKey).(*libpod.Runtime)
   207  	name := utils.GetName(r)
   208  
   209  	ic := abi.ContainerEngine{Libpod: runtime}
   210  	report, err := ic.VolumeExists(r.Context(), name)
   211  	if err != nil {
   212  		utils.Error(w, http.StatusInternalServerError, err)
   213  		return
   214  	}
   215  	if !report.Value {
   216  		utils.Error(w, http.StatusNotFound, define.ErrNoSuchVolume)
   217  		return
   218  	}
   219  	utils.WriteResponse(w, http.StatusNoContent, "")
   220  }