Skip to content

Commit 36f9236

Browse files
authored
Merge pull request containerd#4326 from jedevc/name-filter-regexp
feat: allow regexp name filters to match docker
2 parents c46f1f4 + 27c2572 commit 36f9236

File tree

7 files changed

+106
-20
lines changed

7 files changed

+106
-20
lines changed

.golangci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ linters:
126126
# 222 occurrences. Could indicate failure to handle broken conditions.
127127
disabled: true
128128
- name: cognitive-complexity
129-
arguments: [197]
129+
arguments: [205]
130130
# 441 occurrences (at default 7). We should try to lower it (involves significant refactoring).
131131

132132
##### P2: nice to have.

cmd/nerdctl/container/container_list_linux_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,42 @@ func TestContainerListWithFilter(t *testing.T) {
304304
return nil
305305
})
306306

307+
// should support regexp
308+
base.Cmd("ps", "--filter", "name=.*"+testContainerA.name+".*").AssertOutWithFunc(func(stdout string) error {
309+
lines := strings.Split(strings.TrimSpace(stdout), "\n")
310+
if len(lines) < 2 {
311+
return fmt.Errorf("expected at least 2 lines, got %d", len(lines))
312+
}
313+
314+
tab := tabutil.NewReader("CONTAINER ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS\tNAMES")
315+
err := tab.ParseHeader(lines[0])
316+
if err != nil {
317+
return fmt.Errorf("failed to parse header: %v", err)
318+
}
319+
320+
containerName, _ := tab.ReadRow(lines[1], "NAMES")
321+
assert.Equal(t, containerName, testContainerA.name)
322+
return nil
323+
})
324+
325+
// fully anchored regexp
326+
base.Cmd("ps", "--filter", "name=^"+testContainerA.name+"$").AssertOutWithFunc(func(stdout string) error {
327+
lines := strings.Split(strings.TrimSpace(stdout), "\n")
328+
if len(lines) < 2 {
329+
return fmt.Errorf("expected at least 2 lines, got %d", len(lines))
330+
}
331+
332+
tab := tabutil.NewReader("CONTAINER ID\tIMAGE\tCOMMAND\tCREATED\tSTATUS\tPORTS\tNAMES")
333+
err := tab.ParseHeader(lines[0])
334+
if err != nil {
335+
return fmt.Errorf("failed to parse header: %v", err)
336+
}
337+
338+
containerName, _ := tab.ReadRow(lines[1], "NAMES")
339+
assert.Equal(t, containerName, testContainerA.name)
340+
return nil
341+
})
342+
307343
base.Cmd("ps", "-q", "--filter", "name="+testContainerA.name+testContainerA.name).AssertOutWithFunc(func(stdout string) error {
308344
lines := strings.Split(strings.TrimSpace(stdout), "\n")
309345
if len(lines) > 0 {

cmd/nerdctl/network/network_list_linux_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,28 @@ func TestNetworkLsFilter(t *testing.T) {
8181
data.Labels().Get("netID2")[:12]: {},
8282
}
8383

84+
for _, name := range lines {
85+
_, ok := netNames[name]
86+
assert.Assert(t, ok, info)
87+
}
88+
},
89+
}
90+
},
91+
},
92+
{
93+
Description: "filter name regexp",
94+
Command: func(data test.Data, helpers test.Helpers) test.TestableCommand {
95+
return helpers.Command("network", "ls", "--quiet", "--filter", "name=.*"+data.Labels().Get("net2")+".*")
96+
},
97+
Expected: func(data test.Data, helpers test.Helpers) *test.Expected {
98+
return &test.Expected{
99+
Output: func(stdout string, info string, t *testing.T) {
100+
var lines = strings.Split(strings.TrimSpace(stdout), "\n")
101+
assert.Assert(t, len(lines) >= 1, info)
102+
netNames := map[string]struct{}{
103+
data.Labels().Get("netID2")[:12]: {},
104+
}
105+
84106
for _, name := range lines {
85107
_, ok := netNames[name]
86108
assert.Assert(t, ok, info)

cmd/nerdctl/volume/volume_list_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,27 @@ func TestVolumeLsFilter(t *testing.T) {
280280
}
281281
},
282282
},
283+
{
284+
Description: "Retrieving name=.*volume1.*",
285+
Command: func(data test.Data, helpers test.Helpers) test.TestableCommand {
286+
return helpers.Command("volume", "ls", "--quiet", "--filter", "name=.*"+data.Labels().Get("vol1")+".*")
287+
},
288+
Expected: func(data test.Data, helpers test.Helpers) *test.Expected {
289+
return &test.Expected{
290+
Output: func(stdout string, info string, t *testing.T) {
291+
var lines = strings.Split(strings.TrimSpace(stdout), "\n")
292+
assert.Assert(t, len(lines) >= 1, "expected at least 1 line"+info)
293+
volNames := map[string]struct{}{
294+
data.Labels().Get("vol1"): {},
295+
}
296+
for _, name := range lines {
297+
_, ok := volNames[name]
298+
assert.Assert(t, ok, fmt.Sprintf("unexpected volume %s found", name)+info)
299+
}
300+
},
301+
}
302+
},
303+
},
283304
{
284305
Description: "Retrieving name=volume1 and name=volume2",
285306
Command: func(data test.Data, helpers test.Helpers) test.TestableCommand {

pkg/cmd/container/list_util.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package container
1919
import (
2020
"context"
2121
"fmt"
22+
"regexp"
2223
"strconv"
2324
"strings"
2425
"time"
@@ -164,11 +165,15 @@ func (cl *containerFilterContext) foldIDFilter(_ context.Context, filter, value
164165
}
165166

166167
func (cl *containerFilterContext) foldNameFilter(_ context.Context, filter, value string) error {
168+
re, err := regexp.Compile(value)
169+
if err != nil {
170+
return err
171+
}
167172
cl.nameFilterFuncs = append(cl.nameFilterFuncs, func(name string) bool {
168173
if value == "" {
169174
return true
170175
}
171-
return strings.Contains(name, value)
176+
return re.MatchString(name)
172177
})
173178
return nil
174179
}

pkg/cmd/network/list.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"context"
2222
"errors"
2323
"fmt"
24+
"regexp"
2425
"strings"
2526
"text/tabwriter"
2627
"text/template"
@@ -147,21 +148,21 @@ func getNetworkFilterFuncs(filters []string) ([]func(*map[string]string) bool, [
147148

148149
for _, filter := range filters {
149150
if strings.HasPrefix(filter, "name") || strings.HasPrefix(filter, "label") {
150-
subs := strings.SplitN(filter, "=", 2)
151-
if len(subs) < 2 {
151+
filter, value, ok := strings.Cut(filter, "=")
152+
if !ok {
152153
continue
153154
}
154-
switch subs[0] {
155+
switch filter {
155156
case "name":
157+
re, err := regexp.Compile(value)
158+
if err != nil {
159+
return nil, nil, err
160+
}
156161
nameFilterFuncs = append(nameFilterFuncs, func(name string) bool {
157-
return strings.Contains(name, subs[1])
162+
return re.MatchString(name)
158163
})
159164
case "label":
160-
v, k, hasValue := "", subs[1], false
161-
if subs := strings.SplitN(subs[1], "=", 2); len(subs) == 2 {
162-
hasValue = true
163-
k, v = subs[0], subs[1]
164-
}
165+
k, v, hasValue := strings.Cut(value, "=")
165166
labelFilterFuncs = append(labelFilterFuncs, func(labels *map[string]string) bool {
166167
if labels == nil {
167168
return false

pkg/cmd/volume/list.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"bytes"
2121
"errors"
2222
"fmt"
23+
"regexp"
2324
"strconv"
2425
"strings"
2526
"text/tabwriter"
@@ -216,21 +217,21 @@ func getVolumeFilterFuncs(filters []string) ([]func(*map[string]string) bool, []
216217
}
217218
for _, filter := range filters {
218219
if strings.HasPrefix(filter, "name") || strings.HasPrefix(filter, "label") {
219-
subs := strings.SplitN(filter, "=", 2)
220-
if len(subs) < 2 {
220+
filter, value, ok := strings.Cut(filter, "=")
221+
if !ok {
221222
continue
222223
}
223-
switch subs[0] {
224+
switch filter {
224225
case "name":
226+
re, err := regexp.Compile(value)
227+
if err != nil {
228+
return nil, nil, nil, false, err
229+
}
225230
nameFilterFuncs = append(nameFilterFuncs, func(name string) bool {
226-
return strings.Contains(name, subs[1])
231+
return re.MatchString(name)
227232
})
228233
case "label":
229-
v, k, hasValue := "", subs[1], false
230-
if subs := strings.SplitN(subs[1], "=", 2); len(subs) == 2 {
231-
hasValue = true
232-
k, v = subs[0], subs[1]
233-
}
234+
k, v, hasValue := strings.Cut(value, "=")
234235
labelFilterFuncs = append(labelFilterFuncs, func(labels *map[string]string) bool {
235236
if labels == nil {
236237
return false

0 commit comments

Comments
 (0)