Skip to content

Commit

Permalink
Restore compatible API for prune endpoints
Browse files Browse the repository at this point in the history
* Restore correct API endpoint payloads including reclaimed space numbers
* Include tests for API prune endpoints
* Clean up function signatures with unused parameters
* Update swagger for /networks/prune

Fixes containers#8891

Signed-off-by: Jhon Honce <[email protected]>
  • Loading branch information
jwhonce committed Jan 7, 2021
1 parent 78cda71 commit b059e10
Show file tree
Hide file tree
Showing 8 changed files with 201 additions and 76 deletions.
44 changes: 29 additions & 15 deletions pkg/api/handlers/compat/containers_prune.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package compat

import (
"bytes"
"net/http"

"github.com/containers/podman/v2/libpod"
"github.com/containers/podman/v2/pkg/api/handlers"
"github.com/containers/podman/v2/pkg/api/handlers/utils"
"github.com/containers/podman/v2/pkg/domain/entities/reports"
"github.com/containers/podman/v2/pkg/domain/filters"
Expand Down Expand Up @@ -32,33 +34,45 @@ func PruneContainers(w http.ResponseWriter, r *http.Request) {
filterFuncs = append(filterFuncs, generatedFunc)
}

report, err := PruneContainersHelper(r, filterFuncs)
if err != nil {
utils.InternalServerError(w, err)
return
}

// Libpod response differs
if utils.IsLibpodRequest(r) {
report, err := PruneContainersHelper(w, r, filterFuncs)
if err != nil {
utils.InternalServerError(w, err)
return
}

utils.WriteResponse(w, http.StatusOK, report)
return
}

report, err := runtime.PruneContainers(filterFuncs)
if err != nil {
utils.InternalServerError(w, err)
var payload handlers.ContainersPruneReport
var errorMsg bytes.Buffer
for _, pr := range report {
if pr.Err != nil {
// Docker stops on first error vs. libpod which keeps going. Given API constraints, concatenate all errors
// and return that string.
errorMsg.WriteString(pr.Err.Error())
errorMsg.WriteString("; ")
continue
}
payload.ContainersDeleted = append(payload.ContainersDeleted, pr.Id)
payload.SpaceReclaimed += pr.Size
}
if errorMsg.Len() > 0 {
utils.InternalServerError(w, errors.New(errorMsg.String()))
return
}
utils.WriteResponse(w, http.StatusOK, report)

utils.WriteResponse(w, http.StatusOK, payload)
}

func PruneContainersHelper(w http.ResponseWriter, r *http.Request, filterFuncs []libpod.ContainerFilter) (
[]*reports.PruneReport, error) {
func PruneContainersHelper(r *http.Request, filterFuncs []libpod.ContainerFilter) ([]*reports.PruneReport, error) {
runtime := r.Context().Value("runtime").(*libpod.Runtime)
reports, err := runtime.PruneContainers(filterFuncs)

report, err := runtime.PruneContainers(filterFuncs)
if err != nil {
utils.InternalServerError(w, err)
return nil, err
}
return reports, nil
return report, nil
}
47 changes: 0 additions & 47 deletions pkg/api/handlers/compat/images.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import (
"github.com/containers/podman/v2/pkg/api/handlers/utils"
"github.com/containers/podman/v2/pkg/auth"
"github.com/containers/podman/v2/pkg/domain/entities"
"github.com/docker/docker/api/types"
"github.com/gorilla/schema"
"github.com/opencontainers/go-digest"
"github.com/pkg/errors"
Expand Down Expand Up @@ -74,52 +73,6 @@ func ExportImage(w http.ResponseWriter, r *http.Request) {
utils.WriteResponse(w, http.StatusOK, rdr)
}

func PruneImages(w http.ResponseWriter, r *http.Request) {
var (
filters []string
)
decoder := r.Context().Value("decoder").(*schema.Decoder)
runtime := r.Context().Value("runtime").(*libpod.Runtime)

query := struct {
All bool
Filters map[string][]string `schema:"filters"`
}{
// This is where you can override the golang default value for one of fields
}

if err := decoder.Decode(&query, r.URL.Query()); err != nil {
utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}

idr := []types.ImageDeleteResponseItem{}
for k, v := range query.Filters {
for _, val := range v {
filters = append(filters, fmt.Sprintf("%s=%s", k, val))
}
}
imagePruneReports, err := runtime.ImageRuntime().PruneImages(r.Context(), query.All, filters)
if err != nil {
utils.InternalServerError(w, err)
return
}
reclaimedSpace := uint64(0)
for _, p := range imagePruneReports {
idr = append(idr, types.ImageDeleteResponseItem{
Deleted: p.Id,
})
reclaimedSpace = reclaimedSpace + p.Size
}

// FIXME/TODO to do this exactly correct, pruneimages needs to return idrs and space-reclaimed, then we are golden
ipr := types.ImagesPruneReport{
ImagesDeleted: idr,
SpaceReclaimed: reclaimedSpace,
}
utils.WriteResponse(w, http.StatusOK, handlers.ImagesPruneReport{ImagesPruneReport: ipr})
}

func CommitContainer(w http.ResponseWriter, r *http.Request) {
var (
destImage string
Expand Down
75 changes: 75 additions & 0 deletions pkg/api/handlers/compat/images_prune.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package compat

import (
"bytes"
"fmt"
"net/http"

"github.com/containers/podman/v2/libpod"
"github.com/containers/podman/v2/pkg/api/handlers"
"github.com/containers/podman/v2/pkg/api/handlers/utils"
"github.com/docker/docker/api/types"
"github.com/gorilla/schema"
"github.com/pkg/errors"
)

func PruneImages(w http.ResponseWriter, r *http.Request) {
var (
filters []string
)
decoder := r.Context().Value("decoder").(*schema.Decoder)
runtime := r.Context().Value("runtime").(*libpod.Runtime)

query := struct {
All bool
Filters map[string][]string `schema:"filters"`
}{
// This is where you can override the golang default value for one of fields
}

if err := decoder.Decode(&query, r.URL.Query()); err != nil {
utils.Error(w, "Something went wrong.", http.StatusBadRequest, errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
return
}

for k, v := range query.Filters {
for _, val := range v {
filters = append(filters, fmt.Sprintf("%s=%s", k, val))
}
}
imagePruneReports, err := runtime.ImageRuntime().PruneImages(r.Context(), query.All, filters)
if err != nil {
utils.InternalServerError(w, err)
return
}

idr := make([]types.ImageDeleteResponseItem, len(imagePruneReports))
var reclaimedSpace uint64
var errorMsg bytes.Buffer
for _, p := range imagePruneReports {
if p.Err != nil {
// Docker stops on first error vs. libpod which keeps going. Given API constraints, concatenate all errors
// and return that string.
errorMsg.WriteString(p.Err.Error())
errorMsg.WriteString("; ")
continue
}

idr = append(idr, types.ImageDeleteResponseItem{
Deleted: p.Id,
})
reclaimedSpace = reclaimedSpace + p.Size
}
if errorMsg.Len() > 0 {
utils.InternalServerError(w, errors.New(errorMsg.String()))
return
}

payload := handlers.ImagesPruneReport{
ImagesPruneReport: types.ImagesPruneReport{
ImagesDeleted: idr,
SpaceReclaimed: reclaimedSpace,
},
}
utils.WriteResponse(w, http.StatusOK, payload)
}
28 changes: 21 additions & 7 deletions pkg/api/handlers/compat/volumes.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package compat

import (
"bytes"
"encoding/json"
"net/http"
"net/url"
"time"

"github.com/containers/podman/v2/libpod"
"github.com/containers/podman/v2/libpod/define"
"github.com/containers/podman/v2/pkg/api/handlers"
"github.com/containers/podman/v2/pkg/api/handlers/utils"
"github.com/containers/podman/v2/pkg/domain/filters"
"github.com/containers/podman/v2/pkg/domain/infra/abi/parse"
Expand Down Expand Up @@ -268,17 +270,29 @@ func PruneVolumes(w http.ResponseWriter, r *http.Request) {
utils.InternalServerError(w, err)
return
}

var errorMsg bytes.Buffer
var reclaimedSpace uint64
prunedIds := make([]string, 0, len(pruned))
for _, v := range pruned {
// XXX: This drops any pruning per-volume error messages on the floor
if v.Err != nil {
errorMsg.WriteString(v.Err.Error())
errorMsg.WriteString("; ")
continue
}
prunedIds = append(prunedIds, v.Id)
reclaimedSpace += v.Size
}
pruneResponse := docker_api_types.VolumesPruneReport{
VolumesDeleted: prunedIds,
// TODO: We don't have any insight into how much space was reclaimed
// from `PruneVolumes()` but it's not nullable
SpaceReclaimed: 0,
if errorMsg.Len() > 0 {
utils.InternalServerError(w, errors.New(errorMsg.String()))
return
}

utils.WriteResponse(w, http.StatusOK, pruneResponse)
payload := handlers.VolumesPruneReport{
VolumesPruneReport: docker_api_types.VolumesPruneReport{
VolumesDeleted: prunedIds,
SpaceReclaimed: reclaimedSpace,
},
}
utils.WriteResponse(w, http.StatusOK, payload)
}
4 changes: 2 additions & 2 deletions pkg/api/handlers/libpod/pods.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,15 +235,15 @@ func PodRestart(w http.ResponseWriter, r *http.Request) {
}

func PodPrune(w http.ResponseWriter, r *http.Request) {
reports, err := PodPruneHelper(w, r)
reports, err := PodPruneHelper(r)
if err != nil {
utils.InternalServerError(w, err)
return
}
utils.WriteResponse(w, http.StatusOK, reports)
}

func PodPruneHelper(w http.ResponseWriter, r *http.Request) ([]*entities.PodPruneReport, error) {
func PodPruneHelper(r *http.Request) ([]*entities.PodPruneReport, error) {
var (
runtime = r.Context().Value("runtime").(*libpod.Runtime)
)
Expand Down
4 changes: 2 additions & 2 deletions pkg/api/handlers/libpod/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,15 @@ func SystemPrune(w http.ResponseWriter, r *http.Request) {
return
}

podPruneReport, err := PodPruneHelper(w, r)
podPruneReport, err := PodPruneHelper(r)
if err != nil {
utils.InternalServerError(w, err)
return
}
systemPruneReport.PodPruneReport = podPruneReport

// We could parallelize this, should we?
containerPruneReports, err := compat.PruneContainersHelper(w, r, nil)
containerPruneReports, err := compat.PruneContainersHelper(r, nil)
if err != nil {
utils.InternalServerError(w, err)
return
Expand Down
13 changes: 13 additions & 0 deletions pkg/api/server/register_networks.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,19 @@ import (
)

func (s *APIServer) registerNetworkHandlers(r *mux.Router) error {
// swagger:operation POST /networks/prune compat compatPruneNetwork
// ---
// tags:
// - networks (compat)
// Summary: Delete unused networks
// description: Not supported
// produces:
// - application/json
// responses:
// 404:
// $ref: "#/responses/NoSuchNetwork"
r.HandleFunc(VersionedPath("/networks/prune"), compat.UnsupportedHandler).Methods(http.MethodPost)
r.HandleFunc("/networks/prune", compat.UnsupportedHandler).Methods(http.MethodPost)
// swagger:operation DELETE /networks/{name} compat compatRemoveNetwork
// ---
// tags:
Expand Down
Loading

0 comments on commit b059e10

Please sign in to comment.