Skip to content

sandbox: forward Create fields, fix event topics#13260

Merged
estesp merged 1 commit into
containerd:mainfrom
willmyrs:main
Apr 22, 2026
Merged

sandbox: forward Create fields, fix event topics#13260
estesp merged 1 commit into
containerd:mainfrom
willmyrs:main

Conversation

@willmyrs

@willmyrs willmyrs commented Apr 20, 2026

Copy link
Copy Markdown
Contributor

sandbox: forward Create fields, fix event topics

What

Fixes two bugs in the gRPC sandbox controller service and adds unit tests for the service.

Bug 1: Create silently dropped fields

The controllerService.Create method only forwarded the options field when calling the local controller. The netns_path, rootfs, and annotations fields from the gRPC request were silently discarded, causing clients using the gRPC proxy path to receive incomplete sandbox configurations.

All four CreateOptions fields are now forwarded:

err = ctrl.Create(ctx, sb,
    sandbox.WithOptions(req.GetOptions()),
    sandbox.WithNetNSPath(req.GetNetnsPath()),
    sandbox.WithRootFS(mount.FromProto(req.GetRootfs())),
    sandbox.WithAnnotations(req.GetAnnotations()),
)

Bug 2: Event topics missing leading /

Event topics were published as "sandboxes/create" instead of "/sandboxes/create". The event exchange validates that topics start with /, so every Publish call returned an error to the caller. Fixed for three event-publishing methods: Create, Start, and Wait.

Testing

Added controller_service_test.go with unit tests exercising the happy path for all implemented RPC methods, field forwarding for Create, and error handling for invalid/unknown sandboxer names.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes two issues in the sandbox gRPC controller service: it now forwards all Create request fields to the underlying controller and publishes events with valid, leading-/ topics. It also adds unit tests for the controller service’s RPC methods.

Changes:

  • Forward netns_path, rootfs, and annotations (in addition to options) from ControllerCreateRequest into sandbox.Controller.Create.
  • Fix event publish topics to include the required leading / for Create, Start, and Wait.
  • Add unit tests covering the happy path for most RPC methods plus Create field-forwarding and invalid/unknown sandboxer handling.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
plugins/services/sandbox/controller_service.go Fix Create option forwarding and correct event topic strings to satisfy exchange topic validation.
plugins/services/sandbox/controller_service_test.go Add unit tests for controller service behavior, including Create forwarding and sandboxer error cases.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread plugins/services/sandbox/controller_service_test.go
@willmyrs
willmyrs marked this pull request as ready for review April 21, 2026 15:00
@dosubot dosubot Bot added the kind/bug label Apr 21, 2026
Copilot AI review requested due to automatic review settings April 22, 2026 17:54

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (1)

plugins/services/sandbox/controller_service.go:145

  • When req.Sandbox is provided, sb (and sb.ID) comes from sandbox.FromProto(req.Sandbox), but the event and response IDs are taken from req.GetSandboxID(). If a client sets only sandbox.sandbox_id (or the two IDs diverge), the controller may create one ID while the response/event report another (possibly empty). Consider deriving a single effective ID (validate equality when both are set) and use that consistently for ctrl.Create, event publishing, and the response.
	var sb sandbox.Sandbox
	if req.Sandbox != nil {
		sb = sandbox.FromProto(req.Sandbox)
	} else {
		sb = sandbox.Sandbox{ID: req.GetSandboxID()}
	}
	err = ctrl.Create(ctx, sb,
		sandbox.WithOptions(req.GetOptions()),
		sandbox.WithNetNSPath(req.GetNetnsPath()),
		sandbox.WithRootFS(mount.FromProto(req.GetRootfs())),
		sandbox.WithAnnotations(req.GetAnnotations()),
	)
	if err != nil {
		return &api.ControllerCreateResponse{}, errgrpc.ToGRPC(err)
	}

	if err := s.publisher.Publish(ctx, "/sandboxes/create", &eventtypes.SandboxCreate{
		SandboxID: req.GetSandboxID(),
	}); err != nil {
		return &api.ControllerCreateResponse{}, errgrpc.ToGRPC(err)
	}

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +209 to +217
resp, err := svc.Create(nsCtx(), &api.ControllerCreateRequest{
SandboxID: "sb-1",
Sandboxer: "test",
NetnsPath: "/var/run/netns/test",
Rootfs: []*apitypes.Mount{
{Type: "overlay", Source: "src", Options: []string{"ro"}},
},
Annotations: map[string]string{"io.containerd.netns": "/var/run/netns/test"},
})

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ControllerCreateRequest.Options is omitted in this test, but controllerService.Create always applies sandbox.WithOptions(req.GetOptions()). When Options is nil, WithOptions will fail to marshal and Create will return an error, so this "happy path" test will fail (or pass/fail for the wrong reason depending on future changes). Set Options (e.g., an empty anypb.Any{}) in the request, or update controllerService.Create to skip WithOptions when req.GetOptions() is nil.

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is inaccurate; test currently passes with this as nil. The current behavior accurately reflects how the methods are used, i.e. the Options field is optional on the request.

