Browse Source

daemon/config: fix filter type in BuildKit GC config

For backwards compatibility, the old incorrect object format for
builder.GC.Rule.Filter still works but is deprecated in favor of array of
strings akin to what needs to be passed on the CLI.

Signed-off-by: Tibor Vass <tibor@docker.com>
Tibor Vass 5 năm trước cách đây
mục cha
commit
fbdd437d29

+ 2 - 1
builder/builder-next/controller.go

@@ -8,6 +8,7 @@ import (
 	"github.com/containerd/containerd/content/local"
 	"github.com/containerd/containerd/content/local"
 	"github.com/containerd/containerd/platforms"
 	"github.com/containerd/containerd/platforms"
 	"github.com/docker/docker/api/types"
 	"github.com/docker/docker/api/types"
+	"github.com/docker/docker/api/types/filters"
 	"github.com/docker/docker/builder/builder-next/adapters/containerimage"
 	"github.com/docker/docker/builder/builder-next/adapters/containerimage"
 	"github.com/docker/docker/builder/builder-next/adapters/localinlinecache"
 	"github.com/docker/docker/builder/builder-next/adapters/localinlinecache"
 	"github.com/docker/docker/builder/builder-next/adapters/snapshot"
 	"github.com/docker/docker/builder/builder-next/adapters/snapshot"
@@ -229,7 +230,7 @@ func getGCPolicy(conf config.BuilderConfig, root string) ([]client.PruneInfo, er
 				gcPolicy[i], err = toBuildkitPruneInfo(types.BuildCachePruneOptions{
 				gcPolicy[i], err = toBuildkitPruneInfo(types.BuildCachePruneOptions{
 					All:         p.All,
 					All:         p.All,
 					KeepStorage: b,
 					KeepStorage: b,
-					Filters:     p.Filter,
+					Filters:     filters.Args(p.Filter),
 				})
 				})
 				if err != nil {
 				if err != nil {
 					return nil, err
 					return nil, err

+ 30 - 4
daemon/config/builder.go

@@ -1,12 +1,38 @@
 package config
 package config
 
 
-import "github.com/docker/docker/api/types/filters"
+import (
+	"encoding/json"
+	"strings"
+
+	"github.com/docker/docker/api/types/filters"
+)
 
 
 // BuilderGCRule represents a GC rule for buildkit cache
 // BuilderGCRule represents a GC rule for buildkit cache
 type BuilderGCRule struct {
 type BuilderGCRule struct {
-	All         bool         `json:",omitempty"`
-	Filter      filters.Args `json:",omitempty"`
-	KeepStorage string       `json:",omitempty"`
+	All         bool            `json:",omitempty"`
+	Filter      BuilderGCFilter `json:",omitempty"`
+	KeepStorage string          `json:",omitempty"`
+}
+
+type BuilderGCFilter filters.Args
+
+func (x *BuilderGCFilter) UnmarshalJSON(data []byte) error {
+	var arr []string
+	f := filters.NewArgs()
+	if err := json.Unmarshal(data, &arr); err != nil {
+		// backwards compat for deprecated buggy form
+		err := json.Unmarshal(data, &f)
+		*x = BuilderGCFilter(f)
+		return err
+	}
+	for _, s := range arr {
+		fields := strings.SplitN(s, "=", 2)
+		name := strings.ToLower(strings.TrimSpace(fields[0]))
+		value := strings.TrimSpace(fields[1])
+		f.Add(name, value)
+	}
+	*x = BuilderGCFilter(f)
+	return nil
 }
 }
 
 
 // BuilderGCConfig contains GC config for a buildkit builder
 // BuilderGCConfig contains GC config for a buildkit builder

+ 44 - 0
daemon/config/builder_test.go

@@ -0,0 +1,44 @@
+package config
+
+import (
+	"testing"
+
+	"github.com/docker/docker/api/types/filters"
+	"github.com/google/go-cmp/cmp"
+	"gotest.tools/assert"
+	"gotest.tools/fs"
+)
+
+func TestBuilderGC(t *testing.T) {
+	tempFile := fs.NewFile(t, "config", fs.WithContent(`{
+  "builder": {
+    "gc": {
+      "enabled": true,
+      "policy": [
+        {"keepStorage": "10GB", "filter": ["unused-for=2200h"]},
+        {"keepStorage": "50GB", "filter": {"unused-for": {"3300h": true}}},
+        {"keepStorage": "100GB", "all": true}
+      ]
+    }
+  }
+}`))
+	defer tempFile.Remove()
+	configFile := tempFile.Path()
+
+	cfg, err := MergeDaemonConfigurations(&Config{}, nil, configFile)
+	assert.NilError(t, err)
+	assert.Assert(t, cfg.Builder.GC.Enabled)
+	f1 := filters.NewArgs()
+	f1.Add("unused-for", "2200h")
+	f2 := filters.NewArgs()
+	f2.Add("unused-for", "3300h")
+	expectedPolicy := []BuilderGCRule{
+		{KeepStorage: "10GB", Filter: BuilderGCFilter(f1)},
+		{KeepStorage: "50GB", Filter: BuilderGCFilter(f2)}, /* parsed from deprecated form */
+		{KeepStorage: "100GB", All: true},
+	}
+	assert.DeepEqual(t, cfg.Builder.GC.Policy, expectedPolicy, cmp.AllowUnexported(BuilderGCFilter{}))
+	// double check to please the skeptics
+	assert.Assert(t, filters.Args(cfg.Builder.GC.Policy[0].Filter).UniqueExactMatch("unused-for", "2200h"))
+	assert.Assert(t, filters.Args(cfg.Builder.GC.Policy[1].Filter).UniqueExactMatch("unused-for", "3300h"))
+}