Browse Source

Merge pull request #45294 from vvoland/builder-fix-prune-timestamp

builder-next/prune: Handle `until` filter timestamps
Sebastiaan van Stijn 2 years ago
parent
commit
fd03a52468
3 changed files with 23 additions and 8 deletions
  1. 1 1
      api/swagger.yaml
  2. 19 3
      builder/builder-next/builder.go
  3. 3 4
      daemon/prune.go

+ 1 - 1
api/swagger.yaml

@@ -8226,7 +8226,7 @@ paths:
 
             Available filters:
 
-            - `until=<duration>`: duration relative to daemon's time, during which build cache was not used, in Go's duration format (e.g., '24h')
+            - `until=<timestamp>` remove cache older than `<timestamp>`. The `<timestamp>` can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. `10m`, `1h30m`) computed relative to the daemon's local time.
             - `id=<id>`
             - `parent=<id>`
             - `type=<string>`

+ 19 - 3
builder/builder-next/builder.go

@@ -14,6 +14,7 @@ import (
 	"github.com/containerd/containerd/remotes/docker"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types/backend"
+	timetypes "github.com/docker/docker/api/types/time"
 	"github.com/docker/docker/builder"
 	mobyexporter "github.com/docker/docker/builder/builder-next/exporter"
 	"github.com/docker/docker/builder/builder-next/exporter/overrides"
@@ -53,6 +54,12 @@ func (e errConflictFilter) Error() string {
 
 func (errConflictFilter) InvalidParameter() {}
 
+type errInvalidFilterValue struct {
+	error
+}
+
+func (errInvalidFilterValue) InvalidParameter() {}
+
 var cacheFields = map[string]bool{
 	"id":          true,
 	"parent":      true,
@@ -626,11 +633,20 @@ func toBuildkitPruneInfo(opts types.BuildCachePruneOptions) (client.PruneInfo, e
 	case 0:
 		// nothing to do
 	case 1:
-		var err error
-		until, err = time.ParseDuration(untilValues[0])
+		ts, err := timetypes.GetTimestamp(untilValues[0], time.Now())
+		if err != nil {
+			return client.PruneInfo{}, errInvalidFilterValue{
+				errors.Wrapf(err, "%q filter expects a duration (e.g., '24h') or a timestamp", filterKey),
+			}
+		}
+		seconds, nanoseconds, err := timetypes.ParseTimestamps(ts, 0)
 		if err != nil {
-			return client.PruneInfo{}, errors.Wrapf(err, "%q filter expects a duration (e.g., '24h')", filterKey)
+			return client.PruneInfo{}, errInvalidFilterValue{
+				errors.Wrapf(err, "failed to parse timestamp %q", ts),
+			}
 		}
+
+		until = time.Since(time.Unix(seconds, nanoseconds))
 	default:
 		return client.PruneInfo{}, errMultipleFilterValues{}
 	}

+ 3 - 4
daemon/prune.go

@@ -2,7 +2,6 @@ package daemon // import "github.com/docker/docker/daemon"
 
 import (
 	"context"
-	"fmt"
 	"regexp"
 	"strconv"
 	"sync/atomic"
@@ -230,15 +229,15 @@ func getUntilFromPruneFilters(pruneFilters filters.Args) (time.Time, error) {
 	}
 	untilFilters := pruneFilters.Get("until")
 	if len(untilFilters) > 1 {
-		return until, fmt.Errorf("more than one until filter specified")
+		return until, errdefs.InvalidParameter(errors.New("more than one until filter specified"))
 	}
 	ts, err := timetypes.GetTimestamp(untilFilters[0], time.Now())
 	if err != nil {
-		return until, err
+		return until, errdefs.InvalidParameter(err)
 	}
 	seconds, nanoseconds, err := timetypes.ParseTimestamps(ts, 0)
 	if err != nil {
-		return until, err
+		return until, errdefs.InvalidParameter(err)
 	}
 	until = time.Unix(seconds, nanoseconds)
 	return until, nil