Comment on lines +231 to +239
_, err := svc.Create(nsCtx(), &api.ControllerCreateRequest{
SandboxID: "sb-2",
Sandboxer: "test",
Sandbox: &apitypes.Sandbox{
SandboxID: "sb-2",
Runtime: &apitypes.Sandbox_Runtime{Name: "test-runtime"},
Labels: map[string]string{"key": "val"},
},
})

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This Create request also omits Options, but controllerService.Create unconditionally calls sandbox.WithOptions(req.GetOptions()). With a nil Options, WithOptions will error during marshaling and the test won’t actually cover the intended "Sandbox proto" behavior. Provide a non-nil Options in the request (or change the service to treat nil options as "not provided").

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above comment.


_, err := svc.Create(nsCtx(), &api.ControllerCreateRequest{
SandboxID: "sb-3",
Sandboxer: "test",

Copilot AI Apr 22, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test aims to verify controller errors are propagated, but since the request doesn’t set Options, the call can fail earlier inside sandbox.WithOptions(req.GetOptions()) (marshaling a nil) and never reach ctrl.createErr. Set a non-nil Options in the request so the failure you observe is definitely coming from the controller.

Suggested change
Sandboxer: "test",
Sandboxer: "test",
Options: &anypb.Any{},

Copilot uses AI. Check for mistakes.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above comment.

The gRPC sandbox controller service only forwarded the `options` field
when calling the local controller. The `netns_path`, `rootfs`, and
`annotations` fields were silently dropped, causing clients using the
gRPC proxy path to receive incomplete sandbox configurations.

Event topics were missing the leading `/` prefix ("sandboxes/create"
instead of "/sandboxes/create"), causing the event exchange to reject
the publish and return an error to the caller.

Add unit tests for the controller service that exercise all RPC
methods.

Signed-off-by: William Myers <[email protected]>
@estesp estesp moved this from Needs Triage to Needs Reviewers in Pull Request Review Apr 22, 2026
@estesp estesp added cherry-pick/2.0.x Change to be cherry picked to release/2.0 branch cherry-pick/2.1.x Change to be cherry picked to release/2.1 branch cherry-pick/2.2.x Change to be cherry picked to release/2.2 branch labels Apr 22, 2026
@estesp
estesp requested a review from mxpv April 22, 2026 20:30
@github-project-automation github-project-automation Bot moved this from Needs Reviewers to Review In Progress in Pull Request Review Apr 22, 2026
@estesp
estesp added this pull request to the merge queue Apr 22, 2026
Merged via the queue into containerd:main with commit 3bb1cc7 Apr 22, 2026
95 of 96 checks passed
@github-project-automation github-project-automation Bot moved this from Review In Progress to Done in Pull Request Review Apr 22, 2026
@estesp

estesp commented Apr 22, 2026

Copy link
Copy Markdown
Member

/cherry-pick release/2.0 release/2.1 release/2.2

@k8s-infra-cherrypick-robot

Copy link
Copy Markdown

@estesp: #13260 failed to apply on top of branch "release/2.0":

Applying: sandbox: forward Create fields, fix event topics
Using index info to reconstruct a base tree...
M	plugins/services/sandbox/controller_service.go
Falling back to patching base and 3-way merge...
Auto-merging plugins/services/sandbox/controller_service.go
CONFLICT (content): Merge conflict in plugins/services/sandbox/controller_service.go
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am --abort".
hint: Disable this message with "git config set advice.mergeConflict false"
Patch failed at 0001 sandbox: forward Create fields, fix event topics

Details

In response to this:

/cherry-pick release/2.0 release/2.1 release/2.2

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@estesp

estesp commented Apr 22, 2026

Copy link
Copy Markdown
Member

/cherry-pick release/2.1
/cherry-pick release/2.2

@k8s-infra-cherrypick-robot

Copy link
Copy Markdown

@estesp: #13260 failed to apply on top of branch "release/2.1":

Applying: sandbox: forward Create fields, fix event topics
Using index info to reconstruct a base tree...
M	plugins/services/sandbox/controller_service.go
Falling back to patching base and 3-way merge...
Auto-merging plugins/services/sandbox/controller_service.go
CONFLICT (content): Merge conflict in plugins/services/sandbox/controller_service.go
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch=diff' to see the failed patch
hint: When you have resolved this problem, run "git am --continue".
hint: If you prefer to skip this patch, run "git am --skip" instead.
hint: To restore the original branch and stop patching, run "git am --abort".
hint: Disable this message with "git config set advice.mergeConflict false"
Patch failed at 0001 sandbox: forward Create fields, fix event topics

Details

In response to this:

/cherry-pick release/2.1
/cherry-pick release/2.2

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@k8s-infra-cherrypick-robot

Copy link
Copy Markdown

@estesp: new pull request created: #13266

Details

In response to this:

/cherry-pick release/2.1
/cherry-pick release/2.2

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@estesp estesp added cherry-picked/2.2.x PR commits are cherry-picked into release/2.2 branch and removed cherry-pick/2.2.x Change to be cherry picked to release/2.2 branch labels Apr 22, 2026
@estesp estesp added cherry-picked/2.0.x PR commits are cherry picked into the release/2.0 branch cherry-picked/2.1.x PR commits are cherry picked into the release/2.1 branch and removed cherry-pick/2.0.x Change to be cherry picked to release/2.0 branch cherry-pick/2.1.x Change to be cherry picked to release/2.1 branch labels Apr 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cherry-picked/2.0.x PR commits are cherry picked into the release/2.0 branch cherry-picked/2.1.x PR commits are cherry picked into the release/2.1 branch cherry-picked/2.2.x PR commits are cherry-picked into release/2.2 branch kind/bug size/L

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

6 participants