From 79fafbac4f3021a824c44de3b04bc236f964b7a1 Mon Sep 17 00:00:00 2001 From: Sambhav Jain Date: Wed, 20 Aug 2025 12:33:03 +0000 Subject: [PATCH] feat: add LoadTaskProcess api in containerd client This commit aims to add an api to get the task process of the containerd client. We have a use case where we are trying to consume the exited containers and get their exit code however the current implementation of the cliet dosn't expose this api. The broader issue and usecase is captured here https://github.com/google/cadvisor/issues/3722. --- container/containerd/client.go | 12 ++++++++++++ container/containerd/client_test.go | 20 ++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/container/containerd/client.go b/container/containerd/client.go index 34134baf3e..86aa4ec69d 100644 --- a/container/containerd/client.go +++ b/container/containerd/client.go @@ -45,6 +45,7 @@ type client struct { type ContainerdClient interface { LoadContainer(ctx context.Context, id string) (*containers.Container, error) TaskPid(ctx context.Context, id string) (uint32, error) + LoadTaskProcess(ctx context.Context, id string) (*tasktypes.Process, error) Version(ctx context.Context) (string, error) } @@ -132,6 +133,17 @@ func (c *client) TaskPid(ctx context.Context, id string) (uint32, error) { return response.Process.Pid, nil } +func (c *client) LoadTaskProcess(ctx context.Context, id string) (*tasktypes.Process, error) { + response, err := c.taskService.Get(ctx, &tasksapi.GetRequest{ + ContainerID: id, + }) + if err != nil { + return nil, errgrpc.ToNative(err) + } + + return response.Process, nil +} + func (c *client) Version(ctx context.Context) (string, error) { response, err := c.versionService.Version(ctx, &emptypb.Empty{}) if err != nil { diff --git a/container/containerd/client_test.go b/container/containerd/client_test.go index eaaab0e44e..a4af2ee0fc 100644 --- a/container/containerd/client_test.go +++ b/container/containerd/client_test.go @@ -18,12 +18,14 @@ import ( "context" "fmt" + "github.com/containerd/containerd/api/types/task" "github.com/google/cadvisor/container/containerd/containers" ) type containerdClientMock struct { cntrs map[string]*containers.Container returnErr error + tasks map[string]*task.Process } func (c *containerdClientMock) LoadContainer(ctx context.Context, id string) (*containers.Container, error) { @@ -45,9 +47,27 @@ func (c *containerdClientMock) TaskPid(ctx context.Context, id string) (uint32, return 2389, nil } +func (c *containerdClientMock) LoadTaskProcess(ctx context.Context, id string) (*task.Process, error) { + if c.returnErr != nil { + return nil, c.returnErr + } + task, ok := c.tasks[id] + if !ok { + return nil, fmt.Errorf("unable to find task for container %q", id) + } + return task, nil +} + func mockcontainerdClient(cntrs map[string]*containers.Container, returnErr error) ContainerdClient { + tasks := make(map[string]*task.Process) + + for _, cntr := range cntrs { + tasks[cntr.ID] = &task.Process{} + } + return &containerdClientMock{ cntrs: cntrs, returnErr: returnErr, + tasks: tasks, } }