Skip to content

Commit fd9b2ca

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

14 files changed

+251
-40
lines changed

Diff for: pkg/buildah/common.go

+3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515

1616
"github.com/werf/common-go/pkg/util"
1717
"github.com/werf/werf/v2/pkg/buildah/thirdparty"
18+
"github.com/werf/werf/v2/pkg/container_backend/filter"
1819
"github.com/werf/werf/v2/pkg/container_backend/info"
1920
"github.com/werf/werf/v2/pkg/image"
2021
"github.com/werf/werf/v2/pkg/werf"
@@ -102,6 +103,8 @@ type CommitOpts struct {
102103

103104
type PruneImagesOptions struct {
104105
CommonOpts
106+
107+
Filters filter.FilterList
105108
}
106109

107110
type PruneImagesReport struct {

Diff for: pkg/buildah/native_linux.go

+19-4
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,12 @@ import (
4141
"github.com/containers/storage/pkg/unshare"
4242
"github.com/moby/buildkit/frontend/dockerfile/instructions"
4343
"github.com/opencontainers/runtime-spec/specs-go"
44+
"github.com/samber/lo"
4445
"github.com/sirupsen/logrus"
4546

47+
"github.com/werf/common-go/pkg/util"
4648
"github.com/werf/werf/v2/pkg/buildah/thirdparty"
49+
"github.com/werf/werf/v2/pkg/container_backend/filter"
4750
"github.com/werf/werf/v2/pkg/container_backend/info"
4851
"github.com/werf/werf/v2/pkg/image"
4952
"github.com/werf/werf/v2/pkg/ssh_agent"
@@ -605,9 +608,14 @@ func (b *NativeBuildah) PruneImages(ctx context.Context, opts PruneImagesOptions
605608
return PruneImagesReport{}, err
606609
}
607610

611+
// ensure dangling=true
612+
filters := opts.Filters
613+
filters.Remove(filter.DanglingFalse)
614+
filters.Add(filter.DanglingTrue)
615+
608616
imageReports, rmiErrors := runtime.RemoveImages(ctx, []string{}, &libimage.RemoveImagesOptions{
609617
Force: false, // not remove containers
610-
Filters: []string{"dangling=true"},
618+
Filters: mapBackendOldFiltersToBuildahImageFilters(filters.ToPairs()),
611619
WithSize: true,
612620
NoPrune: false,
613621
})
@@ -898,10 +906,10 @@ func (b *NativeBuildah) Images(ctx context.Context, opts ImagesOptions) (image.I
898906
return nil, err
899907
}
900908

901-
listOpts := &libimage.ListImagesOptions{}
902-
for _, filter := range opts.Filters {
903-
listOpts.Filters = append(listOpts.Filters, fmt.Sprintf("%s=%s", filter.First, filter.Second))
909+
listOpts := &libimage.ListImagesOptions{
910+
Filters: mapBackendOldFiltersToBuildahImageFilters(opts.Filters),
904911
}
912+
905913
images, err := runtime.ListImages(ctx, opts.Names, listOpts)
906914
if err != nil {
907915
return nil, err
@@ -938,6 +946,13 @@ func (b *NativeBuildah) Images(ctx context.Context, opts ImagesOptions) (image.I
938946
return res, nil
939947
}
940948

949+
// mapBackendOldFiltersToBuildahImageFilters returns filters in key=value format
950+
func mapBackendOldFiltersToBuildahImageFilters(filters []util.Pair[string, string]) []string {
951+
return lo.Map(filters, func(pair util.Pair[string, string], _ int) string {
952+
return fmt.Sprintf("%s=%s", pair.First, pair.Second)
953+
})
954+
}
955+
941956
func (b *NativeBuildah) Containers(ctx context.Context, opts ContainersOptions) (image.ContainerList, error) {
942957
builders, err := buildah.OpenAllBuilders(b.Store)
943958
if err != nil {

Diff for: pkg/buildah/native_linux_test.go

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package buildah
2+
3+
import (
4+
. "github.com/onsi/ginkgo/v2"
5+
. "github.com/onsi/gomega"
6+
7+
"github.com/werf/common-go/pkg/util"
8+
)
9+
10+
var _ = Describe("buildah", func() {
11+
DescribeTable("mapBackendOldFiltersToBuildahImageFilters",
12+
func(oldFilters []util.Pair[string, string], expectedFilters []string) {
13+
actual := mapBackendOldFiltersToBuildahImageFilters(oldFilters)
14+
Expect(actual).To(Equal(expectedFilters))
15+
},
16+
Entry(
17+
"should work with empty input",
18+
[]util.Pair[string, string]{},
19+
[]string{},
20+
),
21+
Entry(
22+
"should work with non-empty input",
23+
[]util.Pair[string, string]{
24+
util.NewPair("foo", "bar"),
25+
util.NewPair("key", "value"),
26+
},
27+
[]string{"foo=bar", "key=value"},
28+
),
29+
)
30+
})

Diff for: pkg/buildah/suite_test.go

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package buildah
2+
3+
import (
4+
"testing"
5+
6+
. "github.com/onsi/ginkgo/v2"
7+
. "github.com/onsi/gomega"
8+
)
9+
10+
func TestBuildah(t *testing.T) {
11+
RegisterFailHandler(Fail)
12+
RunSpecs(t, "Buildah Suite")
13+
}

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

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package filter
2+
3+
import (
4+
"github.com/werf/common-go/pkg/util"
5+
)
6+
7+
type Filter util.Pair[string, string]
8+
9+
func NewFilter(key, value string) Filter {
10+
return Filter{
11+
First: key,
12+
Second: value,
13+
}
14+
}
15+
16+
func (f *Filter) ToPair() util.Pair[string, string] {
17+
return util.NewPair(f.First, f.Second)
18+
}

Diff for: pkg/container_backend/filter/filter_list.go

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package filter
2+
3+
import (
4+
"slices"
5+
6+
"github.com/samber/lo"
7+
8+
"github.com/werf/common-go/pkg/util"
9+
)
10+
11+
type FilterList []Filter
12+
13+
func (list *FilterList) Add(filter Filter) {
14+
*list = lo.Uniq(append(*list, filter))
15+
}
16+
17+
func (list *FilterList) Remove(filter Filter) {
18+
*list = slices.DeleteFunc(*list, func(f Filter) bool {
19+
return f == filter
20+
})
21+
}
22+
23+
func (list *FilterList) ToPairs() []util.Pair[string, string] {
24+
return lo.Map(*list, func(f Filter, _ int) util.Pair[string, string] {
25+
return f.ToPair()
26+
})
27+
}

Diff for: pkg/container_backend/filter/filter_list_test.go

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package filter_test
2+
3+
import (
4+
. "github.com/onsi/ginkgo/v2"
5+
. "github.com/onsi/gomega"
6+
7+
"github.com/werf/werf/v2/pkg/container_backend/filter"
8+
)
9+
10+
var _ = Describe("FilterList", func() {
11+
DescribeTable("Add",
12+
func(list filter.FilterList, item filter.Filter, expectedList filter.FilterList) {
13+
list.Add(item)
14+
Expect(list).To(Equal(expectedList))
15+
},
16+
Entry(
17+
"should modify list in place",
18+
filter.FilterList{},
19+
filter.NewFilter("foo", "bar"),
20+
filter.FilterList{
21+
filter.NewFilter("foo", "bar"),
22+
},
23+
),
24+
Entry(
25+
"should prevent duplication",
26+
filter.FilterList{
27+
filter.NewFilter("foo", "bar"),
28+
},
29+
filter.NewFilter("foo", "bar"),
30+
filter.FilterList{
31+
filter.NewFilter("foo", "bar"),
32+
},
33+
),
34+
)
35+
36+
DescribeTable("Remove",
37+
func(list filter.FilterList, item filter.Filter, expectedList filter.FilterList) {
38+
list.Remove(item)
39+
Expect(list).To(Equal(expectedList))
40+
},
41+
Entry(
42+
"should not modify list if item not found",
43+
filter.FilterList{
44+
filter.NewFilter("foo", "bar"),
45+
},
46+
filter.NewFilter("foo", "1"),
47+
filter.FilterList{
48+
filter.NewFilter("foo", "bar"),
49+
},
50+
),
51+
Entry(
52+
"should remove item from the list if found",
53+
filter.FilterList{
54+
filter.NewFilter("foo", "bar"),
55+
},
56+
filter.NewFilter("foo", "bar"),
57+
filter.FilterList{},
58+
),
59+
)
60+
})

Diff for: pkg/container_backend/filter/image.go

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package filter
2+
3+
var (
4+
DanglingTrue = NewFilter("dangling", "true")
5+
DanglingFalse = NewFilter("dangling", "false")
6+
)

Diff for: pkg/container_backend/filter/suite_test.go

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package filter
2+
3+
import (
4+
"testing"
5+
6+
. "github.com/onsi/ginkgo/v2"
7+
. "github.com/onsi/gomega"
8+
)
9+
10+
func TestFilter(t *testing.T) {
11+
RegisterFailHandler(Fail)
12+
RunSpecs(t, "Filter Suite")
13+
}

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

+4-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
package prune
22

3-
import "github.com/werf/common-go/pkg/util"
3+
import (
4+
"github.com/werf/werf/v2/pkg/container_backend/filter"
5+
)
46

57
type Options struct {
6-
Filters []util.Pair[string, string]
8+
Filters filter.FilterList
79
}
810

911
type Report struct {

Diff for: pkg/docker/image.go

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

23-
"github.com/werf/common-go/pkg/util"
2423
"github.com/werf/logboek"
24+
"github.com/werf/werf/v2/pkg/container_backend/filter"
2525
"github.com/werf/werf/v2/pkg/container_backend/prune"
2626
)
2727

@@ -78,7 +78,7 @@ type (
7878
// ImagesPrune containers using opts.Filters.
7979
// List of accepted filters is there https://github.com/moby/moby/blob/25.0/daemon/containerd/image_prune.go#L22
8080
func ImagesPrune(ctx context.Context, opts ImagesPruneOptions) (ImagesPruneReport, error) {
81-
report, err := apiCli(ctx).ImagesPrune(ctx, mapImagesPruneOptionsToImagesPruneFilters(opts))
81+
report, err := apiCli(ctx).ImagesPrune(ctx, mapBackendFiltersToImagesPruneFilters(opts.Filters))
8282
if err != nil {
8383
return ImagesPruneReport{}, err
8484
}
@@ -91,9 +91,9 @@ func ImagesPrune(ctx context.Context, opts ImagesPruneOptions) (ImagesPruneRepor
9191
}, err
9292
}
9393

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)
94+
func mapBackendFiltersToImagesPruneFilters(list filter.FilterList) filters.Args {
95+
args := lo.Map(list, func(filter filter.Filter, _ int) filters.KeyValuePair {
96+
return filters.Arg(filter.First, filter.Second)
9797
})
9898
return filters.NewArgs(args...)
9999
}

Diff for: pkg/docker/image_test.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ import (
55
. "github.com/onsi/ginkgo/v2"
66
. "github.com/onsi/gomega"
77

8-
"github.com/werf/common-go/pkg/util"
8+
"github.com/werf/werf/v2/pkg/container_backend/filter"
99
)
1010

1111
var _ = Describe("docker images", func() {
12-
DescribeTable("mapImagesPruneOptionsToImagesPruneFilters",
12+
DescribeTable("mapBackendFiltersToImagesPruneFilters",
1313
func(opts ImagesPruneOptions, expected filters.Args) {
14-
actual := mapImagesPruneOptionsToImagesPruneFilters(opts)
14+
actual := mapBackendFiltersToImagesPruneFilters(opts.Filters)
1515
Expect(actual).To(Equal(expected))
1616
},
1717
Entry(
@@ -21,8 +21,8 @@ var _ = Describe("docker images", func() {
2121
),
2222
Entry("should work with 'label' filter",
2323
ImagesPruneOptions{
24-
Filters: []util.Pair[string, string]{
25-
util.NewPair("label", "foo=bar"),
24+
Filters: filter.FilterList{
25+
filter.NewFilter("label", "foo=bar"),
2626
},
2727
},
2828
filters.NewArgs(

0 commit comments

Comments
 (0)