Skip to content

fix(api): bound OptimizationJob random search seed to the sampler range - #4248

Merged
google-oss-prow[bot] merged 4 commits into
kubeflow:masterfrom
rshdhere:fix-optimizationjob-seed-bounds
Oct 21, 2026
Merged

google-oss-prow[bot] merged 4 commits into
kubeflow:masterfrom
rshdhere:fix-optimizationjob-seed-bounds

Conversation

@rshdhere

@rshdhere rshdhere commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor
  • Add Minimum=0 and Maximum=4294967295 to RandomAlgorithm.Seed in optimizationjob_types.go
  • Out-of-range seeds were admitted and forwarded as random_state to the Optuna suggestion service, whose RandomSampler raises "Seed must be between 0 and 2**32 - 1"
  • The service never caches the failed sampler, so every reconcile retried GetSuggestions and the OptimizationJob stalled with no trials and no Failed condition
  • Regenerate the CRD manifests, Helm chart CRD, OpenAPI spec, apply configuration and Python API model
  • Add an integration test that checks the API server accepts nil, 0 and 4294967295 and rejects -1 and 4294967296

What this PR does / why we need it:
spec.searchAlgorithm.random.seed accepted any int64, but the Optuna random sampler in the suggestion service only accepts seeds in [0, 2^32-1]. An out-of-range seed made every GetSuggestions call fail, so the OptimizationJob stalled with no trials and no Failed condition. This adds Minimum/Maximum validation to the seed so the API server rejects it at creation, regenerates the API artifacts, and adds an integration test for the boundary values.

Which issue(s) this PR fixes:
Fixes #4247

Checklist:

  • Docs included if any changes are user facing

- Add Minimum=0 and Maximum=4294967295 to RandomAlgorithm.Seed in optimizationjob_types.go
- Out-of-range seeds were admitted and forwarded as random_state to the Optuna suggestion service, whose RandomSampler raises "Seed must be between 0 and 2**32 - 1"
- The service never caches the failed sampler, so every reconcile retried GetSuggestions and the OptimizationJob stalled with no trials and no Failed condition
- Regenerate the CRD manifests, Helm chart CRD, OpenAPI spec, apply configuration and Python API model
- Add an integration test that checks the API server accepts nil, 0 and 4294967295 and rejects -1 and 4294967296

Signed-off-by: raashed <mohammedraashed10@gmail.com>
// RandomAlgorithm is the random search algorithm.
type RandomAlgorithm struct {
// seed is the seed for the random search algorithm.
// It must be between 0 and 4294967295, the range accepted by the Optuna random sampler.

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.

could we not mention about algorithm being used in the api spec

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.

Good point.

I've removed the sampler mention so it now just states the accepted range, and regenerated the manifests/OpenAPI/Python model. Thanks!

@@ -0,0 +1,92 @@
/*

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.

please rename the fine to optimizationjob_test.go so it can be reused for other webhook tests

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.

Makes sense, renamed it to optimizationjob_test.go. Just a heads-up: #4062 also adds a file with that name, so whichever lands second will need a quick rebase to merge the two. Happy to handle that on my side if this one goes in later.

- Remove the mention of the underlying random sampler from the RandomAlgorithm.Seed API doc, keeping only the accepted range
- Regenerate the CRD manifests, Helm chart CRD, OpenAPI spec, apply configuration and Python API model
- Rename optimizationjob_seed_test.go to optimizationjob_test.go so other OptimizationJob webhook tests can live in the same file

Signed-off-by: raashed <mohammedraashed10@gmail.com>
@andreyvelich

Copy link
Copy Markdown
Member

/ok-to-test

@andreyvelich andreyvelich left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks @rshdhere for the fix! This review was done with the help of AI tools.

"github.com/kubeflow/trainer/v2/test/integration/framework"
)

var _ = ginkgo.Describe("OptimizationJob random search seed validation", ginkgo.Ordered, func() {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Since this file will host other OptimizationJob webhook tests, use a generic suite name matching trainjob_test.go:

Suggested change
var _ = ginkgo.Describe("OptimizationJob random search seed validation", ginkgo.Ordered, func() {
var _ = ginkgo.Describe("OptimizationJob Webhook", ginkgo.Ordered, func() {

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.

Done in ace3938. Renamed it to OptimizationJob webhook to match trainjob_test.go.

ginkgo.BeforeEach(func() {
ns = &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "optimizationjob-seed-",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Same here, align with trainjob-webhook-:

Suggested change
GenerateName: "optimizationjob-seed-",
GenerateName: "optimizationjob-webhook-",

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.

Done in ace3938 as well. The prefix is now optimizationjob-webhook-, matching trainjob-webhook-.

…tionJob webhook tests

- Rename the Describe block to "OptimizationJob Webhook" to match trainjob_test.go, since the file will host other OptimizationJob webhook tests
- Use the optimizationjob-webhook- namespace prefix to align with trainjob-webhook-

Signed-off-by: raashed <mohammedraashed10@gmail.com>
@rshdhere

Copy link
Copy Markdown
Contributor Author

Thanks for the review @andreyvelich!
I've applied both suggestions in ace3938. Let me know if anything else needs changing.

Comment on lines +57 to +58
ginkgo.DescribeTable("validates the random search seed at admission",
func(seed *int64, errorMatcher gomega.OmegaMatcher) {

@andreyvelich andreyvelich Oct 21, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you accept OptimizationJob as input, like we do for TrainJob validation tests: https://github.com/rshdhere/trainer/blob/ace3938e61767a58c207a483a5e7e20c63887347/test/integration/webhooks/trainjob_test.go#L91
So we can add the rest of the tests in the followup PRs.

Suggested change
ginkgo.DescribeTable("validates the random search seed at admission",
func(seed *int64, errorMatcher gomega.OmegaMatcher) {
ginkgo.DescribeTable("Validate OptimizationJob on creation", func(optimizationJob func() *trainer.OptimizationJob, errorMatcher gomega.OmegaMatcher) {
gomega.Expect(k8sClient.Create(ctx, optimizationJob())).Should(errorMatcher)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You can update the MakeOptimizationJobWrapper to set default values for Objectives, SearchAlgorithm, Parameters, and TrainJobTemplate

…ests

- Default Objectives, SearchAlgorithm, Parameters and TrainJobTemplate in MakeOptimizationJobWrapper to a minimal valid random search, so tests only override the fields they exercise
- Make the OptimizationJob webhook table take a func() *trainer.OptimizationJob, matching the TrainJob validation tests, so future entries can vary any field

Signed-off-by: raashed <mohammedraashed10@gmail.com>
@rshdhere

Copy link
Copy Markdown
Contributor Author

done in cb96c3f. MakeOptimizationJobWrapper now defaults Objectives, SearchAlgorithm, Parameters and TrainJobTemplate to a minimal valid random search. The table now takes func() *trainer.OptimizationJob, the same as the TrainJob validation tests, so each entry only overrides the field it tests.

@andreyvelich andreyvelich left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks @rshdhere!
/lgtm
/approve

@google-oss-prow

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: andreyvelich

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@google-oss-prow
google-oss-prow Bot merged commit 3e2e15d into kubeflow:master Oct 21, 2026
30 checks passed
@google-oss-prow google-oss-prow Bot added this to the v2.4 milestone Oct 21, 2026
@github-project-automation github-project-automation Bot moved this from Needs Triage to Done in Kubeflow Trainer Oct 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

OptimizationJob: random search seed outside [0, 2^32-1] stalls the job instead of being rejected

3 participants