Skip to content

api: tighten runtime CRD validation#382

Open
googs1025 wants to merge 1 commit into
volcano-sh:mainfrom
googs1025:add-crd-validation
Open

api: tighten runtime CRD validation#382
googs1025 wants to merge 1 commit into
volcano-sh:mainfrom
googs1025:add-crd-validation

Conversation

@googs1025

Copy link
Copy Markdown
Member

Summary

  • add CRD schema/CEL validation for runtime session durations and ordering
  • validate runtime target ports and path prefixes
  • enforce non-negative CodeInterpreter warm pool size and add generated CRD schema tests

Test Plan

  • GOCACHE=/private/tmp/agentcube-go-cache make gen-crd
  • GOCACHE=/private/tmp/agentcube-go-cache go test -gcflags=all=-l ./pkg/apis/runtime/v1alpha1 ./pkg/workloadmanager -count=1

Copilot AI review requested due to automatic review settings June 10, 2026 11:59
@volcano-sh-bot

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign hzxuzhonghu for approval. For more information see the Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found 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

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

Note

Copilot was unable to run its full agentic suite in this review.

Adds/updates Kubebuilder CRD validations for runtime APIs (durations, ports, warm pool sizing, and cross-field constraints) and introduces a Go test to assert the generated CRD schemas contain the expected OpenAPI/CEL validation rules.

Changes:

  • Add Format=duration and positive-duration CEL validations for sessionTimeout / maxSessionDuration.
  • Add min/max/regex validations for ports, path prefix, and warm pool size; add cross-field sessionTimeout <= maxSessionDuration validations.
  • Add tests that load the generated CRDs and assert the schema contains the expected validation constraints.

Reviewed changes

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

Show a summary per file
File Description
pkg/apis/runtime/v1alpha1/crd_validation_test.go New tests to verify generated CRD OpenAPI schema and CEL rules.
pkg/apis/runtime/v1alpha1/codeinterpreter_types.go Adds Kubebuilder validation markers for CodeInterpreter spec fields and port fields.
pkg/apis/runtime/v1alpha1/agent_type.go Adds Kubebuilder validation markers for AgentRuntime spec duration fields and cross-field constraint.
manifests/charts/base/crds/runtime.agentcube.volcano.sh_codeinterpreters.yaml Regenerated CRD including the new schema constraints and CEL rules.
manifests/charts/base/crds/runtime.agentcube.volcano.sh_agentruntimes.yaml Regenerated CRD including the new schema constraints and CEL rules.

Comment on lines +42 to +46
name: "CodeInterpreter",
crdFile: "runtime.agentcube.volcano.sh_codeinterpreters.yaml",
ports: "ports",
rule: "!has(self.sessionTimeout) || !has(self.maxSessionDuration) || self.sessionTimeout <= self.maxSessionDuration",
},

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done

Comment on lines +49 to +51
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
specSchema := loadCRDSpecSchema(t, tt.crdFile)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done

Comment on lines +82 to +83
path := filepath.Join("..", "..", "..", "..", "manifests", "charts", "base", "crds", crdFile)
data, err := os.ReadFile(path)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request adds OpenAPI validation rules and CEL validations to the AgentRuntime and CodeInterpreter CRDs, ensuring correct port ranges, path prefixes, and session duration limits, along with a test suite to verify the generated schemas. However, the CEL validation rules contain critical bugs: comparing metav1.Duration fields (which are serialized as strings) directly using operators like <= or > results in lexicographical string comparisons or runtime type mismatch errors. To fix this, all duration fields must be explicitly wrapped in the duration() function (e.g., duration(self)) in the Go API definitions, the generated YAML manifests, and the corresponding unit tests.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread pkg/apis/runtime/v1alpha1/agent_type.go Outdated
}

// AgentRuntimeSpec describes how to create and manage agent runtime sandboxes.
// +kubebuilder:validation:XValidation:rule="self.sessionTimeout <= self.maxSessionDuration",message="sessionTimeout must be less than or equal to maxSessionDuration"

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.

high

In CEL, comparing string fields (which metav1.Duration is represented as in OpenAPI/JSON) directly using <= performs a lexicographical string comparison instead of a duration comparison. For example, "10h" <= "8h" would evaluate to true because "1" is lexicographically less than "8". To compare them correctly as durations, they must be parsed using the duration() function.

