From 0a9c83ed7ea3a2f8b1f2f77a3c5a32cc5251ffb4 Mon Sep 17 00:00:00 2001 From: Mujib Ahasan Date: Wed, 24 Jun 2026 00:49:50 +0530 Subject: [PATCH 1/3] feature: lebel-based filtering added Signed-off-by: Mujib Ahasan --- pkg/cmd/system/events.go | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/pkg/cmd/system/events.go b/pkg/cmd/system/events.go index a544f071b57..2897b00ab94 100644 --- a/pkg/cmd/system/events.go +++ b/pkg/cmd/system/events.go @@ -44,6 +44,7 @@ type EventOut struct { Topic string Status Status Event string + Labels map[string]string } type Status string @@ -90,6 +91,20 @@ func generateEventFilter(filter, filterValue string) (func(e *EventOut) bool, er return strings.EqualFold(string(e.Status), filterValue) }, nil + case "LABEL": + return func(e *EventOut) bool { + if len(e.Labels) == 0 { + return false + } + + parts := strings.SplitN(filterValue, "=", 2) + if len(parts) == 1 { + _, ok := e.Labels[parts[0]] + return ok + } + + return e.Labels[parts[0]] == parts[1] + }, nil } return nil, fmt.Errorf("%s is an invalid or unsupported filter", filter) @@ -175,6 +190,7 @@ func Events(ctx context.Context, client *containerd.Client, options types.System if e != nil { var out []byte var id string + labels := map[string]string{} if e.Event != nil { v, err := typeurl.UnmarshalAny(e.Event) if err != nil { @@ -197,8 +213,13 @@ func Events(ctx context.Context, client *containerd.Client, options types.System id = data["container_id"].(string) } } - - eOut := EventOut{e.Timestamp, id, e.Namespace, e.Topic, TopicToStatus(e.Topic), string(out)} + if id != "" { + container, err := client.ContainerService().Get(ctx, id) + if err == nil { + labels = container.Labels + } + } + eOut := EventOut{e.Timestamp, id, e.Namespace, e.Topic, TopicToStatus(e.Topic), string(out), labels} match := applyFilters(&eOut, filterMap) if match { if tmpl != nil { From e5e45974a6c691ca7a8148fb2a348b9cb01536e1 Mon Sep 17 00:00:00 2001 From: Mujib Ahasan Date: Thu, 25 Jun 2026 15:54:38 +0530 Subject: [PATCH 2/3] test case added Signed-off-by: Mujib Ahasan --- .../system/system_events_linux_test.go | 42 +++++++++++++++++++ pkg/cmd/system/events.go | 3 +- 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/cmd/nerdctl/system/system_events_linux_test.go b/cmd/nerdctl/system/system_events_linux_test.go index 431abdafb0b..79acb2a8b1c 100644 --- a/cmd/nerdctl/system/system_events_linux_test.go +++ b/cmd/nerdctl/system/system_events_linux_test.go @@ -38,6 +38,18 @@ func testEventFilterExecutor(data test.Data, helpers test.Helpers) test.Testable return cmd } +func testEventLabelFilterExecutor(data test.Data, helpers test.Helpers) test.TestableCommand { + helpers.Ensure("pull", testutil.CommonImage) + + cmd := helpers.Command("events", "--filter", data.Labels().Get("filter"), "--format", "json") + cmd.WithTimeout(10 * time.Second) + cmd.Background() + + helpers.Ensure("run", "--rm", "--label", data.Labels().Get("containerLabel"), testutil.CommonImage) + + return cmd +} + func TestEventFilters(t *testing.T) { testCase := nerdtest.Setup() @@ -115,6 +127,36 @@ func TestEventFilters(t *testing.T) { "output": "\"Status\":\"unknown\"", }), }, + { + Description: "LabelFilter", + Command: testEventLabelFilterExecutor, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: expect.ExitCodeTimeout, + Output: expect.Contains(data.Labels().Get("output")), + } + }, + Data: test.WithLabels(map[string]string{ + "filter": "label=com.example.app=myapp", + "containerLabel": "com.example.app=myapp", + "output": "\"Status\":\"start\"", + }), + }, + { + Description: "LabelKeyOnlyFilter", + Command: testEventLabelFilterExecutor, + Expected: func(data test.Data, helpers test.Helpers) *test.Expected { + return &test.Expected{ + ExitCode: expect.ExitCodeTimeout, + Output: expect.Contains(data.Labels().Get("output")), + } + }, + Data: test.WithLabels(map[string]string{ + "filter": "label=com.example.app", + "containerLabel": "com.example.app=myapp", + "output": "\"Status\":\"start\"", + }), + }, } testCase.Run(t) diff --git a/pkg/cmd/system/events.go b/pkg/cmd/system/events.go index 2897b00ab94..76bdd3c5de7 100644 --- a/pkg/cmd/system/events.go +++ b/pkg/cmd/system/events.go @@ -214,8 +214,7 @@ func Events(ctx context.Context, client *containerd.Client, options types.System } } if id != "" { - container, err := client.ContainerService().Get(ctx, id) - if err == nil { + if container, err := client.ContainerService().Get(ctx, id); err == nil { labels = container.Labels } } From beb85a4b35650e1676042589772c36fd253e0076 Mon Sep 17 00:00:00 2001 From: Mujib Ahasan Date: Sat, 27 Jun 2026 01:53:44 +0530 Subject: [PATCH 3/3] events: log errors when retrieving container labels Signed-off-by: Mujib Ahasan --- pkg/cmd/system/events.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/cmd/system/events.go b/pkg/cmd/system/events.go index 76bdd3c5de7..66882d31eae 100644 --- a/pkg/cmd/system/events.go +++ b/pkg/cmd/system/events.go @@ -214,7 +214,9 @@ func Events(ctx context.Context, client *containerd.Client, options types.System } } if id != "" { - if container, err := client.ContainerService().Get(ctx, id); err == nil { + if container, err := client.ContainerService().Get(ctx, id); err != nil { + log.G(ctx).WithError(err).WithField("containerID", id).Debug("failed to retrieve container labels") + } else { labels = container.Labels } }