Skip to content

fix: reject nodeSelector on sandbox agents instead of silently dropping it - #2348

Open
younsl wants to merge 3 commits into
kagent-dev:mainfrom
younsl:fix/sandbox-nodeselector-reject
Open

fix: reject nodeSelector on sandbox agents instead of silently dropping it#2348
younsl wants to merge 3 commits into
kagent-dev:mainfrom
younsl:fix/sandbox-nodeselector-reject

Conversation

@younsl

@younsl younsl commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #2306

For sandbox agents, a configured deployment.nodeSelector was silently dropped: the translator resolves it into the shared PodTemplateSpec, but the substrate backend builds its ActorTemplateSpec only from the kagent container and worker pool and never reads podTemplate.Spec.NodeSelector. The sandbox workload could therefore be scheduled onto an unintended node with no signal that the config was ignored.

ActorTemplateSpec has no node-placement field at all — substrate schedules actors onto WorkerPool workers, and node placement is governed by the WorkerPool's own nodeSelector. So a per-agent selector cannot be honored by mapping it through; the issue's second suggested option (explicit rejection) is implemented instead:

  • ValidateSubstrateSandboxAgentSpec now rejects a non-empty deployment.nodeSelector (declarative and BYO) with an error pointing at the WorkerPool's nodeSelector as the supported alternative.
  • Since this validation runs in the HTTP handler, the reconciler, and the compiler, the misconfiguration surfaces at creation time and in the agent's status conditions instead of being silently discarded.

Notes for reviewers

  • The global --default-agent-node-selector flag is intentionally not rejected here: it is not part of the agent spec, and hard-failing every sandbox agent in clusters that set a global default would be a breaking regression. The sandbox backend simply does not consume it (placement is the WorkerPool's job).
  • tolerations/affinity are also silently ignored by the sandbox backend today; left out of scope to keep this PR focused on the reported bug — can follow up if maintainers want the same treatment.

Testing

  • Added table-driven cases to TestValidateSubstrateSandboxAgentSpec: declarative selector rejected, BYO selector rejected, empty selector map still allowed.
  • go test ./... in go/api, plus go/core controller/translator/sandboxbackend packages — pass.
  • make -C go lint — 0 issues.

…ng it

Substrate ActorTemplates carry no node placement (actors are scheduled
onto WorkerPool workers), so a per-agent deployment.nodeSelector on a
SandboxAgent was silently discarded by the sandbox backend and the
workload could land on an unintended node.

Reject the configuration in ValidateSubstrateSandboxAgentSpec so the
API server, reconciler, and compiler all surface an explicit error
pointing at the WorkerPool's nodeSelector as the supported alternative.

Fixes kagent-dev#2306

Signed-off-by: younsl <cysl@kakao.com>
@younsl
younsl requested a review from a team as a code owner July 28, 2026 10:08
@github-actions github-actions Bot added the bug Something isn't working label Jul 28, 2026

@EItanya EItanya 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.

What about using CEL to reject the whole deployment spec on SandboxAgent

@younsl
younsl force-pushed the fix/sandbox-nodeselector-reject branch from 11176e1 to 8f60459 Compare July 28, 2026 14:26
Per review feedback, reject deployment.nodeSelector on SandboxAgent via
CEL XValidation rules on SandboxAgentSpec so the API server rejects the
config at admission instead of the controller discovering it at
reconcile time. Covers both declarative and BYO deployments; an empty
map is still accepted, matching the Go check.

The Go-side ValidateSubstrateSandboxAgentSpec check is kept (mirroring
the existing spec.skills pattern) for objects created before the rules
shipped and callers that bypass the API server.

Adds an envtest-backed CEL test pinning the rules against the shipped
CRD YAML.

Signed-off-by: younsl <cysl@kakao.com>
@younsl
younsl force-pushed the fix/sandbox-nodeselector-reject branch from 8f60459 to cfa8906 Compare July 28, 2026 14:27
@younsl

younsl commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

@EItanya Agreed, CEL is the right place for this. Done in cfa8906.

I scoped the CEL rules to deployment.nodeSelector instead of rejecting the whole deployment spec. BYO agents require deployment.image and deployment.cmd, and substrate honors deployment.env when rendering ActorTemplates, so rejecting the entire block would break supported configuration.

The Go-side check is kept alongside the CEL rules, following the existing spec.skills pattern, so objects created before the rules shipped are still caught at reconcile time. Also added an envtest backed test that pins the rules against the shipped CRD YAML.

…failure

Signed-off-by: younsl <cysl@kakao.com>
@younsl

younsl commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

@EItanya CI is clean now. PTAL

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Sandbox agents silently drop configured nodeSelector (not applied to ActorTemplate)

2 participants