diff --git a/builder/builder-next/controller.go b/builder/builder-next/controller.go index 158bf69ef1..17d200d6b7 100644 --- a/builder/builder-next/controller.go +++ b/builder/builder-next/controller.go @@ -444,7 +444,7 @@ func newGraphDriverController(ctx context.Context, rt http.RoundTripper, opt Opt func getGCPolicy(conf config.BuilderConfig, root string) ([]client.PruneInfo, error) { var gcPolicy []client.PruneInfo - if conf.GC.Enabled { + if conf.GC.IsEnabled() { if conf.GC.Policy == nil { reservedSpace, maxUsedSpace, minFreeSpace, err := parseGCPolicy(config.BuilderGCRule{ ReservedSpace: conf.GC.DefaultReservedSpace, diff --git a/daemon/config/builder.go b/daemon/config/builder.go index 457f89efc3..22cdd48f4c 100644 --- a/daemon/config/builder.go +++ b/daemon/config/builder.go @@ -84,13 +84,17 @@ func (x *BuilderGCFilter) UnmarshalJSON(data []byte) error { // BuilderGCConfig contains GC config for a buildkit builder type BuilderGCConfig struct { - Enabled bool `json:",omitempty"` + Enabled *bool `json:",omitempty"` Policy []BuilderGCRule `json:",omitempty"` DefaultReservedSpace string `json:",omitempty"` DefaultMaxUsedSpace string `json:",omitempty"` DefaultMinFreeSpace string `json:",omitempty"` } +func (x *BuilderGCConfig) IsEnabled() bool { + return x.Enabled == nil || *x.Enabled +} + func (x *BuilderGCConfig) UnmarshalJSON(data []byte) error { var xx struct { Enabled bool `json:",omitempty"` @@ -103,11 +107,14 @@ func (x *BuilderGCConfig) UnmarshalJSON(data []byte) error { DefaultKeepStorage string `json:",omitempty"` } + // Set defaults. + xx.Enabled = true + if err := json.Unmarshal(data, &xx); err != nil { return err } - x.Enabled = xx.Enabled + x.Enabled = &xx.Enabled x.Policy = xx.Policy x.DefaultReservedSpace = xx.DefaultReservedSpace x.DefaultMaxUsedSpace = xx.DefaultMaxUsedSpace diff --git a/daemon/config/builder_test.go b/daemon/config/builder_test.go index 14b33e8802..3acc463063 100644 --- a/daemon/config/builder_test.go +++ b/daemon/config/builder_test.go @@ -28,7 +28,7 @@ func TestBuilderGC(t *testing.T) { cfg, err := MergeDaemonConfigurations(&Config{}, nil, configFile) assert.NilError(t, err) - assert.Assert(t, cfg.Builder.GC.Enabled) + assert.Assert(t, cfg.Builder.GC.IsEnabled()) f1 := filters.NewArgs() f1.Add("unused-for", "2200h") f2 := filters.NewArgs() @@ -61,7 +61,7 @@ func TestBuilderGC_DeprecatedKeepStorage(t *testing.T) { cfg, err := MergeDaemonConfigurations(&Config{}, nil, configFile) assert.NilError(t, err) - assert.Assert(t, cfg.Builder.GC.Enabled) + assert.Assert(t, cfg.Builder.GC.IsEnabled()) f1 := filters.NewArgs() f1.Add("unused-for", "2200h") f2 := filters.NewArgs() @@ -89,3 +89,28 @@ func TestBuilderGCFilterUnmarshal(t *testing.T) { }} assert.DeepEqual(t, cfg.Policy, expectedPolicy, cmp.AllowUnexported(BuilderGCFilter{})) } + +func TestBuilderGC_Enabled(t *testing.T) { + tests := []struct { + doc, config string + expected bool + }{ + {doc: "empty config", config: ``, expected: true}, + {doc: "empty json", config: `{}`, expected: true}, + {doc: "empty builder", config: `{"builder": {}}`, expected: true}, + {doc: "empty gc", config: `{"builder": {"gc": {}}}`, expected: true}, + {doc: "gc enabled", config: `{"builder": {"gc": {"enabled": true}}}`, expected: true}, + {doc: "gc disabled", config: `{"builder": {"gc": {"enabled": false}}}`, expected: false}, + {doc: "gc with policy", config: `{"builder": {"gc": {"policy": []}}}`, expected: true}, + } + for _, tc := range tests { + t.Run(tc.doc, func(t *testing.T) { + tempFile := fs.NewFile(t, "config", fs.WithContent(tc.config)) + configFile := tempFile.Path() + + cfg, err := MergeDaemonConfigurations(&Config{}, nil, configFile) + assert.NilError(t, err) + assert.Equal(t, cfg.Builder.GC.IsEnabled(), tc.expected) + }) + } +}