Suggested change
// +kubebuilder:validation:XValidation:rule="self.sessionTimeout <= self.maxSessionDuration",message="sessionTimeout must be less than or equal to maxSessionDuration"
// +kubebuilder:validation:XValidation:rule="duration(self.sessionTimeout) <= duration(self.maxSessionDuration)",message="sessionTimeout must be less than or equal to maxSessionDuration"

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done

Comment thread pkg/apis/runtime/v1alpha1/agent_type.go Outdated
// SessionTimeout describes the duration after which an inactive session will be terminated.
// +kubebuilder:validation:Required
// +kubebuilder:validation:Format=duration
// +kubebuilder:validation:XValidation:rule="self > duration('0s')",message="sessionTimeout must be greater than 0"

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.

high

Since self is a string representing the duration, comparing it directly with a duration object (duration('0s')) will cause a CEL type mismatch runtime error, which will reject all API requests. We must parse self using duration(self).

Suggested change
// +kubebuilder:validation:XValidation:rule="self > duration('0s')",message="sessionTimeout must be greater than 0"
// +kubebuilder:validation:XValidation:rule="duration(self) > duration('0s')",message="sessionTimeout must be greater than 0"

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done

Comment thread pkg/apis/runtime/v1alpha1/agent_type.go Outdated
// After this duration, the session will be terminated no matter active or inactive.
// +kubebuilder:validation:Required
// +kubebuilder:validation:Format=duration
// +kubebuilder:validation:XValidation:rule="self > duration('0s')",message="maxSessionDuration must be greater than 0"

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.

high

Since self is a string representing the duration, comparing it directly with a duration object (duration('0s')) will cause a CEL type mismatch runtime error, which will reject all API requests. We must parse self using duration(self).

Suggested change
// +kubebuilder:validation:XValidation:rule="self > duration('0s')",message="maxSessionDuration must be greater than 0"
// +kubebuilder:validation:XValidation:rule="duration(self) > duration('0s')",message="maxSessionDuration must be greater than 0"

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done

}

// CodeInterpreterSpec describes how to create and manage code-interpreter sandboxes.
// +kubebuilder:validation:XValidation:rule="!has(self.sessionTimeout) || !has(self.maxSessionDuration) || self.sessionTimeout <= self.maxSessionDuration",message="sessionTimeout must be less than or equal to maxSessionDuration"

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.

high

In CEL, comparing string fields (which metav1.Duration is represented as in OpenAPI/JSON) directly using <= performs a lexicographical string comparison instead of a duration comparison. To compare them correctly as durations, they must be parsed using the duration() function.

Suggested change
// +kubebuilder:validation:XValidation:rule="!has(self.sessionTimeout) || !has(self.maxSessionDuration) || self.sessionTimeout <= self.maxSessionDuration",message="sessionTimeout must be less than or equal to maxSessionDuration"
// +kubebuilder:validation:XValidation:rule="!has(self.sessionTimeout) || !has(self.maxSessionDuration) || duration(self.sessionTimeout) <= duration(self.maxSessionDuration)",message="sessionTimeout must be less than or equal to maxSessionDuration"

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done

// session will be terminated. Any sandbox that has not received requests within
// this duration is eligible for cleanup.
// +kubebuilder:validation:Format=duration
// +kubebuilder:validation:XValidation:rule="self > duration('0s')",message="sessionTimeout must be greater than 0"

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.

high

Since self is a string representing the duration, comparing it directly with a duration object (duration('0s')) will cause a CEL type mismatch runtime error, which will reject all API requests. We must parse self using duration(self).

Suggested change
// +kubebuilder:validation:XValidation:rule="self > duration('0s')",message="sessionTimeout must be greater than 0"
// +kubebuilder:validation:XValidation:rule="duration(self) > duration('0s')",message="sessionTimeout must be greater than 0"

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done

x-kubernetes-validations:
- message: sessionTimeout must be less than or equal to maxSessionDuration
rule: '!has(self.sessionTimeout) || !has(self.maxSessionDuration) ||
self.sessionTimeout <= self.maxSessionDuration'

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.

high

