From a429c373ff0e9ba9aeab9b8581d5c369078ae4ab Mon Sep 17 00:00:00 2001 From: Mateusz Drab Date: Sun, 14 Aug 2022 09:08:45 +0100 Subject: [PATCH] feat: regex container name filtering (#1241) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Allow container name regex filtering * make regex names backwards compatible Co-authored-by: Mateusz Drab Co-authored-by: nils måsén --- pkg/filters/filters.go | 20 +++++++++++++++++--- pkg/filters/filters_test.go | 30 ++++++++++++++++++++++++++---- 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/pkg/filters/filters.go b/pkg/filters/filters.go index a283301..fa5ed2a 100644 --- a/pkg/filters/filters.go +++ b/pkg/filters/filters.go @@ -1,8 +1,10 @@ package filters import ( - t "github.com/containrrr/watchtower/pkg/types" + "regexp" "strings" + + t "github.com/containrrr/watchtower/pkg/types" ) // WatchtowerContainersFilter filters only watchtower containers @@ -19,9 +21,21 @@ func FilterByNames(names []string, baseFilter t.Filter) t.Filter { return func(c t.FilterableContainer) bool { for _, name := range names { - if (name == c.Name()) || (name == c.Name()[1:]) { + if name == c.Name() || name == c.Name()[1:] { return baseFilter(c) } + + if re, err := regexp.Compile(name); err == nil { + indices := re.FindStringIndex(c.Name()) + if indices == nil { + continue + } + start := indices[0] + end := indices[1] + if start <= 1 && end >= len(c.Name())-1 { + return baseFilter(c) + } + } } return false } @@ -95,7 +109,7 @@ func BuildFilter(names []string, enableLabel bool, scope string) (t.Filter, stri filter = FilterByNames(names, filter) if len(names) > 0 { - sb.WriteString("with name \"") + sb.WriteString("which name matches \"") for i, n := range names { sb.WriteString(n) if i < len(names)-1 { diff --git a/pkg/filters/filters_test.go b/pkg/filters/filters_test.go index c07b181..951e7ca 100644 --- a/pkg/filters/filters_test.go +++ b/pkg/filters/filters_test.go @@ -47,6 +47,28 @@ func TestFilterByNames(t *testing.T) { container.AssertExpectations(t) } +func TestFilterByNamesRegex(t *testing.T) { + names := []string{`ba(b|ll)oon`} + + filter := FilterByNames(names, NoFilter) + assert.NotNil(t, filter) + + container := new(mocks.FilterableContainer) + container.On("Name").Return("balloon") + assert.True(t, filter(container)) + container.AssertExpectations(t) + + container = new(mocks.FilterableContainer) + container.On("Name").Return("spoon") + assert.False(t, filter(container)) + container.AssertExpectations(t) + + container = new(mocks.FilterableContainer) + container.On("Name").Return("baboonious") + assert.False(t, filter(container)) + container.AssertExpectations(t) +} + func TestFilterByEnableLabel(t *testing.T) { filter := FilterByEnableLabel(NoFilter) assert.NotNil(t, filter) @@ -68,8 +90,7 @@ func TestFilterByEnableLabel(t *testing.T) { } func TestFilterByScope(t *testing.T) { - var scope string - scope = "testscope" + scope := "testscope" filter := FilterByScope(scope, NoFilter) assert.NotNil(t, filter) @@ -148,11 +169,12 @@ func TestFilterByImage(t *testing.T) { } func TestBuildFilter(t *testing.T) { - var names []string - names = append(names, "test") + names := []string{"test", "valid"} filter, desc := BuildFilter(names, false, "") assert.Contains(t, desc, "test") + assert.Contains(t, desc, "or") + assert.Contains(t, desc, "valid") container := new(mocks.FilterableContainer) container.On("Name").Return("Invalid")