From 0f54c47401a460e558d002660a4a2e3aba395af9 Mon Sep 17 00:00:00 2001 From: "rongfu.leng" <1275177125@qq.com> Date: Fri, 30 Sep 2022 00:32:50 +0800 Subject: [PATCH] feat add sandbox api status func Signed-off-by: rongfu.leng --- pkg/cri/sbserver/podsandbox/controller.go | 27 ++++++++++++-- .../sbserver/podsandbox/controller_test.go | 37 +++++++++++++++++++ pkg/cri/sbserver/podsandbox/sandbox_stop.go | 3 +- pkg/cri/store/sandbox/status.go | 4 ++ 4 files changed, 66 insertions(+), 5 deletions(-) diff --git a/pkg/cri/sbserver/podsandbox/controller.go b/pkg/cri/sbserver/podsandbox/controller.go index decc59f7f..0ba2a9131 100644 --- a/pkg/cri/sbserver/podsandbox/controller.go +++ b/pkg/cri/sbserver/podsandbox/controller.go @@ -22,6 +22,7 @@ import ( "time" "github.com/containerd/containerd" + eventtypes "github.com/containerd/containerd/api/events" api "github.com/containerd/containerd/api/services/sandbox/v1" "github.com/containerd/containerd/errdefs" "github.com/containerd/containerd/oci" @@ -84,8 +85,23 @@ func New( var _ sandbox.Controller = (*Controller)(nil) func (c *Controller) Status(ctx context.Context, sandboxID string) (*api.ControllerStatusResponse, error) { - //TODO implement me - panic("implement me") + sandbox, err := c.sandboxStore.Get(sandboxID) + if err != nil { + return nil, fmt.Errorf("an error occurred while trying to find sandbox %q: %w", + sandboxID, err) + } + status := sandbox.Status.Get() + resp := &api.ControllerStatusResponse{ + ID: sandboxID, + Pid: status.Pid, + State: status.State.String(), + ExitStatus: status.ExitStatus, + Extra: nil, + } + if !status.ExitedAt.IsZero() { + resp.ExitedAt = protobuf.ToTimestamp(status.ExitedAt) + } + return resp, nil } func (c *Controller) Wait(ctx context.Context, sandboxID string) (*api.ControllerWaitResponse, error) { @@ -123,7 +139,7 @@ func (c *Controller) waitSandboxExit(ctx context.Context, id string, exitCh <-ch sb, err := c.sandboxStore.Get(id) if err == nil { - if err := handleSandboxExit(dctx, sb); err != nil { + if err := handleSandboxExit(dctx, sb, &eventtypes.TaskExit{ExitStatus: exitStatus, ExitedAt: protobuf.ToTimestamp(exitedAt)}); err != nil { return err } return nil @@ -144,7 +160,8 @@ func (c *Controller) waitSandboxExit(ctx context.Context, id string, exitCh <-ch } // handleSandboxExit handles TaskExit event for sandbox. -func handleSandboxExit(ctx context.Context, sb sandboxstore.Sandbox) error { +// TODO https://github.com/containerd/containerd/issues/7548 +func handleSandboxExit(ctx context.Context, sb sandboxstore.Sandbox, e *eventtypes.TaskExit) error { // No stream attached to sandbox container. task, err := sb.Container.Task(ctx, nil) if err != nil { @@ -163,6 +180,8 @@ func handleSandboxExit(ctx context.Context, sb sandboxstore.Sandbox) error { sb.Status.Update(func(status sandboxstore.Status) (sandboxstore.Status, error) { status.State = sandboxstore.StateNotReady status.Pid = 0 + status.ExitStatus = e.ExitStatus + status.ExitedAt = e.ExitedAt.AsTime() return status, nil }) // Using channel to propagate the information of sandbox stop diff --git a/pkg/cri/sbserver/podsandbox/controller_test.go b/pkg/cri/sbserver/podsandbox/controller_test.go index 6dc68fe30..aeb76490c 100644 --- a/pkg/cri/sbserver/podsandbox/controller_test.go +++ b/pkg/cri/sbserver/podsandbox/controller_test.go @@ -17,10 +17,16 @@ package podsandbox import ( + "context" + "testing" + "time" + criconfig "github.com/containerd/containerd/pkg/cri/config" "github.com/containerd/containerd/pkg/cri/store/label" sandboxstore "github.com/containerd/containerd/pkg/cri/store/sandbox" ostesting "github.com/containerd/containerd/pkg/os/testing" + "github.com/containerd/containerd/protobuf" + "github.com/stretchr/testify/assert" ) const ( @@ -50,3 +56,34 @@ func newControllerService() *Controller { sandboxStore: sandboxstore.NewStore(labels), } } + +func Test_Status(t *testing.T) { + sandboxID, pid, exitStatus := "1", uint32(1), uint32(0) + createdAt, exitedAt := time.Now(), time.Now() + controller := newControllerService() + status := sandboxstore.Status{ + Pid: pid, + CreatedAt: createdAt, + ExitStatus: exitStatus, + ExitedAt: exitedAt, + State: sandboxstore.StateReady, + } + sb := sandboxstore.Sandbox{ + Metadata: sandboxstore.Metadata{ + ID: sandboxID, + }, + Status: sandboxstore.StoreStatus(status), + } + err := controller.sandboxStore.Add(sb) + if err != nil { + t.Fatal(err) + } + s, err := controller.Status(context.Background(), sandboxID) + if err != nil { + t.Fatal(err) + } + assert.Equal(t, s.Pid, pid) + assert.Equal(t, s.ExitStatus, exitStatus) + assert.Equal(t, s.ExitedAt, protobuf.ToTimestamp(exitedAt)) + assert.Equal(t, s.State, sandboxstore.StateReady.String()) +} diff --git a/pkg/cri/sbserver/podsandbox/sandbox_stop.go b/pkg/cri/sbserver/podsandbox/sandbox_stop.go index 5173431ba..656b410b2 100644 --- a/pkg/cri/sbserver/podsandbox/sandbox_stop.go +++ b/pkg/cri/sbserver/podsandbox/sandbox_stop.go @@ -20,6 +20,7 @@ import ( "context" "fmt" "syscall" + "time" eventtypes "github.com/containerd/containerd/api/events" api "github.com/containerd/containerd/api/services/sandbox/v1" @@ -134,5 +135,5 @@ func (c *Controller) waitSandboxStop(ctx context.Context, sandbox sandboxstore.S // cleanupUnknownSandbox cleanup stopped sandbox in unknown state. func cleanupUnknownSandbox(ctx context.Context, id string, sandbox sandboxstore.Sandbox) error { // Reuse handleSandboxExit to do the cleanup. - return handleSandboxExit(ctx, sandbox) + return handleSandboxExit(ctx, sandbox, &eventtypes.TaskExit{ExitStatus: unknownExitCode, ExitedAt: protobuf.ToTimestamp(time.Now())}) } diff --git a/pkg/cri/store/sandbox/status.go b/pkg/cri/store/sandbox/status.go index dff96ccc0..bbdf3b4e2 100644 --- a/pkg/cri/store/sandbox/status.go +++ b/pkg/cri/store/sandbox/status.go @@ -99,6 +99,10 @@ type Status struct { Pid uint32 // CreatedAt is the created timestamp. CreatedAt time.Time + // ExitedAt is the stop timestamp + ExitedAt time.Time + // ExitStatus is the stop sandbox status + ExitStatus uint32 // State is the state of the sandbox. State State }