Remove deprecated keep-storage parameter from /build/prune API

- Remove keep-storage parameter from swagger.yaml API specification
- Remove KeepStorage field from CachePruneOptions struct
- Remove client-side logic for setting keep-storage query parameter
- Remove server-side fallback logic for keep-storage in API v1.49+
- Remove backward compatibility logic in builder.go
- Add comprehensive tests to validate keep-storage is no longer sent
- Maintain backward compatibility for API versions < v1.49

Co-authored-by: vvoland <5046555+vvoland@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2025-08-14 13:00:36 +00:00
parent 56b3c83168
commit bda984d120
6 changed files with 144 additions and 17 deletions

View File

@@ -9358,15 +9358,7 @@ paths:
- "application/json"
operationId: "BuildPrune"
parameters:
- name: "keep-storage"
in: "query"
description: |
Amount of disk space in bytes to keep for cache
> **Deprecated**: This parameter is deprecated and has been renamed to "reserved-space".
> It is kept for backward compatibility and will be removed in API v1.49.
type: "integer"
format: "int64"
- name: "reserved-space"
in: "query"
description: "Amount of disk space in bytes to keep for cache"

View File

@@ -40,8 +40,6 @@ type CachePruneOptions struct {
MaxUsedSpace int64
MinFreeSpace int64
Filters filters.Args
KeepStorage int64 // Deprecated: deprecated in API 1.48.
}
// CachePruneReport contains the response for Engine API:

View File

@@ -22,9 +22,6 @@ func (cli *Client) BuildCachePrune(ctx context.Context, opts build.CachePruneOpt
query.Set("all", "1")
}
if opts.KeepStorage != 0 {
query.Set("keep-storage", strconv.Itoa(int(opts.KeepStorage)))
}
if opts.ReservedSpace != 0 {
query.Set("reserved-space", strconv.Itoa(int(opts.ReservedSpace)))
}

123
client/build_prune_test.go Normal file
View File

@@ -0,0 +1,123 @@
package client
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"testing"
cerrdefs "github.com/containerd/errdefs"
"github.com/moby/moby/api/types/build"
"github.com/moby/moby/api/types/filters"
"gotest.tools/v3/assert"
is "gotest.tools/v3/assert/cmp"
)
func TestBuildCachePruneError(t *testing.T) {
client := &Client{
client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")),
version: "1.31",
}
_, err := client.BuildCachePrune(context.Background(), build.CachePruneOptions{})
assert.Check(t, is.ErrorType(err, cerrdefs.IsInternal))
}
func TestBuildCachePrune(t *testing.T) {
expectedURL := "/v1.31/build/prune"
testCases := []struct {
options build.CachePruneOptions
expectedQueryParams map[string]string
}{
{
options: build.CachePruneOptions{},
expectedQueryParams: map[string]string{
"all": "",
"filters": "",
"reserved-space": "",
"max-used-space": "",
"min-free-space": "",
},
},
{
options: build.CachePruneOptions{
All: true,
},
expectedQueryParams: map[string]string{
"all": "1",
"filters": "",
"reserved-space": "",
"max-used-space": "",
"min-free-space": "",
},
},
{
options: build.CachePruneOptions{
ReservedSpace: 1024,
MaxUsedSpace: 2048,
MinFreeSpace: 512,
},
expectedQueryParams: map[string]string{
"all": "",
"filters": "",
"reserved-space": "1024",
"max-used-space": "2048",
"min-free-space": "512",
},
},
{
options: build.CachePruneOptions{
Filters: filters.NewArgs(filters.Arg("unused-for", "24h")),
},
expectedQueryParams: map[string]string{
"all": "",
"filters": `{"unused-for":{"24h":true}}`,
"reserved-space": "",
"max-used-space": "",
"min-free-space": "",
},
},
}
for _, testCase := range testCases {
client := &Client{
client: newMockClient(func(req *http.Request) (*http.Response, error) {
if !strings.HasPrefix(req.URL.Path, expectedURL) {
return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, req.URL)
}
query := req.URL.Query()
for key, expected := range testCase.expectedQueryParams {
actual := query.Get(key)
if actual != expected {
return nil, fmt.Errorf("Expected '%s' for '%s', got '%s'", expected, key, actual)
}
}
// Ensure keep-storage parameter is NOT present
if query.Get("keep-storage") != "" {
return nil, fmt.Errorf("keep-storage parameter should not be present, but found: %s", query.Get("keep-storage"))
}
report := build.CachePruneReport{
CachesDeleted: []string{"cache1", "cache2"},
SpaceReclaimed: 12345,
}
b, err := json.Marshal(report)
if err != nil {
return nil, err
}
return &http.Response{
StatusCode: http.StatusOK,
Body: io.NopCloser(bytes.NewReader(b)),
}, nil
}),
version: "1.31",
}
_, err := client.BuildCachePrune(context.Background(), testCase.options)
assert.NilError(t, err)
}
}

View File

@@ -696,9 +696,6 @@ func toBuildkitPruneInfo(opts build.CachePruneOptions) (client.PruneInfo, error)
}
}
if opts.ReservedSpace == 0 && opts.KeepStorage != 0 {
opts.ReservedSpace = opts.KeepStorage
}
return client.PruneInfo{
All: opts.All,

View File

@@ -196,7 +196,27 @@ func (br *buildRouter) postPrune(ctx context.Context, w http.ResponseWriter, r *
}
version := httputils.VersionFromContext(ctx)
if versions.GreaterThanOrEqualTo(version, "1.48") {
if versions.GreaterThanOrEqualTo(version, "1.49") {
// API v1.49+ only supports the new parameters, keep-storage was removed
if bs, err := parseBytesFromFormValue("reserved-space"); err != nil {
return err
} else {
opts.ReservedSpace = bs
}
if bs, err := parseBytesFromFormValue("max-used-space"); err != nil {
return err
} else {
opts.MaxUsedSpace = bs
}
if bs, err := parseBytesFromFormValue("min-free-space"); err != nil {
return err
} else {
opts.MinFreeSpace = bs
}
} else if versions.GreaterThanOrEqualTo(version, "1.48") {
// API v1.48 supports both new and deprecated parameters for backward compatibility
if bs, err := parseBytesFromFormValue("reserved-space"); err != nil {
return err
} else {