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 }