Wire UpdatePodSandboxResources to Sandbox API

Integrates CRI container resource updates with core Sandbox API plugin.
Delegates payload to out-of-tree controllers via UpdateSandbox API.
Gracefully tolerates ErrNotImplemented to preserve backwards
compatibility for legacy sandboxers.

Assisted-by: Antigravity
Signed-off-by: Chris Henzie <chrishenzie@gmail.com>
This commit is contained in:
Chris Henzie committed 2026-03-24 15:50:49 -07:00
1 parent e6c7f37235
commit 33db836a8b
5 files changed
+92

No files matched your search

+8
View File
@@ -110,6 +110,14 @@ func (c *criSandboxService) ShutdownSandbox(ctx context.Context, sandboxer strin
return ctrl.Shutdown(ctx, sandboxID)
}
func (c *criSandboxService) UpdateSandbox(ctx context.Context, sandboxer string, sandboxID string, sandbox sandbox.Sandbox, fields ...string) error {
ctrl, err := c.SandboxController(sandboxer)
if err != nil {
return err
}
return ctrl.Update(ctx, sandboxID, sandbox, fields...)
}
func (c *criSandboxService) StopSandbox(ctx context.Context, sandboxer, sandboxID string, opts ...sandbox.StopOpt) error {
ctrl, err := c.SandboxController(sandboxer)
if err != nil {
@@ -25,6 +25,7 @@ import (
"github.com/containerd/containerd/v2/internal/cri/server/podsandbox"
sstore "github.com/containerd/containerd/v2/internal/cri/store/sandbox"
"github.com/containerd/containerd/v2/pkg/tracing"
"github.com/containerd/errdefs"
"github.com/containerd/log"
)
@@ -75,6 +76,14 @@ func (c *criService) UpdatePodSandboxResources(ctx context.Context, r *runtime.U
return nil, fmt.Errorf("failed to update sandbox %s in core store: %w", sandbox.ID, err)
}
if err := c.sandboxService.UpdateSandbox(ctx, sandboxInfo.Sandboxer, sandboxInfo.ID, sandboxInfo, "extensions"); err != nil {
// Tolerate these errors for older sandbox controllers that may not support this yet.
if !errdefs.IsNotImplemented(err) {
return nil, fmt.Errorf("failed to update sandbox controller: %w", err)
}
log.G(ctx).Tracef("sandbox controller %q does not implement Update endpoint", sandboxInfo.Sandboxer)
}
err = c.nri.PostUpdatePodSandboxResources(ctx, &sandbox)
if err != nil {
log.G(ctx).WithError(err).Errorf("NRI post-update notification failed")
@@ -53,6 +53,17 @@ func (f *fakeSandboxStore) Update(_ context.Context, sb sandbox.Sandbox, _ ...st
return sb, nil
}
type recordSandboxService struct {
fakeSandboxService
calledID string
returnErr error
}
func (s *recordSandboxService) UpdateSandbox(_ context.Context, _ string, sandboxID string, _ sandbox.Sandbox, _ ...string) error {
s.calledID = sandboxID
return s.returnErr
}
func TestUpdatePodSandboxResources(t *testing.T) {
mySandbox := sstore.Metadata{
ID: "test-sandbox-id",
@@ -150,4 +161,63 @@ func TestUpdatePodSandboxResources(t *testing.T) {
assert.Equal(t, int64(100), updatedRes.Overhead.MemoryLimitInBytes)
assert.Equal(t, int64(200), updatedRes.Resources.CpuQuota)
})
t.Run("success fallback when sandbox controller does not implement update", func(t *testing.T) {
recordService := &recordSandboxService{returnErr: errdefs.ErrNotImplemented}
c := newTestCRIService(func(service *criService) {
service.sandboxService = recordService
client, _ := containerd.New("", containerd.WithServices(containerd.WithSandboxStore(&fakeSandboxStore{})))
service.client = client
})
s := sstore.NewSandbox(mySandbox, sstore.Status{})
c.sandboxStore.Add(s)
req := &runtime.UpdatePodSandboxResourcesRequest{
PodSandboxId: "test-sandbox-id",
}
_, err := c.UpdatePodSandboxResources(context.Background(), req)
require.NoError(t, err)
assert.Equal(t, "test-sandbox-id", recordService.calledID)
})
t.Run("success when sandbox controller implements update", func(t *testing.T) {
recordService := &recordSandboxService{returnErr: nil}
c := newTestCRIService(func(service *criService) {
service.sandboxService = recordService
client, _ := containerd.New("", containerd.WithServices(containerd.WithSandboxStore(&fakeSandboxStore{})))
service.client = client
})
s := sstore.NewSandbox(mySandbox, sstore.Status{})
c.sandboxStore.Add(s)
req := &runtime.UpdatePodSandboxResourcesRequest{
PodSandboxId: "test-sandbox-id",
}
_, err := c.UpdatePodSandboxResources(context.Background(), req)
require.NoError(t, err)
assert.Equal(t, "test-sandbox-id", recordService.calledID)
})
t.Run("fails when sandbox controller update fails", func(t *testing.T) {
recordService := &recordSandboxService{returnErr: errdefs.ErrInvalidArgument}
c := newTestCRIService(func(service *criService) {
service.sandboxService = recordService
client, _ := containerd.New("", containerd.WithServices(containerd.WithSandboxStore(&fakeSandboxStore{})))
service.client = client
})
s := sstore.NewSandbox(mySandbox, sstore.Status{})
c.sandboxStore.Add(s)
req := &runtime.UpdatePodSandboxResourcesRequest{
PodSandboxId: "test-sandbox-id",
}
_, err := c.UpdatePodSandboxResources(context.Background(), req)
require.Error(t, err)
assert.Contains(t, err.Error(), errdefs.ErrInvalidArgument.Error())
})
}
+1
View File
@@ -78,6 +78,7 @@ type sandboxService interface {
CreateSandbox(ctx context.Context, info sandbox.Sandbox, opts ...sandbox.CreateOpt) error
StartSandbox(ctx context.Context, sandboxer string, sandboxID string) (sandbox.ControllerInstance, error)
WaitSandbox(ctx context.Context, sandboxer string, sandboxID string) (<-chan containerd.ExitStatus, error)
UpdateSandbox(ctx context.Context, sandboxer string, sandboxID string, sandbox sandbox.Sandbox, fields ...string) error
StopSandbox(ctx context.Context, sandboxer, sandboxID string, opts ...sandbox.StopOpt) error
ShutdownSandbox(ctx context.Context, sandboxer string, sandboxID string) error
SandboxStatus(ctx context.Context, sandboxer string, sandboxID string, verbose bool) (sandbox.ControllerStatus, error)
+4
View File
@@ -47,6 +47,10 @@ func (f *fakeSandboxService) StartSandbox(ctx context.Context, sandboxer string,
return sandbox.ControllerInstance{}, errdefs.ErrNotImplemented
}
func (f *fakeSandboxService) UpdateSandbox(ctx context.Context, sandboxer string, sandboxID string, sandbox sandbox.Sandbox, fields ...string) error {
return errdefs.ErrNotImplemented
}
func (f *fakeSandboxService) StopSandbox(ctx context.Context, sandboxer, sandboxID string, opts ...sandbox.StopOpt) error {
return errdefs.ErrNotImplemented
}