Skip to content

Commit c0d3413

Browse files
authored
fix(host-cleanup): don't prune dangling werf images for some time (Docker) (#6752)
Signed-off-by: Alexandr Zaytsev <alexandr.zaytsev@flant.com>
1 parent 9b43ad0 commit c0d3413

File tree

5 files changed

+67
-6
lines changed

5 files changed

+67
-6
lines changed

Diff for: pkg/container_backend/prune/prune.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package prune
22

3-
type Options struct{}
3+
import "github.com/werf/common-go/pkg/util"
4+
5+
type Options struct {
6+
Filters []util.Pair[string, string]
7+
}
48

59
type Report struct {
610
ItemsDeleted []string

Diff for: pkg/docker/image.go

+12-2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"github.com/spf13/cobra"
2121
"golang.org/x/net/context"
2222

23+
"github.com/werf/common-go/pkg/util"
2324
"github.com/werf/logboek"
2425
"github.com/werf/werf/v2/pkg/container_backend/prune"
2526
)
@@ -74,8 +75,10 @@ type (
7475
ImagesPruneReport prune.Report
7576
)
7677

77-
func ImagesPrune(ctx context.Context, _ ImagesPruneOptions) (ImagesPruneReport, error) {
78-
report, err := apiCli(ctx).ImagesPrune(ctx, filters.NewArgs())
78+
// ImagesPrune containers using opts.Filters.
79+
// List of accepted filters is there https://github.com/moby/moby/blob/25.0/daemon/containerd/image_prune.go#L22
80+
func ImagesPrune(ctx context.Context, opts ImagesPruneOptions) (ImagesPruneReport, error) {
81+
report, err := apiCli(ctx).ImagesPrune(ctx, mapImagesPruneOptionsToImagesPruneFilters(opts))
7982
if err != nil {
8083
return ImagesPruneReport{}, err
8184
}
@@ -88,6 +91,13 @@ func ImagesPrune(ctx context.Context, _ ImagesPruneOptions) (ImagesPruneReport,
8891
}, err
8992
}
9093

94+
func mapImagesPruneOptionsToImagesPruneFilters(opts ImagesPruneOptions) filters.Args {
95+
args := lo.Map(opts.Filters, func(pair util.Pair[string, string], _ int) filters.KeyValuePair {
96+
return filters.Arg(pair.First, pair.Second)
97+
})
98+
return filters.NewArgs(args...)
99+
}
100+
91101
func doCliPull(c command.Cli, args ...string) error {
92102
return prepareCliCmd(image.NewPullCommand(c), args...).Execute()
93103
}

Diff for: pkg/docker/image_test.go

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package docker
2+
3+
import (
4+
"github.com/docker/docker/api/types/filters"
5+
. "github.com/onsi/ginkgo/v2"
6+
. "github.com/onsi/gomega"
7+
8+
"github.com/werf/common-go/pkg/util"
9+
)
10+
11+
var _ = Describe("docker images", func() {
12+
DescribeTable("mapImagesPruneOptionsToImagesPruneFilters",
13+
func(opts ImagesPruneOptions, expected filters.Args) {
14+
actual := mapImagesPruneOptionsToImagesPruneFilters(opts)
15+
Expect(actual).To(Equal(expected))
16+
},
17+
Entry(
18+
"should work with empty filters",
19+
ImagesPruneOptions{},
20+
filters.NewArgs(),
21+
),
22+
Entry("should work with 'label' filter",
23+
ImagesPruneOptions{
24+
Filters: []util.Pair[string, string]{
25+
util.NewPair("label", "foo=bar"),
26+
},
27+
},
28+
filters.NewArgs(
29+
filters.Arg("label", "foo=bar"),
30+
),
31+
),
32+
)
33+
})

Diff for: pkg/host_cleaning/local_backend_cleaner.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -492,7 +492,13 @@ func (cleaner *LocalBackendCleaner) pruneImages(ctx context.Context, options Run
492492
return mapImageListToCleanupReport(list), nil
493493
}
494494

495-
report, err := cleaner.backend.PruneImages(ctx, prune.Options{})
495+
report, err := cleaner.backend.PruneImages(ctx, prune.Options{
496+
// werf relies on a "dangling" image for some time before tagging its image.
497+
// Guard dangling images for "werf build" with Stapel.
498+
Filters: []util.Pair[string, string]{
499+
util.NewPair("label!", image.WerfLabel),
500+
},
501+
})
496502
return mapPruneReportToCleanupReport(report), err
497503
}
498504

Diff for: pkg/host_cleaning/local_backend_cleaner_test.go

+10-2
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,11 @@ var _ = Describe("LocalBackendCleaner", func() {
125125
Expect(report).To(Equal(newCleanupReport()))
126126
})
127127
It("should call backend.PruneImages() if opts.DryRun=false", func() {
128-
backend.EXPECT().PruneImages(ctx, prune.Options{}).Return(prune.Report{}, nil)
128+
imagesFilters := []util.Pair[string, string]{
129+
util.NewPair("label!", image.WerfLabel),
130+
}
131+
132+
backend.EXPECT().PruneImages(ctx, prune.Options{Filters: imagesFilters}).Return(prune.Report{}, nil)
129133

130134
report, err := cleaner.pruneImages(ctx, RunGCOptions{})
131135
Expect(err).To(Succeed())
@@ -322,12 +326,16 @@ var _ = Describe("LocalBackendCleaner", func() {
322326
{ID: "one", RepoDigests: []string{"digest one"}},
323327
}
324328

329+
imagesFilters := []util.Pair[string, string]{
330+
util.NewPair("label!", image.WerfLabel),
331+
}
332+
325333
// keep orders of backend calls
326334
gomock.InOrder(
327335
// use backend native GC pruning
328336
backend.EXPECT().PruneContainers(ctx, prune.Options{}).Return(prune.Report{}, nil),
329337
backend.EXPECT().PruneVolumes(ctx, prune.Options{}).Return(prune.Report{}, nil),
330-
backend.EXPECT().PruneImages(ctx, prune.Options{}).Return(prune.Report{}, nil),
338+
backend.EXPECT().PruneImages(ctx, prune.Options{Filters: imagesFilters}).Return(prune.Report{}, nil),
331339

332340
// list and remove werf containers
333341
backend.EXPECT().Containers(ctx, buildContainersOptions(

0 commit comments

Comments
 (0)