In CEL, comparing string fields directly using <= performs a lexicographical string comparison instead of a duration comparison. To compare them correctly as durations, they must be parsed using the duration() function.

                duration(self.sessionTimeout) <= duration(self.maxSessionDuration)'

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done

name: "AgentRuntime",
crdFile: "runtime.agentcube.volcano.sh_agentruntimes.yaml",
ports: "targetPort",
rule: "self.sessionTimeout <= self.maxSessionDuration",

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.

high

Update the expected validation rule to match the correct duration-based comparison.

Suggested change
rule: "self.sessionTimeout <= self.maxSessionDuration",
rule: "duration(self.sessionTimeout) <= duration(self.maxSessionDuration)",

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done

name: "CodeInterpreter",
crdFile: "runtime.agentcube.volcano.sh_codeinterpreters.yaml",
ports: "ports",
rule: "!has(self.sessionTimeout) || !has(self.maxSessionDuration) || self.sessionTimeout <= self.maxSessionDuration",

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.

high

Update the expected validation rule to match the correct duration-based comparison.

Suggested change
rule: "!has(self.sessionTimeout) || !has(self.maxSessionDuration) || self.sessionTimeout <= self.maxSessionDuration",
rule: "!has(self.sessionTimeout) || !has(self.maxSessionDuration) || duration(self.sessionTimeout) <= duration(self.maxSessionDuration)",

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done


sessionTimeoutSchema := nestedMap(t, specSchema, "properties", "sessionTimeout")
assertString(t, sessionTimeoutSchema, "format", "duration")
assertHasValidationRule(t, sessionTimeoutSchema, "self > duration('0s')")

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.

high

Update the expected validation rule to match the correct duration-based comparison.

Suggested change
assertHasValidationRule(t, sessionTimeoutSchema, "self > duration('0s')")
assertHasValidationRule(t, sessionTimeoutSchema, "duration(self) > duration('0s')")

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done


maxSessionDurationSchema := nestedMap(t, specSchema, "properties", "maxSessionDuration")
assertString(t, maxSessionDurationSchema, "format", "duration")
assertHasValidationRule(t, maxSessionDurationSchema, "self > duration('0s')")

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.

high

Update the expected validation rule to match the correct duration-based comparison.

Suggested change
assertHasValidationRule(t, maxSessionDurationSchema, "self > duration('0s')")
assertHasValidationRule(t, maxSessionDurationSchema, "duration(self) > duration('0s')")

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done

@googs1025 googs1025 force-pushed the add-crd-validation branch from ee6a37f to f5ec701 Compare June 10, 2026 12:03
@codecov-commenter

codecov-commenter commented Jun 10, 2026

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 57.96%. Comparing base (524e55e) to head (311d738).
⚠️ Report is 121 commits behind head on main.
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.

Additional details and impacted files
@@             Coverage Diff             @@
##             main     #382       +/-   ##
===========================================
+ Coverage   47.57%   57.96%   +10.39%     
===========================================
  Files          30       34        +4     
  Lines        2819     3181      +362     
===========================================
+ Hits         1341     1844      +503     
+ Misses       1338     1153      -185     
- Partials      140      184       +44     
Flag Coverage Δ
unittests 57.96% <ø> (+10.39%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@googs1025 googs1025 force-pushed the add-crd-validation branch from f5ec701 to c608717 Compare June 10, 2026 14:20
Copilot AI review requested due to automatic review settings June 10, 2026 14:20

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 6 out of 6 changed files in this pull request and generated 2 comments.

Comment on lines +105 to +106
return nestedMap(t, crd,
"spec", "versions", "0", "schema", "openAPIV3Schema", "properties", "spec")

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done

Comment thread pkg/apis/runtime/v1alpha1/agent_type.go Outdated
}

// AgentRuntimeSpec describes how to create and manage agent runtime sandboxes.
// +kubebuilder:validation:XValidation:rule="duration(self.sessionTimeout) <= duration(self.maxSessionDuration)",message="sessionTimeout must be less than or equal to maxSessionDuration"

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done

Signed-off-by: CYJiang <googs1025@gmail.com>
@googs1025 googs1025 force-pushed the add-crd-validation branch from c608717 to 311d738 Compare June 10, 2026 14:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants